pax_global_header00006660000000000000000000000064137770351500014522gustar00rootroot0000000000000052 comment=2888bf65ab5a87f22fd948fa4c1b429cea3c730c AntiMicroX-antimicrox-2888bf6/000077500000000000000000000000001377703515000162635ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/.clang-format000066400000000000000000000004511377703515000206360ustar00rootroot00000000000000BasedOnStyle: LLVM IndentWidth: 4 BreakBeforeBraces: Custom ColumnLimit: 125 IndentPPDirectives: BeforeHash BraceWrapping: AfterEnum: true AfterStruct: true AfterClass: true AfterControlStatement: true AfterFunction: true AfterUnion: true BreakConstructorInitializersBeforeComma: trueAntiMicroX-antimicrox-2888bf6/.github/000077500000000000000000000000001377703515000176235ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/.github/ISSUE_TEMPLATE/000077500000000000000000000000001377703515000220065ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000013341377703515000245010ustar00rootroot00000000000000--- name: "\U0001F41E Bug Report" about: Create a report to help us improve title: '' labels: 'bug' assignees: '' --- **Describe the bug** **To Reproduce** **Expected behavior** **Screenshots** **Configuration** Version of antimicrox: Used package: System version: **Additional context** AntiMicroX-antimicrox-2888bf6/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000012041377703515000255300ustar00rootroot00000000000000--- name: "\U0001F680 Feature Request" about: Suggest an idea for this project title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** **Describe the solution you'd like** **Describe alternatives you've considered** **Additional context** AntiMicroX-antimicrox-2888bf6/.github/ISSUE_TEMPLATE/question.md000066400000000000000000000002101377703515000241700ustar00rootroot00000000000000--- name: "\U00002753 Question" about: Ask question about app or project title: '' labels: 'question' assignees: '' --- **Question** AntiMicroX-antimicrox-2888bf6/.github/pull_request_template.md000066400000000000000000000011661377703515000245700ustar00rootroot00000000000000Closes #... ## Proposed changes - - - ---- AntiMicroX-antimicrox-2888bf6/.github/workflows/000077500000000000000000000000001377703515000216605ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/.github/workflows/code_formatting.yml000066400000000000000000000012341377703515000255470ustar00rootroot00000000000000name: Check code formatting on: pull_request jobs: test: # The type of runner that the job will run on runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Download tools run: | sudo apt-get update && sudo apt-get install clang-format-10 echo "Clang-format version" clang-format --version wget https://raw.githubusercontent.com/Sarcasm/run-clang-format/master/run-clang-format.py chmod +x ./run-clang-format.py - name: Test run: ./run-clang-format.py -r src AntiMicroX-antimicrox-2888bf6/.github/workflows/main.yml000066400000000000000000000014231377703515000233270ustar00rootroot00000000000000name: Build on: [ push, pull_request] jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: ubuntu-latest # Steps represent a sequence of tasks that will be executed as part of the job steps: - name: Install Dependencies run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 # Runs a set of commands using the runners shell - name: Build run: | ls pwd mkdir build && cd ./build cmake .. make AntiMicroX-antimicrox-2888bf6/.github/workflows/release.yml000066400000000000000000000066031377703515000240300ustar00rootroot00000000000000 name: Release_actions on: release: types: [published] jobs: #Build .deb files for debian-based systems. build_deb: # The type of runner that the job will run on runs-on: ubuntu-latest steps: - name: Install Dependencies run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - name: Build deb file id: create_deb run: | mkdir build && cd ./build cmake .. -DCPACK_GENERATOR="DEB" .. cmake --build . --target package #upload generated files to release - name: Upload binaries to release uses: AButler/upload-release-assets@v2.0 with: files: ./build/*.deb repo-token: ${{ secrets.GITHUB_TOKEN }} #Build universal and portable AppImage package. build-appimage: # Version of ubuntu building this appimage, it shouldn't be the latest verion of ubuntu to avoid breaking compatibility with older systems runs-on: ubuntu-18.04 needs: build_deb steps: - name: Install Dependencies run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext qt5-default libsdl2-2.0-0 zsync # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 # Installing antimicrox is required for appimage creator - name: Install antimicrox run: | VERSION=`cat ./CMakeLists.txt | grep "set(ANTIMICROX_" | grep _VERSION | cut -d " " -f 2 | cut -d ")" -f 1` MAJOR=`echo $VERSION | cut -d " " -f 1` MINOR=`echo $VERSION | cut -d " " -f 2` PATCH=`echo $VERSION | cut -d " " -f 3` wget "https://github.com/$GITHUB_REPOSITORY/releases/latest/download/antimicrox-$MAJOR.$MINOR.$PATCH-amd64.deb" sudo dpkg -i `ls -1 | grep .deb` - name: Prepare files to create apppimage run: | mkdir build && cd ./build wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage chmod +x linuxdeploy-x86_64.AppImage chmod +x appimagetool-x86_64.AppImage chmod +x linuxdeploy-plugin-qt-x86_64.AppImage cmake .. -DCMAKE_INSTALL_PREFIX=/usr make make install DESTDIR=AppDir #UPDATE_INFORMATION describes where information about updates can be found - name: Create AppImage file run: | cd build export UPDATE_INFORMATION="zsync|https://github.com/$GITHUB_REPOSITORY/releases/latest/download/antimicrox-x86_64.AppImage.zsync" ./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt ./appimagetool-x86_64.AppImage AppDir/ -u "$UPDATE_INFORMATION" #Upload generated files to release - name: Upload binaries to release uses: AButler/upload-release-assets@v2.0 with: files: ./build/AntiMicroX*.AppImage;./build/AntiMicroX*.zsync repo-token: ${{ secrets.GITHUB_TOKEN }} AntiMicroX-antimicrox-2888bf6/.github_changelog_generator000066400000000000000000000002041377703515000236170ustar00rootroot00000000000000user=AntiMicroX project=antimicrox since-tag=3.1.1 pr-label=**Other merged pull requests:** issues-label=**Notable closed issues:** AntiMicroX-antimicrox-2888bf6/.gitignore000066400000000000000000000002301377703515000202460ustar00rootroot00000000000000# Build directories build/ build-dir/ Build/ .flatpak-builder/ repo/ doc/ # Changelogs src/Changelog src/CHANGELOG.md # IDE- related files .vscode AntiMicroX-antimicrox-2888bf6/AntiMicroX Future Developments.mm000066400000000000000000000117561377703515000245260ustar00rootroot00000000000000 AntiMicroX-antimicrox-2888bf6/BUILDING.md000066400000000000000000000121731377703515000200060ustar00rootroot00000000000000# Building AntiMicroX Most of these packages are already built and available on [Release Page](https://github.com/AntiMicroX/antimicrox/releases), but if you want, you can also build AntiMicroX by yourself. - [Building AntiMicroX](#building-antimicrox) - [Build Dependencies](#build-dependencies) - [Basic building](#basic-building) - [Build Options for CMake](#build-options-for-cmake) - [Universal Options](#universal-options) - [Linux Options](#linux-options) - [Building deb package](#building-deb-package) - [Building rpm package](#building-rpm-package) - [Building AppImage](#building-appimage) - [Building Flatpak](#building-flatpak) ## Build Dependencies This program is written in C++ using the [Qt](https://www.qt.io/) framework. A C++ compiler and a proper C++ build environment will need to be installed on your system prior to building this program. Under Debian and Debian-based distributions like Ubuntu, the easiest way to get a base build environment set up is to install the meta-package **build-essential**. The following packages are required to be installed on your system in order to build this program: - `g++` from `gcc` - `cmake` - `extra-cmake-modules` - `qttools5-dev` and `qttools5-dev-tools` (`qt5-tools` on distros based on Arch Linux) (Qt5 support) - `libsdl2-dev` (`sdl2` on distros based on Arch Linux) (SDL2) - `libxi-dev` (`libxi` on distros based on Arch Linux) (Optional. Needed to compile with X11 and uinput support) - `libxtst-dev` (`libxtst` on distros based on Arch Linux) (Optional. Needed to compile with XTest support) - `libx11-dev` (`libx11` on distros based on Arch Linux) (Needed to compile with Qt5 support) - `itstool` (extracts messages from XML files and outputs PO template files, then merges translations from MO files to create translated XML files) - `gettext` ## Basic building This way of building is useful for testing purposes. In order to build this program, open a terminal and cd into the antimicrox directory. Enter the following commands in order to: Build the program: ```bash cd antimicrox mkdir build && cd build cmake .. cmake --build . ``` Run built binaries ``` ./bin/antimicrox ``` A recommended way of installation is building package typical for for your system (or building universal one like an AppImage).
Installation using cmake (not recommended) This way of installation is not recommended, because it doesn't integrate very well with some environments. Install: ```bash sudo cmake --install . ``` Uninstall: ```bash sudo make uninstall ```
### Build Options for CMake There are a few application specific options that can be used when running cmake to build antimicrox. The following file will attempt to list some of those options and describe their use in the project. ### Universal Options -DUPDATE_TRANSLATIONS Default: OFF. Set updateqm target to call lupdate in order to update translation files from source. -DTRANS_KEEP_OBSOLETE Default: OFF. Do not specify -noobsolete option when calling lupdate command for qm files. -noobsolete is a method for getting rid of obsolete text entries -DWITH_TESTS Default: OFF. Allows for the launch of test sources with unit tests ### Linux Options -DAPPDATA Default: ON. Build the project with AppData support. -DWITH_UINPUT Default: ON. Compile the program with uinput support. -DWITH_X11 Default: ON. Compile the program with X11 support. -DWITH_XTEST Default: ON. Compile the program with XTest support. ## Building DEB package ```bash cd antimicrox mkdir build && cd build cmake .. -DCPACK_GENERATOR="DEB" cmake --build . --target package ``` ## Building RPM package If your distribution doesn't yet have an RPM package, you can easily build one for yourself. ```bash cd antimicrox mkdir build && cd build cmake .. -DCPACK_GENERATOR="RPM" cmake --build . --target package ``` ## Building AppImage Create build directory ```bash mkdir build && cd ./build ``` Download tools used for creating appimages (and make them executable) ```bash wget https://github.com/linuxdeploy/linuxdeploy/releases/downloacontinuous/linuxdeploy-x86_64.AppImage wget https://github.com/AppImage/AppImageKit/releases/downloacontinuous/appimagetool-x86_64.AppImage wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releasedownload/continuous/linuxdeploy-plugin-qt-x86_64.AppImage chmod +x linuxdeploy-x86_64.AppImage chmod +x appimagetool-x86_64.AppImage chmod +x linuxdeploy-plugin-qt-x86_64.AppImage ``` Build antimicrox and install it in AppDir directory ```bash cmake .. -DCMAKE_INSTALL_PREFIX=/usr make make install DESTDIR=AppDir ``` Create AppImage file ```bash ./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt ./appimagetool-x86_64.AppImage AppDir/ --no-appstream ``` ## Building Flatpak The command builds the package into the `build` folder and installs the created flatpak. The Flathub manifest can be located in [Flathub's Github repo](https://github.com/flathub/io.github.antimicrox.antimicrox). ```bash flatpak install flathub org.kde.Platform//5.11 org.kde.Sdk//5.11 flatpak-builder --user --install build/ other/io.github.antimicrox.antimicrox.yml --force-clean ``` AntiMicroX-antimicrox-2888bf6/CHANGELOG.md000066400000000000000000001341141377703515000201000ustar00rootroot00000000000000# Changelog ## [3.1.4](https://github.com/AntiMicroX/antimicrox/tree/3.1.4) (2021-01-11) [Full Changelog](https://github.com/AntiMicroX/antimicrox/compare/3.1.3...3.1.4) Kudos to @Janfel for PR! **Implemented enhancements:** - Remove qglobalshortcuts [\#106](https://github.com/AntiMicroX/antimicrox/issues/106) - File cleanup [\#104](https://github.com/AntiMicroX/antimicrox/issues/104) - Cmakefile fixes [\#102](https://github.com/AntiMicroX/antimicrox/issues/102) - Add dark tray icon [\#66](https://github.com/AntiMicroX/antimicrox/issues/66) - Icons overhaul [\#61](https://github.com/AntiMicroX/antimicrox/issues/61) - Automate generating changelogs [\#10](https://github.com/AntiMicroX/antimicrox/issues/10) **Fixed bugs:** - Clear shortcut not working [\#116](https://github.com/AntiMicroX/antimicrox/issues/116) - Assigning Text Entry to button doesn't assign proper string. [\#79](https://github.com/AntiMicroX/antimicrox/issues/79) - The uninstallation leaves several folders and files behind \(cmake\) [\#68](https://github.com/AntiMicroX/antimicrox/issues/68) **Notable closed issues:** - Remove antilib shared object because it's not really shared! [\#98](https://github.com/AntiMicroX/antimicrox/issues/98) **Other merged pull requests:** - feat: improve mime type definition [\#132](https://github.com/AntiMicroX/antimicrox/pull/132) ([Janfel](https://github.com/Janfel)) - docs: update building and installation instructions [\#129](https://github.com/AntiMicroX/antimicrox/pull/129) ([pktiuk](https://github.com/pktiuk)) - feat: antimicro config migration [\#120](https://github.com/AntiMicroX/antimicrox/pull/120) ([gombosg](https://github.com/gombosg)) ## [3.1.3](https://github.com/AntiMicroX/antimicrox/tree/3.1.3) (2020-11-15) [Full Changelog](https://github.com/AntiMicroX/antimicrox/compare/3.1.2...3.1.3) **Fixed bugs:** - ARM build failure [\#80](https://github.com/AntiMicroX/antimicrox/issues/80) - AntiMicroX system tray icon not appearing in flatpak package [\#58](https://github.com/AntiMicroX/antimicrox/issues/58) - Icons in tray menu only showing up as "X" [\#56](https://github.com/AntiMicroX/antimicrox/issues/56) - Outdated information in the "Credits" tab in the "About" window [\#67](https://github.com/AntiMicroX/antimicrox/issues/67) **Notable closed issues:** - Consistent style of code [\#25](https://github.com/AntiMicroX/antimicrox/issues/25) **Other merged pull requests:** - Icons overhaul [\#73](https://github.com/AntiMicroX/antimicrox/pull/73) ([pktiuk](https://github.com/pktiuk)) - Fix: Use system icons in common cases to avoid incompatibility issues [\#62](https://github.com/AntiMicroX/antimicrox/pull/62) ([pktiuk](https://github.com/pktiuk)) - General cleanup of repository [\#18](https://github.com/AntiMicroX/antimicrox/pull/18) ([pktiuk](https://github.com/pktiuk)) ## [3.1.2](https://github.com/AntiMicroX/antimicrox/tree/3.1.2) (2020-10-02) [Full Changelog](https://github.com/AntiMicroX/antimicrox/compare/3.1.1...3.1.2) **Fixed bugs:** - Right click - Turbo and Clear not working properly [\#7](https://github.com/AntiMicroX/antimicrox/issues/7) - Wrong order for setting sets [\#6](https://github.com/AntiMicroX/antimicrox/issues/6) **Notable closed issues:** - Fedora resubmission [\#29](https://github.com/AntiMicroX/antimicrox/issues/29) - Flatpak packaging [\#9](https://github.com/AntiMicroX/antimicrox/issues/9) **Other merged pull requests:** - refactor: remove Dockerfiles [\#52](https://github.com/AntiMicroX/antimicrox/pull/52) ([gombosg](https://github.com/gombosg)) 2020-09-15 Gergely Gombos Version 3.1.1 * AppStream XML file revision * New screenshots * Add 128x128 icon * Prepare for Flathub submission 2020-09-09 Paweł Kotiuk Version 3.1.0 * Updated documentation connected with migration to new repository * Add instruction and config for building Flatpak packages - Gergely "gombosg" Gombos * Multiple improvements of packaging for Debian/Ubuntu * Ensure consistent naming across entire project * Rename used directories and files from antimicroX to antimicrox * First official AppImage release 2018-16-06 Jagoda Gorska Version 3.0.1 * Works with old antimicro profiles * Added small changes (in instructions, comments, etc.) * Added running in tray from right button Version 3.0 * Added qt directives for compatibility with older versions of qt5 * Arch Linux packages of application of frealgagu and sir_lucjan Link1: https://aur.archlinux.org/packages/antimicrox/ Link2: https://aur.archlinux.org/packages/antimicrox-git/ * Deb package of Paweł "pktiuk" Kotiuk Link1: https://github.com/pktiuk Link2: https://github.com/juliagoda/antimicroX/pull/120 Link3: https://github.com/juliagoda/antimicroX/pull/103 * Rpm package of Gergely "gombosg" Gombos meanwhile Link1: https://github.com/gombosg Link2: https://github.com/juliagoda/antimicroX/issues/118 * Created and added dockerfiles to containers - look README Link1: https://hub.docker.com/r/juliagoda/antimicrox * Changed icon for antimicroX * Added F13-F24 buttons to "Others" only if they are detected on keyboard * Added more adjusted debug/info/warning outputs to log settings * Added new functionality - joining and splitting slots * Added new functionality - deletion of more slots at once * Added new functionality - insertion of more slots at once * Added new functionality - One choice of execution paths and its arguments for multiple slots * Added new functionality - One choice of profile for multiple slots * Added new functionality - attaching numeric keypad keys thanks to option in settings * Added new functionality - global shortcuts for quitting application from settings * Added support for the same model of gamepads * Updated german, english and polish translation files # Fixed issue #92 * Fixed issue #97 * Fixed issue #90 * Fixed issue #98 * Fixed issue #101 * Fixed issue #107 * Fixed issue #108 * Fixed issue #109 * Fixed issue #113 * Fixed issue #112 * Fixed issue #114 * Fixed iisue #116 Version 2.25 * renamed AntiMicro into antimicroX * added detection of scripts - fixed unfinished JoyExecute slot * added menu icons and shortcuts * removed unused files and directives * removed majority of deprecated code * updated information about application * sorted and cleaned headers in header files * unlocked multiple parameters for command line * added notifications about battery level * added guard conditions Version 2.24.2 * Fixed bug with too many "emit propertyUpdated()" * Splitted JoyButtonSlot class into JoyButtonSlotXml and the original * Created template class for JoyDPad and VDPad xml * Splitted GameControllerDPad class into GameControllerDPadXml and the original * Replaced for loops with iterators and functional mappers * Replaced for loops with hashiterators * Added functions about vendor and product informations * Changed guid to uniqueID Version 2.24.1 * Changed images and screenshots * Updated Documents (README, *.txt files, *.md, *.mm files) * Updated resources * Created index.theme * Changed destination directories for icons, images, index.theme and other resources * Translated new text entries * Added detection of window partial title * Added reset settings option * Created smaller functions in part of classes * Splitted part of classes into new xml classes * Added com.github.juliagoda.antimicro.json for Flatpak (building and installation on Linux) * Cppcheck Analysis - fixed part of warnings * Added Comparing to nullptr instead of NULL and smart pointers * Changed if else to switch statements for int data types * First preparation for unit tests (app splitted into library (antilib) and executable (antimicro)) * Updated calibration - reset old values during calibration startup * Fixed part of memory leaks with Memcheck (application exit) * Fixed bug in gamecontrollermappingdialog class * Fixed segmentation fault for activating Turbo option * Unblocked delay sliders Version 2.24 * Added calibration * Ported Qt4 to Qt5 * Removed Qt4 support 2016-11-05 Jeff Backus Version 2.23 * Fixed portable version. (issue #37) * Added ability to specify logging level and file in config dialog. (issue #50) * Updated build system to find libraries on Windows systems instead of using explicit paths. (issue #43) * Added relevant window information to debug messages related to auto profiles. (issue #46) * Fixed issue with anything in profile name after first period being truncated. (issue #70) * Fixed issues with SDL 2.0.5 on all platforms. (issue #71) * Added support for additional small-case Latin characters when using Xtest. (issue #49) * Added inclusion of README-SDL.txt when building Windows distributables. 2016-07-30 Jeff Backus Version 2.22 * Fixed a segfault on startup issue affecting some Linux distributions * Fixed issues with SDL 2.0.4 on Windows. * Updated documentation and URLs in code to note transition in management. * Updated translations and added new ones. * Added code to revert all virtual buttons to beginning of slot list before a set switch. * Build system updates * Fixed a bug where invalid joystick was inserted into device list. * Modified to hide turbo mode combobox for regular buttons * Changed to allow blank config for auto profile entries again. * Fixed matching by process filename in AutoProfileWatcher 2016-01-10 Travis Nickles Version 2.21 * Changed unplug routine slightly. The old behavior was slightly wrong anyway but the old behavior did not work with SDL 2.0.4. * Custom Qt builds are being used for the 64 bit Windows build and noSSE Windows build. * Updated Windows build to use Qt 5.5.1. * Updated Windows build to use SDL 2.0.4. This should clear up a couple of problems for people running Windows 10. * Changes to some acceleration curves. Both the output values and the input offsets were changed to make mouse movement looser. * Removed First Run Wizard from program. In the end, that wizard was causing more problems for other users than it was worth. * Add arguments property for Execute slots. * Allow a real absolute mouse to be used with uinput support. Previously, relative mouse movement was being used to fake an absolute position for the mouse pointer. The WiimoteGlue project provided a way to allow uinput to send absolute mouse pointer events when using uinput. * Fixed set changing with analog triggers. 2015-10-19 Travis Nickles Version 2.20.2 * Change Enhanced Precision and Easing Quad/Cubic acceleration curves * Skipped straight to 2.20.2 since version 2.20 actually had 2.20.1 marked as its version in the application 2015-10-10 Travis Nickles Version 2.20 * Replace usage of QElapsedTimer with QTime for mouse movement calculations. * Start using Qt 5 with Ubuntu Vivid package. * Change XTest pointer acceleration when starting the program. * Allow release slot to have a 0 ms interval. This is useful for people who use a gamepad poll rate less than 10 ms. * Change minimize to tray code to work better with later versions of Gnome 3 and Unity. * Transfer travel distance axis changes when switching sets. 2015-09-29 Travis Nickles Version 2.19.3 * Japanese translation provided by tou omiya. * Make sure Game Controller Mapping dialog window reads raw joystick events. This should fix problems regarding improper mapping causing controller elements to no longer be mappable. * Make Set Change slots activate on button release instead of button press. * Tweaked the locking being performed in various portions of the program. * Fixed a problem with blank info window appearing when escaping from window capture utility dialog. * Fixed issues with document-save-as icon staying displayed after resetting a profile. * Fixed "Media Next" key binding for virtual keyboard. * Fixed various issues regarding binding slots in the Advanced Edit dialog window. 2015-09-15 Travis Nickles Version 2.19.2 * Add --next to allow multiple profiles to be loaded in one command call. * Add a flag to settings file when wizard is finished. Don't depend on any other settings being changed during an application run. * Fixed issue with inserting Pause slots. * Fixed issue with blank application filepath being matched for auto profile support. 2015-09-03 Travis Nickles Version 2.19.1 * Fixed SDL 1.2 build support. * Fixed issue with SDL thread not being stopped due to connections not being made in some situations. * Fixed loading of a profile from a second instance. * Fixed problem with main window not being populated after the App Settings Wizard was finished. * Fixed another portion of the program that assumed that a controller would be connected at startup. Fixes excessive CPU load. 2015-08-31 Travis Nickles Version 2.19 * Added curve options for extra acceleration. * Fixed bug when App Settings Wizard would pop up when not needed. * Simplified Chinese translation updated. 2015-08-24 Travis Nickles Version 2.18.2 * Fixed overly active timer used to reset acceleration distances when no events are returned from SDL in a given gamepad poll. * Sebian translation updated by Jay Alexander Fleming. * Changed behavior of 4 Way Cardinal mode for DPads. Diagonals are no longer counted as a dead zone. This change is more likely temporary. Up+Right - Up, Down+Right - Right, Down+Left - Down, Up+Left - Left 2015-08-18 Travis Nickles Version 2.18.1 * Fixed some threading issues when using X11. * Fixed excessive CPU load on startup when no controller is connected. 2015-08-15 Travis Nickles Version 2.18 * Perform event simulation in its own thread. Timer used for mouse speed calculations has improved as a result. * Slow down Enhanced Precision mouse acceleration curve slightly. Changes were mainly due to overall mouse emulation being tweaked. * Distributing 64 bit builds for Windows again. * Using a simulated event to click the minimize button in title bar now works on Windows. The move to using a dedicated thread for event simulation allows that to work now. * Simplified Chinese translation added thanks to zzpxyx. 2015-08-02 Travis Nickles Version 2.17 * Changed Enhanced Precision acceleration curve. The curve has been slowed down slightly. * Changed how initial mouse movement is performed when the gamepad poll rate and the mouse refresh rate differ. * Flash interface buttons after restoring the main window from the tray icon. * Tweaked mouse movement remainder routine. Remainders now only apply when the direction along an axis is the same. * Raised maximum cycle reset time to 60 seconds. * Fixed improper cycle reset interval. 2015-07-22 Travis Nickles Version 2.16 * Loosen initial mouse movement experienced after going outside the dead zone. * Added option in the mouse settings section that would allow antimicroX to reset the acceleration values being used for the uinput virtual mouse pointer. This is useful after playing older Linux games that change the acceleration settings for all mouse pointers after a game exits. Postal 2 and Doom 3 are two examples of games in my game library that exhibit this behavior. * Queue all events before performing any actions. The priority of various events has been changed as well. * Added option to change the gamepad poll rate used by the application. By default, the old 10 ms poll rate will be used. * Bundle a few backup icon files. Mainly useful on SteamOS since the themes used don't bundle a couple of essential icons that are expected to be present. * Compiled vmulti support into Windows build. The driver is not currently provided. The program needs to be started with the arguments --eventgen vmulti. * Temporarily stop packaging a 64 bit version of the program for Windows. Unfortunately, the version of Qt being used has a problem regarding timer accuracy that is not experienced with the 32 bit version of Qt being used. At this time, working around the problem is not feasible so there will be no 64 bit release. Please use the 32 bit version. * Change shortcuts used for the .msi package. * Bundle Qt translation files for Windows version. 2015-06-27 Travis Nickles Version 2.15 * Changed routine for extra acceleration for mouse movement. The new version is a bit faster and more responsive than the previous version. * Added release circle setting for spring mouse mode. This can be used to have the mouse return to a region around a character based on the last detected direction of an analog stick. * Added a sub-menu to the virtual keyboard. Some multimedia and browser keys can now be selected. * Added Execute slot type. A program can be set to launch when a slot is activated. * Added Text Entry slot type. You can now have a string of text typed when a slot is activated. This can be useful for inputting common commands in games. * Added proper interpolation to determine the start of diagonal regions of analog sticks. This is used for mouse movement in order to determine the proper starting dead zone point. * Changed Enhanced Precision mouse acceleration curve. The new changes in the curve should be much looser than before. * Fixed --unload command line option. Enforce reloading of config file when finished. * Fixed issue with spring mouse mode where the mouse would temporarily return to center when switching stick directions quickly. * Fixed some bindings in the virtual keyboard when using SendInput for the event generator. * Fixed issue with widgets used to update stick and dpad delay. The spinbox can now be used to edit the delay. * Reduced multiple instances of some objects. Reduces memory usage slightly. 2015-05-01 Travis Nickles Version 2.14 * Refactored extra axis acceleration. This revision uses individual gamepad polls again. Other changes in the code have made switching back feasible. With minor adjustments, the mouse will be looser but very controllable. * Added longer duration for extra axis acceleration. This allows extra acceleration to be performed over a period of time as opposed to just one gamepad poll. * Changed key repeat routine when using SendInput on Windows. Key releases restart the last active key repeat delay. * Now using Qt64-NG for the 64 bit Windows builds. * Initial experiments with vmulti support in the Windows version. Using that driver would allow antimicroX to use a virtual keyboard and mouse rather than using SendInput. That would allow antimicroX to work around UAC problems and anti-cheat programs. Support is not currently compiled into the Windows builds due to not being able to properly distribute the vmulti driver. * Do not write empty names tag in profiles if no custom button names have been specified. * Allow mouse history buffer size to go up to 100. * Allow diagonal range to go up to 90 degrees. * Remove old mouse speeds from mouse history buffer if stick has been returned to the dead zone. History buffer will be filled with zeroes. * Omit hotplugging dependent code when compiling against SDL 1.2. * Fixed dpad pointer bug when certain QueuedConnection slots are executed. 2015-03-31 Travis Nickles Version 2.13 * Updated extra axis acceleration routine. Now, extra acceleration is calculated after an axis has stopped moving past the assigned threshold in one gamepad poll. * Stick presets now change the diagonal range of a stick. This is mainly beneficial for mouse control changes so that 65 degrees is used by default. * Added a screen selector for Spring mouse mode in settings menu. * Added a small language selection portion to the settings menu. * Added a small logger. Please run antimicroX with "--log-level debug" in order to get output about button presses. 2015-03-22 Travis Nickles Version 2.12.1 * Implemented a small wizard that will be run when antimicroX is launched for the first time. It currently only has a page for editing some of the mouse settings and a page for associating antimicroX with .amgp files on Windows. * Show slots that are active for a stick modifier button on the main interface. The text for the main stick direction buttons will be prefixed with the currently active slots of the stick modifier button. * Corrected issue with stick and dpad events not getting activated on a set change. Events were being queued but not executed. 2015-03-15 Travis Nickles Version 2.12 * Added option for extra mouse acceleration. Enabling that option will increase the speed of the mouse based on the amount an axis has travelled in one gamepad poll and the set multiplier. This will greatly affect how the mouse behaves and it will make mouse movement looser. Using this feature can be problematic if the analog stick on your controller is worn out and loose. * Corrected issue with extra mouse sync events occurring when not needed (0,0 events). This change seems to have smoothed out mouse movement on the low end of an axis a bit. * Tweaked controller unplug workaround to still invoke release events for axes and buttons. For triggers, the release value is modified from what is provided by SDL so an unplug event will cause a release event to occur for the triggers. 2015-02-25 Travis Nickles Version 2.11.1 * Added workaround to allow gamepad unplugging on Windows to not activate bindings for the triggers. This was caused by the way controller unplugging is handled by SDL (primarily with the Windows version). SDL sends a release value for all elements of an unplugged joystick a brief period before sending the expected SDL_JOYDEVICEREMOVED event. The problem is that the released value used for triggers assumes that the dead zone is half the trigger's full range. This would cause bindings for triggers to usually activate for a brief period before SDL would send the final SDL_JOYDEVICEREMOVED event which would then deactivate those bindings. * Changes for the portable Windows version. Allow relative profile paths for use in the portable package on Windows. Associate profiles registry change prompt skipped. * Queue stick and dpad events. Allows for better control of 8-way sticks and dpads. 2015-02-07 Travis Nickles Version 2.11 * Adjusted the Enhanced Precision, Easing Quadratic, and Easing Cubic mouse acceleration curves. The low end of each curve has been loosened a bit and the rest of the curves have been adjusted accordingly. Comparing the two versions, the resulting mouse speed for a given axis point is slightly lower in the new versions for most of the curve. The extreme low end and the extreme high end of the curves will be slightly faster. * Updated Qt to version 5.4.0 for the Windows builds. * Compiled a 64 bit version for Windows thanks to the Qt-x64 project. * Added a set changing slot. * Added AppData for use when packaging on Linux thanks to Jeff Backus. * Fixed bug with mouse wheel event methods for axes which resulted in negative values being passed to the event timer. 2014-12-29 Travis Nickles Version 2.10.1 * Changed event handler fallback method under Linux. * Changed interface of Assignments page in Advanced Button Dialog. * Reset set number upon changing profiles. * Added "About Development" tab to About Dialog. * Fixed dynamic text resizing in Button Edit Dialog under Linux. * Fixed launching a second instance in order to load a profile in the first instance. 2014-12-10 Travis Nickles Version 2.10 * Changed allowed values for easing duration. The minimum value has been lowered to 0.0 and the maximum value has been increased to 5.0. * Added a stick modifier button. This button is primarily meant to be used to assign walk/run functionality to an analog stick. Instead of having to create distance zones and assign keyboard modifier keys to each stick button, you can now make the assignment on the stick modifier button and it will apply to the stick as a whole. It makes assigning walk/run functionality to an analog stick much less cumbersome. The DreadOut demo has already shown a use case where only the stick modifier button was needed due to the demo not handling running when using the left stick on an Xbox 360 controller. * Increased idle mouse timer interval to 100 ms. * Added a load profile slot. You can now tell the program to load a different profile upon pressing a button. * Added gradient functionality for the high end of the Easing Quadratic and Easing Cubic mouse acceleration curves. * Raise process priority on Windows. Now, the antimicroX process will run with High priority. This allows internal timers to work better and be less susceptible to the activity of other running programs. On Linux, the priority of the main thread has been increased. * Take multiple direction buttons into account when assigning set switching to stick buttons. * If uinput is enabled but not usable at runtime then XTest will be used as a fallback option for the Linux version. * Tweaked Gradient and Pulse turbo modes to make them a bit tighter. A lower delay will be needed in profiles to achieve a similar control from previous versions. On the plus side, this has been tested to work with FlatOut 2 fairly well. It is good enough to use and actually win some races against AI opponents. * Added analog control for mouse wheel buttons that are mapped to an axis button. * Tweaked mouse movement code to improve mouse accuracy. This is mainly due to discovering the QElapsedTimer class that is included in Qt. * Fixed middle mouse button binding when using the uinput event handler on Linux. * Fixed memory leaks that were discovered by Valgrind. 2014-11-19 Travis Nickles Version 2.9 * Added mouse refresh rate as an option. Please be mindful of how your system behaves if you set the refresh rate to a low value like 1 ms. In the worst case scenario, you could end up dedicating one CPU core on just the antimicroX process. Also, on Windows, you will want to make sure to disable the "Enhance Pointer Precision" option if you use a low value otherwise Windows will severely slow down the mouse pointer. * Added an application level mouse smoothing option. The older button level smoothing option has been removed. The old option didn't do much since it only dealt with the partial distance remainder. * Button responsiveness has been improved. The old mouse movement code was creating a bottleneck for button processing which would result in a slight delay. * Changed mouse movement code. The overall mouse movement should be smoother now. * Allow the Windows setting "Enhance Pointer Precision" to be disabled while antimicroX is running. This will make sure Windows does not directly manipulate the mouse events sent to the system. This will allow mouse control on an analog stick to be more accurate on Windows. * Changes to Auto Profile to allow more variables for matching. Multiple window properties can be specified which will cause antimicroX to count an entry as a match only if all specified properties match. * Changed how windows are grabbed in X on Linux. * Minor fix for Gradient and Pulse turbo modes. There were times when the timer interval controlling those modes could be negative and cause problems. 2014-11-05 Travis Nickles Version 2.8.1 * Fixed some buttons in virtual keyboard when program is using uinput support. * Fixed Update Joysticks option for SDL 1.2 users. 2014-10-28 Travis Nickles Version 2.8 * Added delay settings for analog sticks and dpads. This is meant to keep some games from overreacting when switching directions quickly. A delay is especially useful for games that utilize a dash on a key double tap. This will also be very useful while playing rougelike games. The new delay setting allows for more responsive controls than the old alternative of using hold zones on individual direction buttons. * Added two new mouse acceleration curves: Easing Quadratic and Easing Cubic. These new mouse acceleration curves are meant to mimic the camera control that is used for gamepad support in some recent first person shooters such as Borderlands 2. Once a stick direction has reached a threshold (80%) then the mouse speed will gradually accelerate over a period of time before the mouse speed reaches its peak. The duration of the easing method is set at 0.50 seconds by default but the setting is configurable per button. * Major refactor to mouse event generation. The new routine requires fewer system resources and it is more accurate. * Made uinput support a runtime option for Linux users. The program can now be compiled with both XTest and uinput support and the event generator can be specified using the --eventgen flag. It defaults to XTest if available. The option is only available when the program is compiled with both XTest and uinput support. * Added right click context menus for buttons in main interface. * Fixed issue with Game Controller Mapping dialog. Controller DPads that are exposed as 4 buttons can now be bound to the DPad of an SDL Game Controller. * Fixed an issue with incorrect profile names being displayed in the profile combobox. * Fixed issue introduced in version 2.7 regarding mouse movement calculations for the left direction of analog sticks. A major portion of the safe zone for that direction was being skipped. * Changed button groups in the main interface to update immediately when a stick or dpad mode has been changed. * Initial removal of old joystick abstraction support in interface when using SDL 2. 2014-10-14 Travis Nickles Version 2.7 * Added a UAC workaround for use in Windows. antimicroX can be restarted as Administrator in case a game is running with elevated permissions and the events generated by antimicroX are not detected by a game. * Added more key aliases for uinput support. * Force higher dead zones for axes in Game Controller Mapping window. * Fixed virtual keyboard in Button Edit Dialog window for Linux users utilizing XTest support. * Display some minor mouse stats in Mouse Settings dialog. * Alter Analog Stick dialog window to show some new stats. Also, show square stick coordinates as well as adjusted circle stick coordinates. * Added square stick to circle stick conversion. * Fixed issue with VK_LSHIFT and VK_RSHIFT aliases not being saved properly on Windows. * xinput is used for the uinput virtual pointer in order to disable mouse acceleration for the pointer. This allows spring mode to work as intended. * Added some code to guess which axes of a gamepad should be considered triggers by default while in old Joystick mode. The initial values of axes are taken from SDL and those are used as the point of the axes while centered. If the initial value of an axis is below -30,000 then an axis is considered to be a trigger. 2014-09-16 Travis Nickles Version 2.6 * Added two new Turbo modes. Gradient mode is used to change the key press time depending on the position of an axis (useful for racing games). Pulse mode is used to change how many times a key press is invoked depending on the position of an axis (scrolling in a web browser using arrow keys). * Fixed profile resetting in a couple of places. * A Russian translation has been provided by Dima Koshel. * Added option to invoke Game Controller mapping window from command line. The final mapping string will be printed to stdout. This is useful for saving a SDL_GAMECONTROLLERCONFIG for your controller that can be used system wide. Any SDL 2 game can then be set up to use that mapping and it can be changed if needed. * Profiles now use a unique .amgp file extension. Older xml profiles will continue to be supported. * Fixed spring mouse mode so that it uses proper axis distance values. * Set changing has been fixed for analog sticks and virtual dpads. * EXPERIMENTAL. uinput support has been added to the source code. Binary Linux packages will continue to utilize XTest for event generation for the time being. If you would like to test uinput integration then you will have to compile the program using -DWITH_UINPUT=ON and -DWITH_XTEST=OFF when running cmake. Playing Warsow 1.51 in Linux using antimicroX requires using uinput integration. Also, keys can now be pressed in a tty. 2014-08-01 Travis Nickles Version 2.5 * Fixed packaging the Windows version so the program will work on Windows XP again. * Delay rendering of flashing buttons. This helps improve controller responsiveness when the main window is not hidden. * Reduced the size of written profiles. Only changed values are now stored in profiles. * Updated German translation provided by phob and Leonard Koenig. * Allow a profile to be listed as the final argument on the command line. Ex: antimicroX ~/antimicroX-profiles/profile.xml. * Added diagonal distance support for distance slots for Standard mode on Sticks and DPads. This was necessary for some modifier assignments to work properly. The best example is for assigning walking in Half-Life 1. * Allow generated events to be sent to a different X display than the application is running on. This change was mainly done to better work with SteamOS. antimicroX can be run via ssh with X tunneling in order to configure profiles on one system but the program will send events to the X display that is running Steam and games. * Auto Profile support has improved for SteamOS. Application grabbing can now be done while in the SteamOS BPM Session. Steam BPM can be grabbed as well. * Only show active or soon to be active slots for buttons in the main window. The text displayed on the buttons will update when a new zone has been reached due to using slots such as distance or hold. * Allow no profile to be assigned to an application for an Auto Profile entry. This means that the program will choose an empty profile when the application for that Auto Profile entry has focus. This will help with disabling antimicro for applications that already have controller support. * Controller Mapping dialog now stops processing events until all elements have been released on a controller. 2014-05-30 Travis Nickles Version 2.4 * Relative spring mode added. * Key repeating changes in Windows. * Updated Windows version to use Qt 5.3.0. * Set copying added. * Corrected application checks used for Auto Profile support in Windows. 2014-05-23 Travis Nickles Version 2.3.3 * Tweaked Enhanced Precision mouse acceleration curve. * Tweaked "all" option in Auto Profile. No profile assigned to "all" now implies that a blank configuration should be loaded. * Manpage created by Jeff Backus. * Migrated to the CMake build system. 2014-05-15 Travis Nickles Version 2.3.2 * Fixed problem with old profiles not being usable in the program. 2014-05-13 Travis Nickles Version 2.3.1 * Added new Enhanced Precision mouse curve. It is now the default mouse curve. The new mouse curve will make the cursor move slowly towards the low end of an axis and the cursor movement will be accelerated towards the high end of an axis. * Added unsaved profile dialogs. * Added key repeating behavior under Windows. * Increased maximum turbo interval. * Added more options to the Edit Settings dialog. * Added profile name display editing. * Fixed invalid pointer issue for Hold events. 2014-05-02 Travis Nickles Version 2.3 * Added a daemon mode. * Added joystick profile compatibility parser for game controllers. Old profiles are now usable when using SDL Game Controller support. Old profiles have to be mapped against the same controller that is connected. * Added cycle reset support. Sequences with cycles can now get returned to the first cycle zone in a sequence after a period of time. * Changed Auto Profile support to work properly in SteamOS while running the SteamOS Big Picture Mode session. On many tested games (Duke Nukem 3D, SuperTux, World of Goo), the game had to be run in windowed mode in order for Auto Profile support to be able to detect the application. It is recommended that you run games in windowed mode when using Auto Profile support in the SteamOS BPM session. This is not an issue when running the Steam desktop client in desktop mode. * Added a delay slot type. A delay slot can be used for key presses in a key combination. Unlike other macro slots, slots placed before a delay slot will remain active after the specified time has passed. * Added option to allow the program to start on Windows startup. * Changed dialogs for secondary set buttons to display the set that the button is currently in. * Changed turbo mode to give more control. Key presses are now given more time to be active. Key presses and releases now run for a duration of t/2 seconds. * Altered tray menu to display a single list when only one controller is connected. An option has been added to allow for a single list to also be used when multiple controllers are detected. * Fixed issue with Windows XP Auto Profile workaround. On the plus side, now the program is confirmed to work in Windows XP. * Fixed issues with Auto Profile support saving and precedence. 2014-04-19 Travis Nickles Version 2.2 * Added example controller display to Game Controller Mapping dialog window. * Added Auto Profile support. Allows for profiles to be associated with specific applications. * Added button icons in Windows version. * Added a press time slot type. That slot type is used to have keys active for a specific period of time. * Allow Pause slots to have a 0 second interval. Allows for a forced key release. * Windows version is now built with SDL 2.0.3. * Fixed 8-Way D-Pad mode. * Fixed preset options in various dialogs to account for new aliases. * Fixed ampersand rendering in set buttons. * Fixed spring mouse mode dimension support. * Fixed spring mouse mode accuracy under Windows. 2014-02-28 Travis Nickles Version 2.1 * Added new stick and dpad modes. * Added set names. * Minor fixes for Windows. * Fixed QSettings usage to reduce reads and write to config file. 2014-02-10 Travis Nickles Version 2.0.1 * Active keyboard keys now use a reference count. This will be useful for keeping modifier keys held when moving a stick from a diagonal direction to a cardinal direction. This will allow a run to be maintained properly. * A release delay has been added to release slot events. This is needed for some games where a key press and release might happen too quickly for a game, such as The Elder Scrolls IV: Oblivion, to catch it. * Altered data sent to SendInput under Windows. The change should allow games that rely exclusively on scancode data to detect keyboard key presses now. Previously, keyboard emulation would not work while playing The Elder Scrolls IV: Oblivion on Windows. * Improved key associations under Windows. VK_OEM_* keys associations are now generated at runtime which will allow associations to be more layout independent. * Changed some portions of the Windows version so that the Numpad Enter key can be emulated. * The recent profile list is now updated when a profile is added or removed from the list as opposed to when the program is closed. This allows the list to be in sync while utilizing hotplugging. 2014-01-04 Travis Nickles Version 2.0 * Migrated profiles to use Qt key values as opposed to using native key code values. Allows for better cross-platform compatibility. Current joystick profiles will be migrated when first loaded by the program. * Program can now be compiled against SDL 2. * The Game Controller API provided by SDL 2 has been integrated into the application. The API is used to abstract various gamepads to a unified standard. Profiles made against the Game Controller API can be used with any controller that is supported. Unsupported controllers will have to be mapped in the program. * A simple Game Controller mapping window has been made so people that are using an unsupported controller can map that controller so that it can be used with the Game Controller API. Any saved mapping string will be loaded into SDL when antimicro is first launched or when you select the "Update Joysticks" option in the main window. * Any new saved profile will include the device type that it is associated with in the filename. Joysticks and game controllers use slightly different file specifications. * Joystick hotplugging support has been added thanks to SDL 2. * On Windows, XInput support is now available. This allows the Xbox 360 controller guide button to be usable and both gamepad triggers can be used at the same time. Previously, only DirectInput was being used so both triggers were being mapped to one axis so they would negate each other if used at the same time. This problem would really affect people trying to play Call of Duty with a 360 controller when the "Hold Aim Down the Sight" option is enabled in the game. * The list of recent profiles is now tied to a joystick GUID or joystick name if the GUID is not available (compiled against SDL 1.2). * Program options window has been made. For right now, it is only being used to allow users to be able to disable Game Controller integration for specific controllers. * Mouse events are queued before a mouse event is sent to the system. This allows for smoother diagonal mouse movement. This really helped improve camera control for me in Warsow. * Key checker dialog has been made so you can check the alias values that are being used for keyboard keys. This is mainly for debugging purposes. If you find that a keyboard key that you use does not have a built-in alias, please let me know so an alias can be added. Although, the key can still be used in the program and saved to a profile. The major downside is that a profile that uses an unsupported key will not be cross-platform compatible. 2013-12-13 Travis Nickles Version 1.2 * Improved while held set changing so that the program should not get stuck on the wrong set. The changes made should behave roughly like the old while held workaround that used turbo. * Windows port of antimicro has been made. * Tweaked code used for button presses and releases in order to improve responsiveness. * Allow time-dependent action slots to have an interval as low as 0.01 seconds. * Tweaked Release action slot. Release slots can now be placed at the beginning of the assigned slots. This can be useful for Tap and Hold slot configurations. * Pause slots can now be used with Release slots. * Profiles can be removed from the recent configs list. * Spring mouse mode preview has now been enabled. * Mouse speed modifier action slot has been added. This can be used to modify the mouse speed settings used with any controller element while the slot is active. The setting will modify the mouse speed by the percentage that is specified. The mouse speed modifier can be used to allow for the mouse speed to be slowed down while sniping. * Button and action names have been added. Names can be used to describe the action that a slot sequence performs in the game. * Mouse wheel buttons are now used as a form of mouse movement. Mouse wheel scrolling is now possible without using turbo. The speed that the wheel is rotated can be specified in the mouse settings dialog window. * Added support for two extra mouse buttons. * A new controller properties window has been made. This window shows various bits of information provided by SDL about a controller as well as the current values of all the controller elements. * Added quick assign functionality for sticks and virtual dpads. * Windows version of the program now uses LocalAppData variable to know where to place the program's settings file. * New translations provided by the translation team. 2013-10-03 Travis Nickles Version 1.1 * Added spring mouse mode. This mode is used to move the mouse cursor from the center of the screen based on how much an axis has been moved from the dead zone. The mouse cursor will be returned to the center of the screen when the axis is released. * Added mouse curve options from QJoyPad. * Tweaked mouse movement in cursor mode to improve axis responsiveness and to allow mouse movement to be less jittery. * Added optional mouse smoothing for a further reduction in jitter in exchange for slightly delayed responsiveness. * Moved various mouse settings into a new dialog window. Several other dialog windows have been changed to point to the new dialog window to allow for mouse setting adjustments. * Added an option to start the program hidden. * Tray menu has been tweaked to allow configuration profiles to be disabled. A blank new profile will be enabled in the program for a controller. This is equivalent to selecting in the main window combobox. * Serbian translation provided by Jay Alexander Fleming. * Brazilian Portuguese translation provided by VaGNaroK. 2013-07-12 Travis Nickles Version 1.0 * 8-way controls have been implemented. This allows keys to be mapped to the diagonal directions of controller sticks and dpads. 8-way controls allow rougelike games to be playable. * Virtual Dpad support has been added. Axes and buttons can be mapped to a virtual dpad. This is useful for mapping dpads that are detected as a pair of axes in SDL. * A Quick Set option has been added. Using the Quick Set option, you can press a button on the controller and the program will bring up the edit window for that specific button. The button can then be mapped to an assignment from the edit window. The Quick Set option also works for axes, controller sticks, and dpads. This is more of a convenience function than anything but I have found it really useful since implementing it. * Main interface button text is now updated whenever the assigned slots are changed. This allows the buttons' text to be in sync in many situations that was not possible before. * Toggle and Turbo can be used together to create automated key macros for use in MMORPGs. \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* AntiMicroX-antimicrox-2888bf6/CMakeLists.txt000066400000000000000000000547241377703515000210370ustar00rootroot00000000000000## antimicrox Gamepad to KB+M event mapper ## Copyright (C) 2015 Travis Nickles ## Copyright (C) 2020 Jagoda Górska ## Copyright (C) 2020 Paweł Kotiuk ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program. If not, see . cmake_minimum_required(VERSION 3.6) set(QT_REQUIRED_VERSION 5.8) set(SDL_REQUIRED_VERSION 2.0.6) project(antimicrox) if(POLICY CMP0071) cmake_policy(SET CMP0071 NEW) endif() if(UNIX) find_package(ECM REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_DIR}) endif(UNIX) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" "${CMAKE_ROOT}/Modules") set(CMAKE_INCLUDE_CURRENT_DIR ON) if(UNIX AND NOT APPLE AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "force cmake prefix to be set for /usr" FORCE) endif(UNIX AND NOT APPLE AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) include(CheckCXXCompilerFlag) include(GNUInstallDirs) if(UNIX) include(ECMInstallIcons) endif(UNIX) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) if(COMPILER_SUPPORTS_CXX11) if(NOT WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -std=c++11") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") endif() else() message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif(COMPILER_SUPPORTS_CXX11) # The version number. set(ANTIMICROX_MAJOR_VERSION 3) set(ANTIMICROX_MINOR_VERSION 1) set(ANTIMICROX_PATCH_VERSION 4) option(WITH_TESTS "Allow tests for classes" OFF) if(WITH_TESTS) message("Tests enabled") endif(WITH_TESTS) if(UNIX) option(WITH_X11 "Compile with support for X11." ON) option(WITH_UINPUT "Compile with support for uinput. uinput will be usable to simulate events." ON) option(WITH_XTEST "Compile with support for XTest. XTest will be usable to simulate events." ON) option(APPDATA "Build project with AppData file support." ON) endif(UNIX) option(UPDATE_TRANSLATIONS "Call lupdate to update translation files from source." OFF) option(TRANS_KEEP_OBSOLETE "Add -noobsolete option to lupdate command to get rid of old text entries" OFF) option(ATTACH_FAKE_CLASSES "Fake classes can be used in application to tests functionalities" OFF) if(UNIX) find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) # find_package(SDL2 REQUIRED) -> will fail on some systems if(WITH_X11) find_package(X11 REQUIRED) endif(WITH_X11) if(WITH_XTEST AND NOT WITH_X11) set(WITH_XTEST OFF) message("Cannot use XTest without X11. Disabling XTest support.") endif(WITH_XTEST AND NOT WITH_X11) if(WITH_XTEST) message("XTest support allowed for simulating events.") endif(WITH_XTEST) if(WITH_UINPUT) message("uinput support allowed for simulating events.") endif(WITH_UINPUT) if(NOT WITH_XTEST AND NOT WITH_UINPUT) message(FATAL_ERROR "No system is defined for simulating events.") endif(NOT WITH_XTEST AND NOT WITH_UINPUT) endif(UNIX) set(antimicrox_MAIN src/main.cpp) set(antimicrox_SOURCES src/aboutdialog.cpp src/addeditautoprofiledialog.cpp src/advancebuttondialog.cpp src/advancestickassignmentdialog.cpp src/antimicrosettings.cpp src/antkeymapper.cpp src/applaunchhelper.cpp src/autoprofileinfo.cpp src/axiseditdialog.cpp src/axisvaluebox.cpp src/buttoneditdialog.cpp src/calibration.cpp src/commandlineutility.cpp src/common.cpp src/dpadcontextmenu.cpp src/dpadeditdialog.cpp src/dpadpushbutton.cpp src/dpadpushbuttongroup.cpp src/editalldefaultautoprofiledialog.cpp src/event.cpp src/eventhandlerfactory.cpp src/eventhandlers/baseeventhandler.cpp src/extraprofilesettingsdialog.cpp src/flashbuttonwidget.cpp src/gamecontroller/gamecontroller.cpp src/gamecontroller/gamecontrollerdpad.cpp src/gamecontroller/gamecontrollerset.cpp src/gamecontroller/gamecontrollertrigger.cpp src/gamecontroller/gamecontrollertriggerbutton.cpp src/gamecontroller/xml/gamecontrollerdpadxml.cpp src/gamecontroller/xml/gamecontrollertriggerxml.cpp src/gamecontroller/xml/gamecontrollerxml.cpp src/gamecontrollerexample.cpp src/gamecontrollermappingdialog.cpp src/globalvariables.cpp src/inputdaemon.cpp src/inputdevice.cpp src/inputdevicebitarraystatus.cpp src/joyaxis.cpp src/joyaxiscontextmenu.cpp src/joyaxiswidget.cpp src/joybutton.cpp src/joybuttoncontextmenu.cpp src/joybuttonmousehelper.cpp src/joybuttonslot.cpp src/joybuttonstatusbox.cpp src/joybuttontypes/joyaxisbutton.cpp src/joybuttontypes/joycontrolstickbutton.cpp src/joybuttontypes/joycontrolstickmodifierbutton.cpp src/joybuttontypes/joydpadbutton.cpp src/joybuttontypes/joygradientbutton.cpp src/joybuttonwidget.cpp src/joycontrolstick.cpp src/joycontrolstickbuttonpushbutton.cpp src/joycontrolstickcontextmenu.cpp src/joycontrolstickeditdialog.cpp src/joycontrolstickpushbutton.cpp src/joycontrolstickstatusbox.cpp src/joydpad.cpp src/joydpadbuttonwidget.cpp src/joystick.cpp src/joystickstatuswindow.cpp src/joytabwidget.cpp src/joytabwidgetcontainer.cpp src/keyboard/virtualkeyboardmousewidget.cpp src/keyboard/virtualkeypushbutton.cpp src/keyboard/virtualmousepushbutton.cpp src/localantimicroserver.cpp src/logger.cpp src/mainsettingsdialog.cpp src/mainwindow.cpp src/messagehandler.cpp src/mousedialog/mouseaxissettingsdialog.cpp src/mousedialog/mousebuttonsettingsdialog.cpp src/mousedialog/mousecontrolsticksettingsdialog.cpp src/mousedialog/mousedpadsettingsdialog.cpp src/mousedialog/springmoderegionpreview.cpp src/mousedialog/uihelpers/mouseaxissettingsdialoghelper.cpp src/mousedialog/uihelpers/mousebuttonsettingsdialoghelper.cpp src/mousedialog/uihelpers/mousecontrolsticksettingsdialoghelper.cpp src/mousedialog/uihelpers/mousedpadsettingsdialoghelper.cpp src/mousehelper.cpp src/mousesettingsdialog.cpp src/qkeydisplaydialog.cpp src/qtkeymapperbase.cpp src/quicksetdialog.cpp src/sdleventreader.cpp src/setaxisthrottledialog.cpp src/setjoystick.cpp src/setnamesdialog.cpp src/simplekeygrabberbutton.cpp src/slotitemlistwidget.cpp src/stickpushbuttongroup.cpp src/uihelpers/advancebuttondialoghelper.cpp src/uihelpers/buttoneditdialoghelper.cpp src/uihelpers/dpadcontextmenuhelper.cpp src/uihelpers/dpadeditdialoghelper.cpp src/uihelpers/gamecontrollermappingdialoghelper.cpp src/uihelpers/joyaxiscontextmenuhelper.cpp src/uihelpers/joycontrolstickcontextmenuhelper.cpp src/uihelpers/joycontrolstickeditdialoghelper.cpp src/uihelpers/joytabwidgethelper.cpp src/vdpad.cpp src/xml/inputdevicexml.cpp src/xml/joyaxisxml.cpp src/xml/joybuttonslotxml.cpp src/xml/joybuttonxml.cpp src/xml/joydpadxml.cpp src/xml/setjoystickxml.cpp src/xmlconfigmigration.cpp src/xmlconfigreader.cpp src/xmlconfigwriter.cpp ) set(antimicrox_HEADERS src/aboutdialog.h src/addeditautoprofiledialog.h src/advancebuttondialog.h src/advancestickassignmentdialog.h src/antimicrosettings.h src/antkeymapper.h src/applaunchhelper.h src/autoprofileinfo.h src/axiseditdialog.h src/axisvaluebox.h src/buttoneditdialog.h src/calibration.h src/commandlineutility.h src/dpadcontextmenu.h src/dpadeditdialog.h src/dpadpushbutton.h src/dpadpushbuttongroup.h src/editalldefaultautoprofiledialog.h src/eventhandlerfactory.h src/eventhandlers/baseeventhandler.h src/extraprofilesettingsdialog.h src/flashbuttonwidget.h src/gamecontroller/gamecontroller.h src/gamecontroller/gamecontrollerdpad.h src/gamecontroller/gamecontrollerset.h src/gamecontroller/gamecontrollertrigger.h src/gamecontroller/gamecontrollertriggerbutton.h src/gamecontroller/xml/gamecontrollerdpadxml.h src/gamecontroller/xml/gamecontrollertriggerxml.h src/gamecontroller/xml/gamecontrollerxml.h src/gamecontrollerexample.h src/gamecontrollermappingdialog.h src/globalvariables.h src/inputdaemon.h src/inputdevice.h src/inputdevicebitarraystatus.h src/joyaxis.h src/joyaxiscontextmenu.h src/joyaxiswidget.h src/joybutton.h src/joybuttoncontextmenu.h src/joybuttonmousehelper.h src/joybuttonslot.h src/joybuttonstatusbox.h src/joybuttontypes/joyaxisbutton.h src/joybuttontypes/joycontrolstickbutton.h src/joybuttontypes/joycontrolstickmodifierbutton.h src/joybuttontypes/joydpadbutton.h src/joybuttontypes/joygradientbutton.h src/joybuttonwidget.h src/joycontrolstick.h src/joycontrolstickbuttonpushbutton.h src/joycontrolstickcontextmenu.h src/joycontrolstickeditdialog.h src/joycontrolstickpushbutton.h src/joycontrolstickstatusbox.h src/joydpad.h src/joydpadbuttonwidget.h src/joystick.h src/joystickstatuswindow.h src/joytabwidget.h src/joytabwidgetcontainer.h src/keyboard/virtualkeyboardmousewidget.h src/keyboard/virtualkeypushbutton.h src/keyboard/virtualmousepushbutton.h src/localantimicroserver.h src/logger.h src/mainsettingsdialog.h src/mainwindow.h src/messagehandler.h src/mousedialog/mouseaxissettingsdialog.h src/mousedialog/mousebuttonsettingsdialog.h src/mousedialog/mousecontrolsticksettingsdialog.h src/mousedialog/mousedpadsettingsdialog.h src/mousedialog/springmoderegionpreview.h src/mousedialog/uihelpers/mouseaxissettingsdialoghelper.h src/mousedialog/uihelpers/mousebuttonsettingsdialoghelper.h src/mousedialog/uihelpers/mousecontrolsticksettingsdialoghelper.h src/mousedialog/uihelpers/mousedpadsettingsdialoghelper.h src/mousehelper.h src/mousesettingsdialog.h src/qkeydisplaydialog.h src/qtkeymapperbase.h src/quicksetdialog.h src/sdleventreader.h src/setaxisthrottledialog.h src/setjoystick.h src/setnamesdialog.h src/simplekeygrabberbutton.h src/slotitemlistwidget.h src/stickpushbuttongroup.h src/uihelpers/advancebuttondialoghelper.h src/uihelpers/buttoneditdialoghelper.h src/uihelpers/dpadcontextmenuhelper.h src/uihelpers/dpadeditdialoghelper.h src/uihelpers/gamecontrollermappingdialoghelper.h src/uihelpers/joyaxiscontextmenuhelper.h src/uihelpers/joycontrolstickcontextmenuhelper.h src/uihelpers/joycontrolstickeditdialoghelper.h src/uihelpers/joytabwidgethelper.h src/vdpad.h src/xml/inputdevicexml.h src/xml/joyaxisxml.h src/xml/joybuttonslotxml.h src/xml/joybuttonxml.h src/xml/joydpadxml.h src/xml/setjoystickxml.h src/xmlconfigmigration.h src/xmlconfigreader.h src/xmlconfigwriter.h ) if(ATTACH_FAKE_CLASSES) LIST(APPEND antimicrox_SOURCES src/fakeclasses/xbox360wireless.cpp ) LIST(APPEND antimicrox_HEADERS src/fakeclasses/xbox360wireless.h ) endif(ATTACH_FAKE_CLASSES) set(antimicrox_FORMS src/aboutdialog.ui src/addeditautoprofiledialog.ui src/advancebuttondialog.ui src/advancestickassignmentdialog.ui src/axiseditdialog.ui src/buttoneditdialog.ui src/calibration.ui src/capturedwindowinfodialog.ui src/dpadeditdialog.ui src/editalldefaultautoprofiledialog.ui src/extraprofilesettingsdialog.ui src/gamecontrollermappingdialog.ui src/joycontrolstickeditdialog.ui src/joystickstatuswindow.ui src/mainsettingsdialog.ui src/mainwindow.ui src/mousesettingsdialog.ui src/qkeydisplaydialog.ui src/quicksetdialog.ui src/setaxisthrottledialog.ui src/setnamesdialog.ui ) set(antimicrox_RESOURCES src/resources.qrc) # Platform dependent files. if(UNIX) if(WITH_X11) LIST(APPEND antimicrox_SOURCES src/x11extras.cpp src/qtx11keymapper.cpp src/unixcapturewindowutility.cpp src/autoprofilewatcher.cpp src/capturedwindowinfodialog.cpp ) LIST(APPEND antimicrox_HEADERS src/x11extras.h src/qtx11keymapper.h src/unixcapturewindowutility.h src/autoprofilewatcher.h src/capturedwindowinfodialog.h ) if(WITH_XTEST) LIST(APPEND antimicrox_SOURCES src/eventhandlers/xtesteventhandler.cpp) LIST(APPEND antimicrox_HEADERS src/eventhandlers/xtesteventhandler.h) endif(WITH_XTEST) endif(WITH_X11) if(WITH_UINPUT) LIST(APPEND antimicrox_SOURCES src/qtuinputkeymapper.cpp src/uinputhelper.cpp src/eventhandlers/uinputeventhandler.cpp ) LIST(APPEND antimicrox_HEADERS src/qtuinputkeymapper.h src/uinputhelper.h src/eventhandlers/uinputeventhandler.h ) endif(WITH_UINPUT) endif(UNIX) if(UNIX) if(WITH_X11) add_definitions(-DWITH_X11) endif(WITH_X11) if(WITH_XTEST) add_definitions(-DWITH_XTEST) endif(WITH_XTEST) if(WITH_UINPUT) add_definitions(-DWITH_UINPUT) endif(WITH_UINPUT) endif(UNIX) if(UNIX) find_package(Qt5Widgets ${QT_REQUIRED_VERSION} REQUIRED) find_package(Qt5Core ${QT_REQUIRED_VERSION} REQUIRED) find_package(Qt5Gui ${QT_REQUIRED_VERSION} REQUIRED) find_package(Qt5Network ${QT_REQUIRED_VERSION} REQUIRED) find_package(Qt5LinguistTools ${QT_REQUIRED_VERSION} REQUIRED) find_package(Qt5Concurrent ${QT_REQUIRED_VERSION} REQUIRED) #find_package(Qt5Test REQUIRED) QT5_WRAP_CPP(antimicrox_HEADERS_MOC ${antimicrox_HEADERS}) QT5_WRAP_UI(antimicrox_FORMS_HEADERS ${antimicrox_FORMS}) QT5_ADD_RESOURCES(antimicrox_RESOURCES_RCC ${antimicrox_RESOURCES}) add_subdirectory("share/antimicrox/translations") set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif(UNIX) # linker libraries LIST(APPEND QT_LIBS Qt5::Core) LIST(APPEND QT_LIBS Qt5::Gui) LIST(APPEND QT_LIBS Qt5::Widgets) LIST(APPEND QT_LIBS Qt5::Concurrent) LIST(APPEND QT_LIBS Qt5::Network) if(UNIX) if(WITH_X11) LIST(APPEND X11_LIBS ${X11_X11_LIB}) LIST(APPEND X11_LIBS ${X11_Xi_LIB}) endif(WITH_X11) if(WITH_XTEST) LIST(APPEND EXTRA_LIBS ${X11_XTest_LIB}) endif(WITH_XTEST) # necessary ifwe use find_package for SDL2 # if(NOT DEFINED SDL2_LIBRARIES) # set(SDL2_LIBRARIES SDL2::SDL2) # endif() endif(UNIX) include_directories( ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/src" ${PROJECT_SOURCE_DIR} "${PROJECT_SOURCE_DIR}/src" ) if(UNIX) # Store executable in a bin subdir. Needed here so translations can be loaded. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") endif(UNIX) add_executable(antimicrox ${antimicrox_MAIN} ${antimicrox_HEADERS_MOC} ${antimicrox_SOURCES} ${antimicrox_FORMS_HEADERS} ${antimicrox_RESOURCES_RCC} ) target_link_libraries(antimicrox ${QT_LIBS} ${X11_LIBS} ${SDL2_LIBRARIES} ${EXTRA_LIBS} ) # Specify out directory for final executable. if(UNIX) install(TARGETS antimicrox RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") # install(TARGETS antilib DESTINATION "${CMAKE_INSTALL_LIBDIR}") install(FILES ${antimicrox_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/antimicrox") endif(UNIX) if(UNIX) ecm_install_icons(ICONS src/icons/application/16x16/apps/16-apps-io.github.antimicrox.antimicrox.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) ecm_install_icons(ICONS src/icons/application/24x24/apps/24-apps-io.github.antimicrox.antimicrox.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) ecm_install_icons(ICONS src/icons/application/32x32/apps/32-apps-io.github.antimicrox.antimicrox.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) ecm_install_icons(ICONS src/icons/application/48x48/apps/48-apps-io.github.antimicrox.antimicrox.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) ecm_install_icons(ICONS src/icons/application/64x64/apps/64-apps-io.github.antimicrox.antimicrox.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) ecm_install_icons(ICONS src/icons/application/128x128/apps/128-apps-io.github.antimicrox.antimicrox.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) ecm_install_icons(ICONS src/icons/application/scalable/apps/sc-apps-io.github.antimicrox.antimicrox.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) ecm_install_icons(ICONS src/images/breeze_themed/48-apps-antimicrox_trayicon.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons THEME breeze) ecm_install_icons(ICONS src/images/48-apps-antimicrox_trayicon.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons) install(FILES CHANGELOG.md DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/doc/antimicrox") install(FILES other/io.github.antimicrox.antimicrox.desktop DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") install(FILES other/io.github.antimicrox.antimicrox.xml DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/mime/packages") # Copy current Changelog file to location that the resource file expects. install(FILES CHANGELOG.md DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/antimicrox") endif(UNIX) # Add man page for *nix platforms. if(UNIX) add_subdirectory(other) # Only way to force install target to be dependent on manpage. install(CODE "execute_process(COMMAND ${CMAKE_BUILD_TOOL} manpage WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\")") if(APPDATA) # Only way to force install target to be dependent on appdata. install(CODE "execute_process(COMMAND ${CMAKE_BUILD_TOOL} appdata WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\")") endif(APPDATA) endif(UNIX) # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) # Only way to force install target to be dependent on updateqm. install(CODE "execute_process(COMMAND ${CMAKE_BUILD_TOOL} updateqm WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\")") # Use this to use some variables created here in the actual project. # Modify the config.h.in file using the appropriate variables. configure_file( "${PROJECT_SOURCE_DIR}/src/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/src/) if(WITH_TESTS) enable_testing() add_subdirectory(tests) endif(WITH_TESTS) #building package using CPack include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Program used to map keyboard keys and mouse controls to a gamepad.") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGE_VERSION_MAJOR "${ANTIMICROX_MAJOR_VERSION}") set(CPACK_PACKAGE_VERSION_MINOR "${ANTIMICROX_MINOR_VERSION}") set(CPACK_PACKAGE_VERSION_PATCH "${ANTIMICROX_PATCH_VERSION}") set(CPACK_PACKAGE_FILE_NAME "antimicrox-${ANTIMICROX_MAJOR_VERSION}.${ANTIMICROX_MINOR_VERSION}.${ANTIMICROX_PATCH_VERSION}-${CMAKE_HOST_SYSTEM_PROCESSOR}") set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") if(UNIX) set(CPACK_STRIP_FILES "") set(CPACK_SOURCE_STRIP_FILES "") endif() # Building .deb package if(CPACK_GENERATOR STREQUAL "DEB") set(CPACK_DEBIAN_PACKAGE_DEPENDS "qtbase5-dev (>= ${QT_REQUIRED_VERSION}), libsdl2-2.0-0 (>= ${SDL_REQUIRED_VERSION}), libc6") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "pktiuk ") set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "AntiMicroX is a graphical program used to map gamepad buttons to keyboard, mouse, scripts and macros. It is a new fork of discontinued AntiMicro.") message("Preparing documentation for DEB package") add_custom_target(package_docummentation ALL) #Compress changelog and save it as share/doc/xournalpp/changelog.Debian.gz add_custom_command(TARGET package_docummentation PRE_BUILD COMMAND gzip -c -9 -n "${PROJECT_SOURCE_DIR}/CHANGELOG.md" > "changelog.gz" VERBATIM) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/changelog.gz" DESTINATION "share/doc/antimicrox/") #Strip binaries from unnecessary notes, comments, etc add_custom_command(TARGET antimicrox POST_BUILD COMMAND strip --strip-unneeded --remove-section=.comment --remove-section=.note "${CMAKE_CURRENT_BINARY_DIR}/bin/antimicrox" VERBATIM) endif() set(CPACK_PACKAGE_EXECUTABLES "antimicrox" "antimicrox") include(CPack) AntiMicroX-antimicrox-2888bf6/LICENSE000066400000000000000000001045151377703515000172760ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . AntiMicroX-antimicrox-2888bf6/ProfileTips.md000066400000000000000000000077721377703515000210620ustar00rootroot00000000000000Profile Tips ============ ## Sticks ### Dead Zones The XInput standard of 8,000 will typically be used in profiles for analog sticks. For an Xbox 360 controller, that value tends to be the best minimum value to ensure that no unintentional events are produced due to what position a stick will be centered at. When using a different controller, you will likely want to play with the value of the dead zone used for the analog sticks and find what works best for your controller. As an example, when I make profiles for my Logitech F310 gamepad, I find that using a dead zone value of 2,000 for the analog sticks works best. ### Left Stick (Keyboard) The default diagonal range of 45 degrees is recommended when mapping keyboard keys to an analog stick when using the **standard** stick mode. If only one action should ever occur at a time and the diagonal direction doesn't matter as much, you might want to look into **4-way cardinal** stick mode. That can be useful for navigating menus or mapping weapon hotkeys to an analog stick. Some games will overreact when mapping WASD or other keyboard keys to an analog stick. This is mainly due to how quickly directions can be changed especially if you have the stick positioned right around where a diagonal zone resides. If you encounter problems in game or you just want to make movement a little more definitive, you can adjust the **stick delay** value used for that stick. That will cause direction changes to be slightly delayed. Even setting the value to 0.01 seconds can greatly increase control in some games. ### Right Stick (Mouse) To allow for better mouse control with an analog stick, it is recommended that you use a diagonal range of at least 65 degrees instead of the normal 45 degree value. If you want more twitchy mouse control, you will likely want to set the diagonal range of the stick to 89 degrees or 90 degrees. This will minimize the range used for the absolute cardinal directions. Another tip that will allow for more twitchy mouse control is related to the dead zone used for the analog stick. Decreasing the value used for the stick dead zone can help make mouse control feel more responsive than when using the standard value of 8,000 even when using an Xbox 360 controller. Based on my experience, even decreasing the value to 6,000 can make a huge difference. The big compromise is that there might be some mouse cursor drift if the analog stick does not center back to the assigned dead zone. On my Xbox 360 controller, I find that the stick can get stuck slightly in the southwest region of the stick; the other directions don't have this issue. However, the mouse cursor drift is very minimal and you can easily compensate while playing a game. It doesn't hinder gameplay and the benefit obtained far outweights the minor problem. One final thing that you can do to make mouse movement more twitchy is to enable extra acceleration for mouse events. Changing the **extra duration** of acceleration will have the biggest impact on mouse movement. Increasing the maximum extra duration of the acceleration will loosen the mouse movement. Changing the **multiplier** is another option that will change how mouse movement behaves. One final option that can be changed is to use a different curve for extra acceleration. **Linear** is still the default setting since it was the only option available for many versions but I find myself using **Ease Out Quad** lately. Besides altering the final multiplier used, it also changes the final duration experienced. With all the options available for extra acceleration, you will have an easier time performing a quick 180 degree turn while still having precision on the low end of a stick for aiming at targets. ## Action Names It is generally recommended that you specify action names when making profiles that you will share with other people. This will allow other people to more easily decipher what buttons are used for in a profile. Specifying action names can also be a helpful reminder for yourself in order to document a more complex action. AntiMicroX-antimicrox-2888bf6/README.md000066400000000000000000000167701377703515000175550ustar00rootroot00000000000000# Icon AntiMicroX 1. [Description](#description) 2. [License](#license) 3. [Installation](#installation) 4. [Wiki](#wiki) 5. [Command Line](#command-line) 6. [Testing Under Linux](#testing-under-linux) 7. [AntiMicroX Profiles](#antimicrox-profiles) 8. [Support](#support) 9. [Bugs](#bugs) 10. [Shoutout](#shoutout) 11. [Credits](#credits) 12. [Participation in the translation of AntiMicroX](#participation-in-the-translation-of-antimicrox) ## Description AntiMicroX is a graphical program used to map gamepad keys to keyboard, mouse, scripts and macros. You can use this program to control any desktop application with a gamepad on Linux. It can be also used for generating SDL2 configuration (useful for mapping atypical gamepads to generic ones like xbox360). Currently we don't support Wayland ([#32](https://github.com/AntiMicroX/antimicrox/issues/32)) - your system has to be running X.org in order to run this program. It allows mapping of gamepads/joystick buttons to: - keyboard buttons - mouse buttons and moves - scripts and executables - macros consisting of elements mentioned above This program is currently supported under various Linux distributions. This application is continuation of project called `AntiMicro`, which was later abandoned and revived by juliagoda. Legacy repositories: - First AntiMicroX repository: https://github.com/juliagoda/antimicroX - Second, maintained by organization: https://github.com/AntiMicro/antimicro - First, original AntiMicro repository: https://github.com/Ryochan7/antimicro **Screenshots:** Disclaimer: Theme may depend on your system configuration.
Main Window Mapping
Calibration Advanced settings
## License This program is licensed under the GPL v.3. Please read the LICENSE text document included with the source code if you would like to read the terms of the license. The license can also be found online at http://www.gnu.org/licenses/gpl.txt ## Installation ### Flatpak The flatpak version is distributed on Flathub, and runs on most major Linux distributions. See instructions here: [Flathub application page](https://flathub.org/apps/details/io.github.antimicrox.antimicrox) If you have Flathub [set up](https://flatpak.org/setup/) already: ``` flatpak install flathub io.github.antimicrox.antimicrox ``` ### Fedora ``` dnf install antimicrox ``` ### Arch Linux or Arch Linux based distributions: ``` trizen -S antimicrox ``` **or** pre-built version can de downloaded from unofficial repository called [chaotic-aur](https://lonewolf.pedrohlc.com/chaotic-aur/). Append (one of listed mirrors) to `/etc/pacman.conf`: ```bash # Brazil Server = http://lonewolf-builder.duckdns.org/$repo/$arch # Germany Server = http://chaotic.bangl.de/$repo/$arch # USA (Cloudflare cached) Server = https://repo.kitsuna.net/$arch # Netherlands Server = https://chaotic.tn.dedyn.io/$arch ``` To check signature, add keys: ```bash sudo pacman-key --keyserver hkp://keyserver.ubuntu.com -r 3056513887B78AEB 8A9E14A07010F7E3 sudo pacman-key --lsign-key 3056513887B78AEB sudo pacman-key --lsign-key 8A9E14A07010F7E3 ``` Install package ```bash pacman -S antimicrox ``` ### Debian/Ubuntu-based distributions: Download from the [release site](https://github.com/AntiMicroX/antimicrox/releases) and install `.deb` package. ### AppImage Download from the [release site](https://github.com/AntiMicroX/antimicrox/releases). It is recommended to use [AppImageLauncher](https://github.com/TheAssassin/AppImageLauncher) with this package. ### Building Yourself List of required dependencies and build instructions can be found [here](./BUILDING.md). ## Command Line Run `antimicrox --help` or read `man antimicrox` for command-line parameters. ## Wiki [Look here](https://github.com/juliagoda/antimicroX/wiki) ## Testing Under Linux If you are having problems with antimicrox detecting a controller or detecting all axes and buttons, you should test the controller outside of antimicrox to check if the problem is with antimicrox or not. The two endorsed programs for testing gamepads outside of antimicrox are **sdl-jstest** (**sdl2-jstest**) and **evtest**. SDL2 utilizes evdev on Linux so performing testing with older programs that use joydev won't be as helpful since some devices behave a bit differently between the two systems. Another method also exist, which can be found [here](https://github.com/juliagoda/SDL_JoystickButtonNames). ## AntiMicroX Profiles If you would like to send the profile you are using for your application or find something for yourself, [here](https://github.com/AntiMicroX/antimicrox-profiles) is the forked repository. If you want to report a bug, ask a question or share a suggestion, you can do that on the antimicrox page or on the [antimicrox-profiles](https://github.com/AntiMicroX/antimicrox-profiles) page. ## Support In order to obtain support, you can post an issue [here](https://github.com/AntiMicroX/antimicrox/issues). ## Bugs Application's bugs will be fixed. There are created tests for detecting bugs. Of course, I'm open to proposals or questions from users. ## Shoutout A big, original inspiration for this program was the program QJoyPad. ## Credits ### Contributors Full list is available [here](https://github.com/AntiMicroX/antimicrox/graphs/contributors) ### Package Maintainers **Distro** | **Maintainer** | **Package** | | :--------- | :------------- | :----------- | | Arch Linux | frealgagu | [antimicrox](https://aur.archlinux.org/packages/antimicrox/) AUR | | Arch Linux | FabioLolix | [antimicrox-git](https://aur.archlinux.org/packages/antimicrox-git) AUR | | Fedora Linux | [gombosg](https://github.com/gombosg) | antimicrox | | Flatpak | [gombosg](https://github.com/gombosg) | [io.github.antimicrox.antimicrox](https://flathub.org/apps/details/io.github.antimicrox.antimicrox) | ### Translators VaGNaroK - Brazilian Portuguese zzpxyx - Chinese Belleguic Terence - French Leonard Koenig - German phob - German tou omiya - Japanese Dmitriy Koshel - Russian Jay Alexander Fleming - Serbian burunduk - Ukrainian Flavio HR - Spanish WAZAAAAA - - Italian juliagoda - Polish ## Participation in the translation of AntiMicroX If you want to participate in the translation of the program, but your language is not yet on the support list. Please contact us. However, if your language is already supported in the program, you must have the Qt Linguist program installed, which is usually included in the qt5-tools package, to conveniently translate the application. However, before you do that, make sure that you don't already have this program installed. All you have to do is open it, and then use it to open a file with the ts extension. If a red exclamation mark appears in the translation field, it means that your translation does not end with the same sign as the original content. Try to place commas or dots in appropriate places and often save your progress. AntiMicroX-antimicrox-2888bf6/Resources.txt000066400000000000000000000047571377703515000210130ustar00rootroot000000000000001) Generate GUIDs for use in .wxs files http://www.guidgen.com/ 2) Site used to check out the behavior of different easing curves http://easings.net/ 3) Repository of code examples for many different easing curves https://github.com/jesusgollonet/ofpennereasing 4) Site used to generate acceleration curve images http://rechneronline.de/function-graphs/ 5) Check GUID of your connected controller, controller name, vendor, product, product version and buttons. https://github.com/juliagoda/SDL_JoystickButtonNames 6) Check ASCII character https://www.tau.ac.il/~flaxer/edu/course/computerappl/ASCII_Characters.htm http://www.asciitable.com 7) Device registers in C https://www.embedded.com/design/programming-languages-and-tools/4432746/Device-registers-in-C https://samypesse.gitbooks.io/how-to-create-an-operating-system/Chapter-8/ 8) Regex tutorial  https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285 9) Appveyor documentation and examples https://www.appveyor.com/docs/getting-started-with-appveyor-for-linux/ https://www.appveyor.com/docs/appveyor-yml/ https://www.appveyor.com/docs/windows-images-software/ https://github.com/vlc-qt/examples/blob/master/.appveyor.yml https://github.com/Yubico/yubioath-desktop/blob/master/appveyor.yml 10) Appveyor validator (log in needed) https://ci.appveyor.com/tools/validate-yaml 11) Travis documentation and example https://docs.travis-ci.com/user/multi-os/ https://docs.travis-ci.com/user/installing-dependencies/ https://www.codementor.io/amratab/travis-ci-integration-for-github-owctkf8js https://eng.localytics.com/best-practices-and-common-mistakes-with-travis-ci/ https://github.com/glfw/glfw/blob/master/.travis.yml https://github.com/qterm/qterm/blob/master/.travis.yml 12) Travis validation https://support.travis-ci.com/hc/en-us/articles/115002904174-Validating-travis-yml-files 13) Hex to string converter http://string-functions.com/hex-string.aspx 14) Boolean Expressions Simplificator https://www.dcode.fr/boolean-expressions-calculator 15) Diff online checker - online diff tool to compare text differences between two text files https://www.diffchecker.com/diff 16) create own icons, fonts, svg https://icomoon.io/app/#/select 17) Create icon theme https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#install_icons https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#example https://api.kde.org/ecm/module/ECMInstallIcons.html AntiMicroX-antimicrox-2888bf6/cmake_uninstall.cmake.in000066400000000000000000000020131377703515000230370ustar00rootroot00000000000000if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif(NOT "${rm_retval}" STREQUAL 0) else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") endforeach(file) AntiMicroX-antimicrox-2888bf6/other/000077500000000000000000000000001377703515000174045ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/other/40-uinput.rules000066400000000000000000000001011377703515000222150ustar00rootroot00000000000000SUBSYSTEM=="misc", KERNEL=="uinput", MODE="0660", GROUP="uinput" AntiMicroX-antimicrox-2888bf6/other/CMakeLists.txt000066400000000000000000000005031377703515000221420ustar00rootroot00000000000000add_subdirectory(appdata) add_custom_target(manpage) add_custom_command(TARGET manpage PRE_BUILD COMMAND gzip -c -9 -n "${PROJECT_SOURCE_DIR}/other/antimicrox.1" > "antimicrox.1.gz" VERBATIM ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/antimicrox.1.gz" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/man/man1") AntiMicroX-antimicrox-2888bf6/other/antimicrox.1000066400000000000000000000042241377703515000216450ustar00rootroot00000000000000.\" Manpage for antimicrox. .\" Contact juliagoda.pl@protonmail.com to correct errors or typos. .TH ANTIMICROX "1" "7 January 2020" "antimicrox 2.25" "User Commands" .SH NAME AntiMicroX \- map keyboard keys and mouse controls to a gamepad .SH SYNOPSIS .B antimicrox [\fIOPTION\fR] [\fIPROFILE\fR] .SH DESCRIPTION .PP AntiMicroX is a graphical program used to map gamepad buttons to keyboard, mouse, scripts and macros. However, you can use this program to control any desktop application with a gamepad. .TP \fB\-\-tray\fR launch program in system tray only .TP \fB\-\-no\-tray\fR launch program with the tray menu disabled .TP \fB\-h\fR, \fB\-\-help\fR display this help and exit .TP \fB\-v\fR, \fB\-\-version\fR output version information and exit .TP \fB\-\-profile\fR \fI\fR use specified profile as default for selected controllers. Defaults to all controllers. .TP \fB\-\-profile-controller\fR \fI\fR apply configuration file to a specific controller. can be an controller index, name, or GUID. .TP \fB\-\-hidden\fR launch program without the main window .TP \fB\-\-unload\fR \fI[]\fR unload currently enabled profile(s). Value can be a controller index, name, or GUID. .TP \fB\-\-startSet\fR \fI\fR \fI[]\fR start joysticks on a specific set. Value can be a controller index, name, or GUID. .TP \fB\-\-next\fR Advance profile loading set options. .TP \fB\-d\fR, \fB\-\-daemon\fR launch program as a daemon. .TP \fB\-\-log\-level\fR \fI{debug,info,warn}\fR Enable logging. Default: warn .TP \fB\-l\fR, \fB\-\-list\fR Print information about joysticks detected by SDL. .TP \fB\-\-map\fR \fI\fR Open game controller mapping window of selected controller. Value can be a controller index or GUID. .TP \fB\-\-eventgen\fR \fI{xtest,uinput}\fR Choose between using XTest support and uinput support for event generation. Default: xtest. .SH BUGS See https://github.com/AntiMicroX/antimicrox/issues .SH AUTHOR Jagoda Górska (juliagoda.pl@protonmail.com) Jeff Backus (jeff@jsbackus.com) Travis Nickles (nickles.travis@gmail.com) .SH "REPORTING BUGS" Report dir bugs to antimicrox issues page: https://github.com/AntiMicroX/antimicrox/issues AntiMicroX-antimicrox-2888bf6/other/appdata/000077500000000000000000000000001377703515000210165ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/other/appdata/CMakeLists.txt000066400000000000000000000015771377703515000235700ustar00rootroot00000000000000# Make appdata optional when installing an application. if(APPDATA) add_custom_target(appdata) file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/PO_files/") add_custom_command(TARGET appdata PRE_BUILD # Add an entry per language COMMAND msgfmt "${PROJECT_SOURCE_DIR}/other/appdata/PO_files/en.po" -o "${CMAKE_CURRENT_BINARY_DIR}/PO_files/en.mo" COMMAND itstool -i "${PROJECT_SOURCE_DIR}/other/appdata/appdata.its" -j "${PROJECT_SOURCE_DIR}/other/appdata/io.github.antimicrox.antimicrox.appdata.xml.in" -o "io.github.antimicrox.antimicrox.appdata.xml" "${CMAKE_CURRENT_BINARY_DIR}/PO_files/*.mo" ) # Only install an appdata file ifthe user requested to have one built. install(FILES "${CMAKE_CURRENT_BINARY_DIR}/io.github.antimicrox.antimicrox.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo") endif(APPDATA) AntiMicroX-antimicrox-2888bf6/other/appdata/PO_files/000077500000000000000000000000001377703515000225165ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/other/appdata/PO_files/en.po000066400000000000000000000064031377703515000234630ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2020-09-27 17:28+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #. (itstool) path: component/name #: io.github.antimicrox.antimicrox.appdata.xml.in:6 msgid "AntiMicroX" msgstr "" #. (itstool) path: component/summary #: io.github.antimicrox.antimicrox.appdata.xml.in:7 msgid "Graphical program used to map gamepad buttons to keyboard, mouse, scripts and macros." msgstr "" #. (itstool) path: description/p #: io.github.antimicrox.antimicrox.appdata.xml.in:9 msgid "AntiMicroX is a graphical program used to map gamepad buttons/joysticks to keyboard, mouse, scripts and macros. It can be also used for generating SLD2 configuration (useful for mapping atypical gamepads to generic ones like xbox360)." msgstr "" #. (itstool) path: ul/li #: io.github.antimicrox.antimicrox.appdata.xml.in:18 msgid "keyboard buttons" msgstr "" #. (itstool) path: ul/li #: io.github.antimicrox.antimicrox.appdata.xml.in:19 msgid "mouse buttons and moves" msgstr "" #. (itstool) path: ul/li #: io.github.antimicrox.antimicrox.appdata.xml.in:20 msgid "scripts and launching apps" msgstr "" #. (itstool) path: ul/li #: io.github.antimicrox.antimicrox.appdata.xml.in:21 msgid "macros consisting of elements mentioned above" msgstr "" #. (itstool) path: description/p #: io.github.antimicrox.antimicrox.appdata.xml.in:15 msgid "It allows mapping of gamepads/joystick buttons to: <_:ul-1/>" msgstr "" #. (itstool) path: description/p #: io.github.antimicrox.antimicrox.appdata.xml.in:24 msgid "AntiMicroX was inspired by QJoyPad." msgstr "" #. (itstool) path: screenshot/caption #: io.github.antimicrox.antimicrox.appdata.xml.in:48 msgid "Main Window (Light Theme)" msgstr "" #. (itstool) path: screenshot/caption #: io.github.antimicrox.antimicrox.appdata.xml.in:52 msgid "Main Window (Dark Theme)" msgstr "" #. (itstool) path: screenshot/caption #: io.github.antimicrox.antimicrox.appdata.xml.in:56 msgid "Controller Calibration (Dark Theme)" msgstr "" #. (itstool) path: screenshot/caption #: io.github.antimicrox.antimicrox.appdata.xml.in:60 msgid "Controller Mapping (Dark Theme)" msgstr "" #. (itstool) path: screenshot/caption #: io.github.antimicrox.antimicrox.appdata.xml.in:64 msgid "Advanced Settings (Dark Theme)" msgstr "" #. (itstool) path: screenshot/caption #: io.github.antimicrox.antimicrox.appdata.xml.in:68 msgid "About Window (Dark Theme)" msgstr "" #. (itstool) path: keywords/keyword #: io.github.antimicrox.antimicrox.appdata.xml.in:73 msgid "game" msgstr "" #. (itstool) path: keywords/keyword #: io.github.antimicrox.antimicrox.appdata.xml.in:74 msgid "controller" msgstr "" #. (itstool) path: keywords/keyword #: io.github.antimicrox.antimicrox.appdata.xml.in:75 msgid "joystick" msgstr "" #. (itstool) path: keywords/keyword #: io.github.antimicrox.antimicrox.appdata.xml.in:76 msgid "keyboard" msgstr "" #. (itstool) path: keywords/keyword #: io.github.antimicrox.antimicrox.appdata.xml.in:77 msgid "mouse" msgstr "" #. (itstool) path: categories/category #: io.github.antimicrox.antimicrox.appdata.xml.in:80 msgid "Utility" msgstr "" AntiMicroX-antimicrox-2888bf6/other/appdata/appdata.its000066400000000000000000000007651377703515000231610ustar00rootroot00000000000000 AntiMicroX-antimicrox-2888bf6/other/appdata/io.github.antimicrox.antimicrox.appdata.xml.in000066400000000000000000000101111377703515000317700ustar00rootroot00000000000000 io.github.antimicrox.antimicrox CC0-1.0 GPL-3.0+ AntiMicroX Graphical program used to map gamepad buttons to keyboard, mouse, scripts and macros.

AntiMicroX is a graphical program used to map gamepad buttons/joysticks to keyboard, mouse, scripts and macros. It can be also used for generating SLD2 configuration (useful for mapping atypical gamepads to generic ones like xbox360).

It allows mapping of gamepads/joystick buttons to:

  • keyboard buttons
  • mouse buttons and moves
  • scripts and launching apps
  • macros consisting of elements mentioned above

AntiMicroX was inspired by QJoyPad.

https://github.com/AntiMicroX/antimicrox/ io.github.antimicrox.antimicrox.desktop antimicrox https://raw.githubusercontent.com/AntiMicroX/antimicrox/master/other/appdata/screenshots/app_light.png Main Window (Light Theme) https://raw.githubusercontent.com/AntiMicroX/antimicrox/master/other/appdata/screenshots/app_dark.png Main Window (Dark Theme) https://raw.githubusercontent.com/AntiMicroX/antimicrox/master/other/appdata/screenshots/calibration.png Controller Calibration (Dark Theme) https://raw.githubusercontent.com/AntiMicroX/antimicrox/master/other/appdata/screenshots/controllermapping.png Controller Mapping (Dark Theme) https://raw.githubusercontent.com/AntiMicroX/antimicrox/master/other/appdata/screenshots/advanced.png Advanced Settings (Dark Theme) https://raw.githubusercontent.com/AntiMicroX/antimicrox/master/other/appdata/screenshots/about.png About Window (Dark Theme) https://github.com/AntiMicroX/antimicrox/ game controller joystick keyboard mouse Utility application/x-amgp none none none none none none none none none none
AntiMicroX-antimicrox-2888bf6/other/appdata/screenshots/000077500000000000000000000000001377703515000233565ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/other/appdata/screenshots/about.png000066400000000000000000001057171377703515000252110ustar00rootroot00000000000000PNG  IHDR--QsBIT|dtEXtSoftwaregnome-screenshot> IDATxw`jW.dM14ı8}NwĹ\r_K98K۸n6tcD$y,B~`gosq2 |/x< HuDDDDDDDN'u#[ZZ N &''_KHHz]@.H$r1TWWDMM͏puHfgg=990++kb860xEDDDDDD00 ׋u+++444l-//Qm+ڕwZZZZZH$'xu]l& Ƀq iiiYQlWI=-""""""r&D"$%% ÃmWMʼn7'''B3s4 s-Up9i FS>mPuNi"""""""g0|e lT!0DqU\DDDDDD9a$ES׍9ݲ=6CpF![DDDDDDxצ<Xf5ﻞA3Rqx?fnJm a2'tǕMfNAc51mBH3`M]]\͈,}l>?O_R⃝_pz~I՟k9銛ɺ4xw/O:=g"""}$|/nmsg 5D?5ܬNcký6i]tn|dKp~Iߧ?W>t1KwEDDcq7V%sg) ?]|eK_䟿"3{s.+?Oe/?΃?)iXc?WdW #Z~jRHyoOb?wș.YIw՟u/.1|.[![DD#3,ZCY&a<.LLV<ӫɝec {~-%GyvKů\^Ńl\|/8+{<#]܌ 55 Y%’F?:Ne$ν{h 4z^kWb.l>a2jF5gőA}f~oj-z(NS%ޮriZ oW_aGE|lz' 0w f85js'ms""rVx!Iw]i5h7h". l^^YDDDDDD$>)ǍtңM~~]uC%%%Swq9=\Dc㙆&~,l9+[Wƒd{lM:v_EDDDDDr[7`ݑFlQlQlQ}3^!;--/!""""""2`GUNEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDbD![DDDDDD$FEDDDDDDb 8%beIcZIWmcG„̈́.N#܂njrB'n91 ٱ7|Fb `xHH"h@S粆N#Vk 1`fs''5w$-uU4U궜a84u%x5}""""""*=}q 架}a$eEapB a""""""0>f0|/lA Fd.)7ݵ}I$94UvGpP ;7X'm9)d,O1n\81-j,YWgMO$‰| xw3 UӍY{DDDDDDU ';l2fc>3ݙ02K4viWiARf'Ø\xvq|nDG!$wn?6Rwu+F^>/gxuw=>?\GxğA\A ׎]""""""ǰ7oXjߩ5L78TYz_0=`Kvp¨Cv\B#Pʝ3D`'Ű3՗im<)dϠQ?(-Ԥn<<؎nYm]"ZWI {5aP]Cv 31 xsEDDDDDbM!DyRDUu]auq]Nݴ ¶COka& 5ڟn?M10\DDDDD\}]töCMckvA{=EXeW'fczԖ?9`c-oE8L h;ֆaO'EDDDDDD5"W^^윾n̙7x:fGm{&c/`PZ2MuC{Jٶu& LjK)Y]鵼_O""""""r6)//?TRR[9>6v 8N`PZ2p6OU%Lv]FcyK]鹜DG!x\}sõ؎-P8u=kc5*d. [g?wvl_DDDz}G^u0^Ou]J+j+c@;p]Lb ԓ>Kcσmg6$ʩED I姷]Lb̏ ڨ5y.8}ebcn ȁ׸'OøƗɗfjX>ޮ$]Wy͞ѼG[TiŘO\vB`׳wq WEDDNBvAʾj3|뉎ˇ]\lD=)˛F TYoRAٺcCծ04kXˋ'ն|Lr!qdKw|.,-9hg,y'M V:iɞtRM8h2r7 `|zǯ㺛>x m.#SެӸZ[frW?`ϖQ Xn7dTx_S3[0K'vNnGjrr H›c|QZuT7k CM$2+Z>~9rZm㻟[D䬓02;ޑ\pdk=EޑYtݵ\wݵ\{,Fvϭ"Y܋wt.'ť97uGh?m\p/^UE%˗5n„-qoVn3dG5⤗9.ߪqHw1# %\ڵ{H}~-ַPၗ:6]2Mǹ"( Ase I۰oV;9$`]{:O%н9$_:\c6<ǡfwI`w y G{O:ztr'fiv)O#0'6dY`~Kl1&&^,p=CqIDDDdSȎ©vh=qBƚ d' '}<_x#:lql0 /-$a~\^J^_RjOW9=l/B.M71̡XpضC@4I<Fp~xOFS0BfMOG rp4 d OFpٓC`6_MUمȍNjzP%_Z4ZǞ$|{?0cfkplksnߺz SgKޡCڷ~ xqW߾@:SYBd5=XO ֫r 1nxp*ѳ#6ۻFqM..ks)F,F,.qAu,۾f{ș>I'r0IxpfL[B\3eW P(ȿkumb~lWmHp}}.#o7nRf\s޽urjxa%l9{Nv/<֩ ܺI>ZOfR߂86-NoAp\i/)PsC4L"t-'e""gk4W\< oC>io,q΅` ƼxMףo9xٷՔO}3- #S{n |vwy$6_w US]ov<`O_ĩSI2y"~b.h_ L$m_ѧWC𱌍.vFJ.g;Xlnyu5[O&uny0$&_b{Lm EnrF c.@T""rPũv(3ȋ4-B{Iؼ(pTgMq>q&߃ѶSh0Lp^i+d3 fZ]3v1ALw>qkVuC֗oG+ziX@0H} ̑#kG4Sw%U.MgL=QSn,}w^]#\%p:b&Ĕi{qD. .ANݛ;3<.3};ܢ5WNӍd/PuNDMEg9vL3O\"F7w=q~6>V<|UʹE_& PDD?(dac4qxf |֑Jr~2]?R?gA{3ޗxb%i/cCoj\/=ݟD;gaD'""V,.Տ>E׭K.xp7?:քe߾w+l\ ̴i|3RCY@{4*fu75]>YW^G\ya'N\bܕir}˜ [l?,\>ɧR30=Ӄax)dMI\ZaӦhI?Ks|QC>17(u};A`urOt_btSy+! s^ծ;oqlƆVL}[l#i\ݣ6DZl`$DsMv I'SkcG"'D<} l$ 5Rw#K/͒.I^߾^ZpKVox2/2_bhuW+;A0;&iypx.{-#""""""S=e;p-[ĭ&Ք> 1?R*dc?NdwfU};r \shqe"""""""nvWŮDǩEbO(G[NDDDDDD:Qn9@#]Ũ5 Zh='[3 n8u'8C 0;Lx9tzqL;-9)dwî8eC66akNpЁM^^ u}'\DDDDDDz I-?L$ڱc 憨}$Bvw ' vƉp]@cmTKȩ=."""""rRAt Z:DpJ "."""""rw2jJCmtA![DD&\ɵky:Ls5(ƒڎuM|+><SEDD8 """y/kmOt%ur%yCk7YDDD-""c^z- Zhs:\}3[p=HBȀ`3*fH'cX!L"a_:d'"""P(|TL UvȉP,O1|<}\~m"""2il P]~[^c;뒸C![DDZ\ nK#.XC|\!htm\DD_Yܯ7SR^CFޔY\߽BI'=e|K=EDDC;|\f7q,γ|,-ͪpu=95; ,QYw0;;;#""""""2*))lQlQlQlQlQlQlE7njEDDDDDDbf1OB6@AAA_U-""""""rJ^ulQlQlQlQlw$đL9dærr69cadﲳfĄ|WeʦnHG:Y(`\(۴w?>*;99=Us൧bwF_gH`M``>qW\XЄFJ6-e;h׭sֱvA#?x}`\+c5Ry/={MsJ(6m- x[Q׾F0&0i[򶻓QXg̰t|-TMNAնw^aQ&-.H=RѬ[NINH2UCq|㒕i\<ԢbEe4u*jNa Luk؝89Xn3=w%X_I]ėJ"1g i~=]FX.` KY_ھF]g=-|5{^H~n2]~O}ь?t[vPѩ)nK@ ٧;0q-zgy\uŌL0h}uF VUהLaN.cyWyѽEs}0 j ,栉,|<wW{7N j>\#օ"9͎;v/9?U3rI8rWĝD~#<>L%3 pd%d&Y Ϭ#mBq#z_GsO4(6| =R4v]~g5z1oSs/ڍjH`ԜE,y9MmA>5/3i9GsSq> oV![ϋۂ?D3ضs=ƸL-ij򧰏wNlߞ)L_JLa%..`2`<%azmo}\0it$kD.&VQn7Gǽq s:!ZZTr,LGWT̜N dB>\uT7Ep{;Mr[,i-4fRC&'3"قHwf_aj؃Hs 7PL] ']I]T8;YrE .MeUքCC.<_.[=̛̜KJ˫h Vs+cQ.v˞^'p(;~RSVEhL FynO,.vNSAE}sه wA K )fqyQ[b;gBbY,8K33Iʛ IDពN@FvI qd E/[BΨFeb)MQOoi67oڱLu7DuM3ֶLm.tyZ}?!mSOo%k0z|-\L`p!#rI4 `哏խvխa-TDv˯fm HFfVk6S rA6>E>ϵށ64t]~jb.0y4r=n/Nq"I<,p#Y^ݜ=}m :0}u8Pz + ˲0v}vguv9͉e0ngY{|Jc$elQ3qCۺ #(>|i_">3#5wX9H5צ*SVZ2t dǎ:h? vh )c= ;~Ot\Th[>z&pi(*l]t WglgoE/,We*<4s`RFQF77ixZrڿ$riHJ([x0mPs0J5 davV`ix\S;)Lpm:~ |#(('mr5Mndo5՝Ε61,ס0- ` 9^Pc ! .$/J~VH7baT1)= ˲;lmO3LYU^.ly~1GL`t:/tF*7)`gX}\7}pTo] C&p\ {カK֭?R>J{vR/؎c?ח9Q:rmvx|CqГi 5[q` ɛ}' 54@'Q^–-\O\i+qZ2#у pj7#p|LN7I0 d.B7PM8NGm|H ˏ~GpqlZ6;ZZ빻R}SnWxG&Ns 6UI뽽nqKC|m6!ƶk(۽]=@,{u>LmS&Pf<[y(o  PW~& KbzH%.%%u4#ؑ MٲU;[/W6죢1H]kW)/u20[x1!j-F/8=O~99J:*.eyQ9 @=ls- [xw).' >9v^Tw&$a4Ƌou5 0z*mPHQTSbf0*d'eGN9;b&1vѨm Pwwm7h>ƭ,[k[.j`@=]\'B⵼,8vY][+vJ(.D[=-2w,~WNsjw^^h+ݸq#ig2dE6s1Lx~^]7 Ӈ+"""""r<lj_OmYWNWԔwqN:R't3 cPISY߽c? >uǒX@DDDDD1B6oߪ'aH! [?M"𥟱v[}d qBF8)y79 *W\L^) ;ߺ Gbo/_y̯~~<\9G|uwo6 o=;~*o@W2ɳo!Lk}-TΡߞ⭼|Έv#ΑF&7r?^gcϾro >}'yp̬Ʒ/RS&ǏQ_=&#[.$| F=+{~[XWi}TlCh+, 13+.CpR^2{?U}?vuf|C|ۮLc}/,]CсcngwiۖLN^|ٻﰪOd JiJMMs?Wfee9fiULrJYN$AlqVvJ㺺os}ߜu:gX!u& Pf]kх!;x/ |9- bݱD!/"""""T@wmpBű}$Oogy[;/ѽ?u9_:<}iҜjt:vx4nug_„ǂZc|+Sn3Hy,_n^`La't2nG߱ԩu˦r$E,j ũW;kb呻4-B8ڦ6̭!=q]w}.4KrԮX1d^{zH؀%IG<#"""""*!ۀw|(I;O'َܸGKJ7R9dl*Ww$dmJѤ_:իHby.fP 2, F dfY5`;ғzJsй/}).\IXkfo̅fPb ^% ߿-dlsY"kv-v.%ӉWzXEDDDDD?la^eP@X>.?6q)>< p <3(N?v1M})];djx>9C0 t0Hбn "]%z d\CL|20 ~w=f雮gŤ[=}g].rtgDqtB64k%Pb3- :N~\^ueZ4|tD'?RV!\ېm_5ekՠUUl,`ɶzBFN- IDAT2oaftݛÈ_pCiN% nfmuZr]hs|lS8r"KY8ԦmU;.lOa0o[DDDDD!V0}'FҎo$+4u +?1Ig1Kvp$x\lm峄%$aq^WzXV,5_\>-FąT9لl#\~9 :a}d׺x6##I m_lCG q9$jO١EDDDDDu//488__\ۤ!ţ.C[peCp\1"""""".;qߕkPV~"##jΝ5$'d|?Mgutv<@N`l;CMDDDDDDD$?EDDDDDDD!?Ʈ`\I]Kb[f 0wd_wĒ7ag2EDDDDD =َb88ـLFjp}̴hFMAcׇ]ןad1̚Ћ! Xc\JLtg>6&=>-0>GW3f.ēCuzO\Ȓ_1Hs9g6f{RVT`[ciϜ{?,g1< p;=1Slj<#u2nC83츄pyu|ң0yJ. 4u#6^ 5k)۳x!eޑ7Ȉ&/,^AHwHc~qs7ۊ,P #u"x|} C߫=Jg97 Ofugim ޓ:P6q ̌Z`Z#.0}ݾ>"""""?b(+14slRT /o6Ҝ?~;Y+*^R<2Ă)XrLaW[W=;Xg iۜd͜Ϙ> v/ɧ `ћ7W>eQ%dqe2+^NlX9>CV#3bp@*Ŭgi|w8GmxTM:'|̣mkMeH_maGr:ݗf޹՘˼oMز+K䎫snd0YCz"f\jT{ejܹ¦Ys=D_WɳSddp*H}t''*ԫ_GJTxFWrѽ?u9_:<}iҜjt:vx4nug_„ǂZc|+Sn3Hy,_n^`La'ts #^^؛H~ͣy2iy&K~Nbx ה [s\[i} ԫםڵ K j:gQxX?oץ]Mvد!3~^ŶM:##ٹ Vr!WesJwfPKv-asZHI76%s;\4$ͤ'Dpkg\ ^Gf 5`GDDDDa*!ۀw|(I;O'm;-Q+aDH"^E0q,L{ؕItW =\~dfY0W̲`ckλzM'`-wi#Pb6w]q͘oN+q7< ]k5x`g_ Wǖ4rA wuY, M1ȧr}6B[#O >"dؤaqa,\Jbs\Ic~(}<\rqaҴQsZu)!ŋR7^Θ8u1M})];xp|x^};6_tF~R4z%%YpsP4G]nUE]$\lOƔ7/7aiԆQ.s)r>0&@ .㒘S7DaY9p 3S e{mQSC9oyuˀg 0EpP>G5N(}eC D[jr5L=ޕ)_0ĺ.~{sKn(M3عh:0uoyX^.ϱgJѻ:9{';6Ѩs523Vz.]dzEcmkQ`\OZZiQ˿OaMO{KQS, )X j?mCr^vu y̡J& Sp)(!V0}'FҎo$+4u +?1Ig1KvaI|Cg KHl*3824ِAJyN>#Q9ρ22tߨpH=ǡe2eY̷eº_JfN ؖ^[B*aN'<›\[3$$Xpk\YV=[RɆ+ 8s& rTn~%Ͻԗzm8>&8~3bG<2jz )?cgǁ|#aJu`GM9-FܚBq'G'0DDDDD |]s˫D~; 76)uHKi:\;0yoi;PkYy u"""""rE7p݉K\ۅRj|WNv}05M'9 %wɌ T.+G&mI|~h)"""""" l93vs<4W-"""""G}?BB]|r9Ķ@ab[SӿjEDDDDDlL^1glb&J21g~oobq:)ٮ >O109ubWOM(~~S2_r)?ہ 03. O)>YWI9Ñ+z&®r}(Uaʡ 6 ߞZ(E\.=DzyUse L63e)RmV}^G1,7KDDDDD)x!3 `["E\}gzϖԜ2OF G Y OBؠxfp58?]d^Ӄɽ-0~`XplOcz3g37(cJVKvo1#s<_58RG/:e:͏ҠKg>SsG8Ue_pʶ {c;I 48TtAj|%"""""RАmj1v/sARӀ}*˔}P'~CF@Fx3;?z|6v޶=-a/zqh)\N~s-VuvtKnxyjv!= b ؖ/m73җlhPfm5ymyJ. 4u#Ʋ{ *IP6>@:UpO>ȬYK~teZL]ߥް2gt7tu{ub?~̸mEHRGo(ۑ:<}>>X!R՞׳ zیhNBQ=HASo6>ʳc>¾i~3{#WN`jIjve= S4m|G[F2USX0eK)j=;Xg iKvظR62}e$Zc1w__<m{9y.%3; ס4T|F|z^rBZB/,!=;&.5*Qp{bD|xm(,uD=c4t'HƿMg&>|<{ jݐJ|[95iطhAM,h`GS Y„qr#Vf3N*'ui`Df]$Z;n7Z[K)).+}9%"""""RАm"lq]"o=q/hH/UȰvckCŊ`FtL2MkۮMS.VGm>7, 6M@tzcO&|ߒ#.KY<ߛ=^c '] )"bxZZ|DG\NIdkQ$] 8+VKDDDDD)R-A͸ł[ N"25:~F8uwW3ȴ]%s*:p}!9z/n>:mPK >rWZTc&b,,, 14|$,3_ܜ\~9 :a}dɹnd\rڴْ"N6\I3ivR%L)ĝ;ɞanlƯ1͉saqzv๗R-61Կݠ89:av(|>Qhk(MLo?L<`gw[[&d>֭DDDDDD |]s˫D~; 76)uHKi`qeCp\1.KN\w.44UHНȎStPqg8ȜO|sX96iC7LxtVG\""""""rBv%}p|uHAU_%""""""-""""""b% ـ]|r9|h W 2mDDDDDD$ =َb88ـł)2qg/_dsy"Nt1?3&]D|I7ڳǍ<9t3:ۤތِr<ΝMؙ03syPu~Ep\!)v~7<'9*1g8c%_/DUE׼ʠ o)9ggOgű{;Wqp6su)-c0E aqlәdnvIթ=kS/ z@a#UKepr$ܪnt+tnτՈłex{[kkt,BJui-VbkGE]`,_GQt̐28g*{UVT})*я$1xZbnPӭY8U@C~ -܃D%*˔}P'~CF@Fx8.]2a2iFΕ퉙ڝwcH3TƈןViңΐq(MolW1kӏ^b OUOlHz)c>_0QC?H;o[Ėl8S˧,~ ש{AfZw-kˆU<91F'kf]l+|@Ej2 e;|]'g9d[ӡz_oM_X |;y =FRmRb ;5fƕa7+#)z~=>><2Ă)XrLaW{NOٱiXI0RӔKpI <³O?%4kǙ=}mw4TaGr:ݗfb5ZKTY|}[#E\0'guQ҆ scf9N'ݶSob¯Xw,K9V@w1=أl CMwJ9|. 쒨l"+P^۱5prf7MOO')gdz5Kwh.|;_,Ԭ`O .ޑ-ćGn&=!Ç q|]K~e 9/mAu,^t]02b(ݙA-}Hص͉w34RoMprqy N =G_vz+7Fw_sҜrM)@~Opגq߶BxcF|O",`2[b %8G\̀g 0EpPUy 7lԟk}qhV:IdZ3jtI p/¥AtD'?RV!\d{9:_ntl IDATӫ)4g;ׅ+w]6Œՠ6$GHj4R饱\6c'wuZWs"vNe<*QBn\87s9|{Nz]dzEcmkQ`nyYOZZiQ˿OaM*}n]|"۫rPdjVFDDDDDPC6`>ʙK7k0}g;k52t.Eq%+nrG&|ʛ$MX,쪚NE bS{#Rw~X~QS/~wvB#Y1\6z W.pjLc@fo0SF qNghp[8xki|h8~3^;dA})d܊a6ts$>|?Mgu%"""""" )3}îCDDDDDD  /l+Wlrr&u-#,d,+aTM>5Rs>לpD\Lz"s\d2~޴kq x&vU4c 3W..[2᧭m϶|ឦn1t֏l }Jl);gSo}?i*6WeDDDDDDjU>3OFlxʼnL8;7lRKRNc3G0vyͳn5>sxƭ6=n8jzC=F|_|~`qGE]`,_GQt̐28g*{2RH!ۮ,m^g x9ep>M̝ߞy؋̝ǡt< ۾IS7i**BzR}1nEiE %:3gEW\Ǭ\Ogjie*''u<[?[ު c wcGjsʈ&/,^AHyOykҠNvub?~̸9l+|@Ej2^5&"""""W*p@.CkY'1Ù|m/'ϙmjJQ0Λk=іLՔ Lƒf szuU!\,?ORL6͚q&`j1:QȦO?♼۽ wŖ_X"\X~Ft,9-mxqHl_mXG?/swTN÷.&Rby[P8 '*azє\#nfœx3qus 9) $Yq-b ~gf"8|8\}0?͋&bQQ': S`]وשQ]ҝ҇]K؜SDDDDDDO(x; `h3H\?fl6GSY;OϳyM%, 6;+J:};cz6m$`,ŸQa=~$G1֭>[T.ZG(QOv,~A$9Y.dgFŒeo+ΞR^E 1㬘4:uAdV_?b1xQ {wwTViwzg bf3#f읦9HЁ;ń ̌=E(Z/}8ӧqVۧdAP1#>MP}0-T\DDDDDP.7gSH+;9p>7Ftk$55AᦃxdkI!5Âٜ}wpik!ߏUG,׆6W{l p$8{ ,XR~چl )HcK7a0oޏO{6>*LϿɊT~eD?-o^ͤDs(2U9oǿahZ@#I9` Nx?ӜݰJo|>kk˹+oҚt6`ܽƁQ*}Zէ3q!vB<5uaJu`GM9-F\WBIuiL-pJSlA)0;?n6wÙ/^q[l(Nc3?ߌ_DDDDDDHnU"k:xԥxvqeCp\1<ɀU)!Nݽ.""""""E7p݉K\ۅRj|WF4d4lܙ'32'0>0Y""""""O .+G&mI|~h= LDDDDDD4d'}p|uȿI{?BB]|r9wMaϻobհ/3kaW%"""""R,d,+aTM>5RsyD'b Vyc&JPж; .vU4c 3W.~3 ^- >]"ⴝ=[Nw1P>eML2/ݻA L@?f^+"""""'|f:3ʽ98AqXn~O_nByӭ_ybi&=d%.م/U#-h2S䥓6N͖X6La+?uk7WDDDDDfȶ+K٠^N$ew:/s'fjw="s絁#q(]Od¶/dԍDJ7FZpuw$.Dj _wZ`Zo,ML3~ދ)[`2! zb~}EDDDDDr w_KW~3Kv+N98ƕA|7o%I%Z!q7^*L Jԭu-ul'g븙-i<۠*Ӕw ܱo,^(.z9uPWx\&, !:<xw=[1l 8`+O;3l)̕\פ|8 W6-xWfNq$&L\ukWd\y2#פy0gHXWDDDDDC6m56=}24KrԮXot:vx4`Bn!`jހ:giPՉIlϸfWk؝.Nzݩ]+TW9R~ >LzBkG=znN, !7> jFLymMɢ|I򘟉ry3BlgٵvZtŃl9C`g}EDDDDD\  `hc,3M@tzcO&|vNfŋx%;L2M3Uu8@FvFY,UB~%{`g_ Wk9s72fs,|ݮ])Oz)]08Eз;Z;-HM+ϯ%%R݊~ه}9lr~r?̨Xpû;_^lO)"LtFG|;oį},'cv񢔧ΚMgtӱMcUR6Eeb)+e_an؝=@5}ſC&CQ<>d՟\1V5<5x]JF|ԛk4O:_c){ c[WDDDDD$w.dB׳)zǍ8o#:5pAD2GÉal&;Y5nGʪ#dkCuw`x6@8f3vpk:>®bưi3a/F4U`uu$c5 { >w?/#[88{PV ZUBkcR`!]f&W3ȴ]%}ϮJ& />qs޹he#X Sڧt:'>f[|NΥF9|?l|;} CӺH΁c]fvr4}Vg^#_CXȄ\y՘%=Yp&~9֓Jemk)\\>-FąT9ls?,ZIU)҈xwcCh;l /%,! K>^m9Ox7&gIHX&F;Ǡ9?;0;Bs k%|2>E^{ ƭ':Fs~d+"""""|]5s˫D~; 76)uHKiځˆฤ7~Kcv5"""""".KN\w.44UH쿅5$'dGCvgġ]dfy """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""""""b% """""""V-""ޝyY03#hhi? 5+,s)=+25F'z\޴ӝ֦eor7ܮԴ0O>DV/iIicRiyݟ~H:׳isIy.òuMWV. >xI90o?yȥ~kLz3V/ʸ>wiP֬ǿ5Ϯn NݝϭvS[~|ns۲1r51p\2iW3oΝ|ڵa˕7?K{wFwNf6_&oe;vO6S~٣^0m9ܓuweE{f{ɧMKg>߽">{Ϟ1eIim?8-{ؔznJ6*ӕtUJv/yexQ 1IDAT֕Y+KyjQsd$)[IMss_Qcʀc3ϜygW۳兢2C韊#]߶sHGg)eseNmSLKJiiiKWYl5u\ѿ&}ґ|]e'!Mb~uo3}3?7L`v{~Wm ꬼY;,o}O]Y9ݵdA& 웮;IRSdV.妻Lͨo^3.}{~>ް+Oy[ސ+-9+ssy+[#sԐ+ˠ=_]Oe5K3{T7mwڻ٧ӟ9k/p̯'p8SZpm7K~4^G~wCygr3s'׵KnaI*+J6]o(ˬߜף&1͹32Y{Rθ#zqIYs#Y71,/՘I,ȜG3Ls5+?$ؘMݝ5Oʬ熙sһǺϬ]3]o/G13yϐyd,[ݙ!ze-ws^Z5?W_l?'W<:9s92RSޑ 2Sss&fD\zӊdxku[g͂|(e'R[>ݯg'λcU{HcCS{]QG7vܥly]|/+("0}ʙPfm};sչ ˋgrqx zWx@AD6Dd@AD6Dd@AD6Dd@AD6Dd@AD6rsObZ*mmmSyE*//Ouuuccl;Yx,_<=r| [jUӻw455m鼢UUU%y;mdlRYi uC;mmm=rl NyP=vߺDd@AD6Dd@A<~@TS V0"ݞҼJz"i]2˖feY޸2t$;μ3:zsO=WTr P՝֕Krmٽl^\3|99mt>t[nY&C> ]k4wH[sKZ;:S*ꚺTU,YڒֵY]}ҷ.Uܒ*5u, 'iD6/b>q|>/úd|ckSOdks州HըCs _Η~8T'w~.omv])Սqrv\E193ge?VlYT 20;WdeغGߘ&aJ&wNeETgy4,HMjkRԤXܴ,Ã2z{3zt\=âl^DWVjIW iN kOֹY剅)90~}Y7>ՇV)4 {xN-9o*^[ D6/j]cۏ90?9,;eI3K.ueYSsdt,LYWU֤kWr1xNixV-٭]fM˪U.|D6G#;]YmwQu;ΨJ2k=Y5|tM:<%7:#Mvg|=l\К (#AķȺG~K/1W7C8*8`dV;ȼ9 zijjSyEɠAz"ĠAz4 yi.l(l(l(l(l(HndɒE=9R`ŹIENDB`AntiMicroX-antimicrox-2888bf6/other/appdata/screenshots/advanced.png000066400000000000000000000752571377703515000256510ustar00rootroot00000000000000PNG  IHDR}홆$sBIT|dtEXtSoftwaregnome-screenshot> IDATxw|unv^ ';CS, ꝧ'6TTAB[H!neEZny=< 3~?3>6y;ߑ`eʋn>ONapQٶ] |O}>k ֆ>1)))OHH8#!!zbbbb[;(g۶`+WVVN-//OR}&x%!!a@,Qa0 (&&.))ǢRRR/99>m{@lV(7:[e- }n>iiiߥuk;B^c㸸&$$~?@444 .זoQxr8m4loQcf۶]4a^-iۢ08˲ l6 ÈoI[g[Бe8CtZ?L}Yz 2!]\.:o |6+ ZTiw=j@Ir6PNI u_)Uz&uɍiUWߢNC:/Fҋ-ZUZ3vZŁLI C;:,]TFe}'W+a5xcԅjɒ/gS#K7i uw eWjm͹˒%Kj $na*sܛ?;?6ӐNI kMڌ} 2Җ?f4p.h_rNUsa (}#2b\OGT̞cúw42}0F/Ò1'p.f]cBJɭY5'nV*a>C%2Eچ]Æ-={~xtQ*qKakny-͚?O3^iU=@_~NNݸ&~X`vzNS_׌W֘SeH2Oc_|'>O?>7GOU瘬#uCk| vea+z|}s_%*v>W?VvU:IJyf)a\ׇ 0 [ZK}ſ=xlLQd$GgwhXu^sf}{?v`$Ci~|͙T~*3MzSfǍͣk_}igclHr1G&k;_*=D=vFu[w{D[Ճ=M*[}㕱w/$i\={7HgML6\}|x,KZ(OW;XC5rwnT7y$KEsgkA {Ώ| 9ԬeYtelˡ/گC_$[D~G_1}n?t/ޤ^XCiDvPKzT}T)xz<㚪U ~.xrÌسS-]v?+o~? -é_\47S%vN[u[]miV<:ra6*f;b>aI Fbwg6JU0W~Y^32;+t;g;wa(Z% }]:Tۚs nE[\yOWr6555|>"I;?!SEAG"agM/ش5QO8I mE]d~jcufcYUw ݹz PЊ«ԧ -V]eBrgnr[)TUR*Ԋ Vh ;#UnuZl,Og bvPҵ3~[[~a*Uͪ-71y'x-Z3S W/\'S/ߴݥCbՓga/jaQv?ď*͔~܏/fjAC:,?>,I8 {CC-INlU9[ +?c֗Xgg }5w'Q+Nfjup&={:-ϟ_$F-;}QZD4ڣ-ue6?5Of_Ж^ kM, 쥡{ɬ\O:/B:trC7?yq:3zfL"BXCKgQ%I?~VR#.u /r 6Kg遛kφ=V׍3\P^s&ޮqA9`LVyVթx:Uڭ?cf'Oc^LPY󑶛ܘnݺ'&&fud(sQrHlݽ۟ߥ-n_UUU\;n*Un9tARL gLI->a4ʣ}.P!ʕpzU{ڀCO%j!e8C3- 0Dz7>Axz@"B>Q D!B(D-mЖu Z$''eh.(D}@jBέ{AE@&$%L[u q>2%:nB>Q D!B(G>.bhc훙q!w@nB + KVkGW_0PO Z@lt!=:p?b֪~ Vk+amJL(9IccRv&d}Ǚ8(tckԠDuUQ\W1;>6CvQ;m%gƑ]t`S%$\.YfI|͈Wӯ߭#3+*%SfX;3^i_~^')kuzzZ7A|Tt^:$˥Pyf\Vԍ}8N=@#M)}f ק.=w~\ϮrnM~\]:t {>R׃z1ZA&U9F%vڪcon?z䩵^Y:RK3#_Uu޺ G7mܗbledjQ}4X}\I:kD]sTاOnKi§ JU'&xao]RV& L-_'cW/wY:|P~#Ɣti:[5=no:]WI˥'vP_kd:kb6&_`KHhw>U΃2u^8˧:8Fo-:I4WЛ*ǧPjh¥}B3V#%*kuզͶ7]x+Ɨ5)N_/hMn^H4} uIvP -]V $NM$lB ! uMu)so8Dn~7;뫩q$nx=-.;;]3lOzkDƑYHzkIޘ7'K+hڝn_ps϶j<+NR$j$klm *OJݻ̣l)+kБ+jRs6߁i:~@W9tjDADV>x'۷^fݲb:.]X-f&J0ź Zzd8}/RUfdXZB?4B; ûJUZ+9.ߣCWǥe%i;[7UzpS7PLIvLJ8UH4pjn;?C>Qcv~\-{Hhc jZt#Tn322ZiNNOzf׫=)z>^l=>7vNNN{¾7Dl%3H KSTTT\v{zW14,d*BkP |@xq@NT^X_ԚH9Q\}4;u>H#Bmv{O~S3}@"B>Q EecT漯Fz"] @D#۷H?OOqt~|a|H> S);Dx3ы$٪XQ%t4mߧwٶ-`-=Y^{&g:}7}J-)~Y3tHx5Qmj_9ݬ[*w#L۱ ϾgFiH$׬jd h_'X:sxAGߣFu>RwsR+PO>\nYgDBiF'Є"Is9]0Xw짃?ŇѴ"I[#)ݷcGhHJMy}-.2S~vpECuJn*7mJFTHc}B$SY۷1 _|WnlL"JV|v2e)TZ_zlϔilvJrM M\j#>fSΨuڭcU=m{Ш>}9~~Q[Ǫf2S dh|}I+`_{g-Պ>7gINe|Ufw —f2 "ϫ8Icn9^ҕZ̝?D+NИrmLIm^ľٚp]qs.{z^]H{Wʩ/U>㮶խ[v}zUI\TϨ.aF/ۭH[x<$Ϸpz\{\U)hT}z0 qk=/դ9롑mr\.cvfs=ZQLGmܮ%"]¬g߸Xw:RP?0ZWXeƲ,!۶#]06]g:m}=zaR2fmTՄ)ٔv왏ulU(m:}ZYӻlۖ]Do {\Gܦ^ŷ^G Hɩ̙jS<eѽWKyZRlm5ILZbK=Y^{&g:}7}Jy@v5}4ZEo<_X9 ¿ Uiн#X:sxAGߣFu |w|zZIPIZ1oOd/겡jthzg^9.~zy1t{jkOkB m#\+TNLEkuAu!.|cٲmEo.ݫxYeEJV|vڼ/Aq j](u"~{_;Fzs+e!1:p_YZJ9\:VӖӗg[@G%ɧ֋FauͽA;GJyѩ;z>n$xKWj3wj8TYX`RҼKqv* KXӡG D~ngy9ٽPm* %g)b{7zS1l,ZD }J^UGFKk>|DW}N^_]rmjm[UdupT bO*k4n=E/^z ɶW4{z?znq\rۊ=E/N\1K[>׽gJFGc\oK*}9r+3}mҺ9O+TcN9'Jwݑf?6/xg+2RU[UlKބ$%x2ڰ^Νd׫\FZݶU)`r++o|J~P_-.=ȹ'%48U[ %?E 4oe%ޝБ@*X^| :`@eW"]n*y|u1 ɖ}.f,R٦Qv0 XЫ_ߘq 5ttCO_kE~Hvp+5#=㚺2KguNIil7xup,-[ p{:۶7^áGFKm5,GOG,vZ3Uo{.?/z)ʾ4Λ[f$V#uxO$}P"c?el^ζ7 9br:px%&xvډ:4i^}bfK.E_?WC4cǶޒ$KSU/K1b@LJ~U#M"M4YZ}\tFSѪ-K 9%;]1u*Z_%#1M~*|YM]^d>yrr(&m+4u3t=SU<*=p>@vH@`W(sJvG|?9R1adܤ/ojA:4e^[XސJʫe%dKO >Ciq )ߒl94 j-bkkԘ)phxV(? =ZÆxnn{̶C  6TjռɚRZimwCt6Tϣ"ֆ#ʋwife j+SEÕޖ\[ɧϗ̻Sߨ~u <1[+Z1:u^G UWƽ_UPZd*=Gߞ~NF0Kt>!}ܭfm{l>wJO 'ۈQb5yj=ӻ:,Ba`ʔAټ-5ޤ˟[ڝ)SanZ.OOa/%;M9wOW!|^7M_9m^tȐ!!م㼺u IDAT'*XR'ܫ'gIg飛/8Gw۠ kTLӡu9xDBUZu=· T}ϫk.>AũVVպժkl=}NCOeUU_>&~'DZcn322ZiNNUQ&77W jMk7eeeu(JMMmQu-J-nXVZaKe7׎Q uy&y_D6N 9jSe)u*[3k}p@]ÿtㄥ ph6i'[hTMR"vSTQQL0VRstmO?tRՓOy;{nnLR{͚&|^}H'e;j e꾹 ;$Wu}2,½oim'ka}^OcRyK5ǩ~qj螋R+PO>\nYg''hAiHe Mߥ翪C;9&I :R!=}zfcuۃW£ }u6ԫkc63},{~;_~nXϽcGhHJMy}-.2S~3WRCj-]vjnl Ӛh;uL]oxZo[m|QL}MY/=+4g\ÏU$)ֳoԶ)G`BLCjezN[_9c`YѦr/33KOʛ[%(F][Mb.?E*I>ִjC\.n֕j>W\ise PanWM.aNo?=@쳷U)\)_C6~-#=WHe5bIUF)vPV%+>C];ZKR2R*-:zU]]-˲v˲fp=ZG穪\l.'ףe*@S"]¬B.UYr<*YPLꤿ]W>*kK3KD5Rb4 CUEKZWv)1Z}oy-֯oXEo~}\WgX۲3rvXUO[#4jO_"?pTUUH[UBBBh TeX{2# ??e K,.T55TW_?j߽ґ:Z-S_VkKjStϸ[tk7=w[4[3>+κ_wxey񶹓58p]7ϲk6h5zZyu'i-+XRSgH=9M.JLLt cHDLswMIu떟NsrrԷo] 24hPmxM+{CKV2st {nEEEyyy͵c(D}@"B>Q D!B(D}@"B>Q D!B(D}@"B>Q D!B(D}@"BH7.}^ HfAE@.(D}@"B>Q D!B(D}@"B>Q D!B(t@eY.!i())&@iibccէOHB(==]%¬RG.K.a6~>߸\.|v3˲d iDQ D!B(#6`vK T__ߪpQE:ZXUݻۨ"FXцb9LӔa2 CƦ/M#Z'cMNa2-_-]_EYSB*Se}L>Ё>M;LSoP<ꍱ}.+ UsW RL{졸 :04eƖ.0`{V*JjY~C%xcdRF5u X. uHW]u|U\Bۇ>y||/OϞS9kEz?l_ez*_YO߭I=N}{%+TOCVL+5[F)vfTS8.뛓4wh3}3 |6{B$)=S5i\V,xύid?OM(usTN8FJ=fҎ:OMߥ$HWn?o>l*eGȟ..ys.ҁOKb6SMAagڵqjᓊ{K]^ފW[F~ /< )4䊍NaHPP!)Ϧv@XcAN;V:w_~8V+JЁ\n_x_SR0+NR4: ǣ޽{70 sS~CX t*!!v?j}@"B>@)˲"]`7bYL}cB <`F^oIYRR,RCC~ulgt*--UEEEKDX\\}\BE|$nJ>Q D!B(ӻ6RUU:YRb^}lB )..Nݻwt)Wiiu\B *++zvU^^rx$mڞ3~X3'2ۭv>@Y%0dvK& h5ޘ}@"B, hTnnm.]CEZSuuuR||<OUPP@f}MJKKSNݿfBu*+#9]InV#~/ESi~*v͜]?guNьE]]ݖ/'Il,U}:\7['6ή,ԚUVMCZۻ_@[r4`#C~VU>(7!I Bkѝ(gz>VK^zlb㓔bB>IڲhsZZZmjjjTZZzyb>N?6ZG&gZ}3 = \-<O6KRii.o ӝޠkx2fkZw|]c#I1is*h~叺gf.t$>@mV$ɶ-駟~RݕhC[}|H&?2IH9FYCZ$q>~WhEAEEjkk%IՒMS^^:Ijڝ꒝_UXi]Ud HSY+~ 2LG};(((ꔕlЧp`+ 0e9R(hZVBPt)-5N"~!gϞӪU츨s5L!ʮ_YA?_3No~O9|ZlmIpd@A@*..nP'66w{i4rdbMxF mzOu>QҕZ<^=9L)C![}/I20%ctD-z]n322ZiNNUQ&77W t+333e_+==]ݻwoMII֬Y}wt`53}[h͚5o" ITaaaNbb"|=@ԥKu%eVB>Q D!r4MB!&cldYV.)Q tH m1 }0KJJeY.Ae^>O:6wm --M*//t)SZZZK]Q D!B(Dxz6QUU:YRd^#]JDyg!+++S\\wR|vGy,R>ªR^Wn[.x<6z(3~<l-R |>\.Wfn"]FH|2@XY%0dvKF Py^$> }@"B, ʕ+U^^i*++KYYYX"l󩬬LxAM:IF'7SӴ/ Cs_5{H{L7hMĎ@KNN'Tnݵvڝڵv@\Reee;l/((PAA{<ׯ';kìw[RJW쑮RVJ %KvCS IJsiΡ5 ^3܁ %tPKp=}DU idGwQU?wf2I&! `(RJSֲV\Ŋ.콢U+E]\u^A AZ4H/23EZBInޯL=;;9qD8Rco(Q )Zihu^c.U!qY?Oԃ;'-wjڣ i;T~zs+`V͘Tnz*YS1\Jک6jl9܄;'-hE|flOЊٚRk=)F]"XoH{)֫UN!w}?u^2EM.U8ňR߻.q>jO$> $75{IʂL͒1MSlJ: >WkLI*ֆYSɬɑmZJp(G҂Cf˸Qz}[Ҽurƿkf$ɧM3kg:)I65[fa~@~WQ+>e_BO_ 4~8,Z(I=r)S*k4;Z(PUjguz0wV/JSV$IZl=U8gR'imK*ަ5YBԘ)[䳇E+u7;5Ú:ﵣ4n!N)^ Yʽ jթ-ZyQFQYU6=@FFjb+TʦeJ9J]=Ks ?_ܠǪtZ]&ek35 tݨ05~mU8P=;74Z|(77%%%SgMӳkG^Q7wj$I2?piUyRjjˬ'ige_Q{+]m}P]X;ZO-ST_|- _$E>.?5v7GLA~dH2}yq;pL`NgF4 MB; RDlG^9lân-Cf5n\ء_]o@Ss֚KoEަ֨4~.;գT9ƻ =_LC IDATLJt~]U<3ڟ6t-^(ϥPT (o˔\ T+$ddvwko[3T=t.YDkJ"s2 5= RJϓt*2E%+n}/"㻩[G s=U}M-ݭg{KMs'_Vԗ˞ЃOַhh`NmɓY%I>E%=1.=||q.ywY[OV{_O>W=D{ZƹkQ3w~opۻeeǙ~05r*I&j*d4zviʧ7i~t]6 L.w\q/Q)|)P*ŢqqqѱU4))I _`1ڵk˨ tuHF=]kq]`%j֬Y˨Q,_\7VVڵgm߾];v$ôɷzu?MkpV;3KKv/. nGk*8gr}3}zuMAºw!YB%.;TDLS;ҟhet:0"M.vi-QmZt\e^];NխUu[]G9EE j$#P XW;륗_P(1DFzšŨOV=J~Y+{h#5[G>7:>!W¼|ze 2BuRIO Diwe(iUԞ[ŀ ꁎ!*K6CYZJO=z %oJVQQdH!o77Wΰp/,WS%딸p~>~uJh(,zbڷZt~U#LG[$¶W4y]4A+s+i"P@=W\,#8X**Se>D(eܹS͛7!4eY*,=̥EEUOYZ=PHX=m5Ko8Anե>Yabysf-=pJWA8nNdj'/2M~$S6sl!ɔӔݻNeM)0@ R`4[ҪFөl,49pXmm.4{lWRȊ;}:mAAj'3HIk4^{}RSS+׎;_Ճ?$ kWhhcQrwQfti9}GK_١Un{<u!!ꚗy=?OvC{]z7 g;2\*ح aak>{~K|`jo/WF%y7iN5#n߂˦_~OYy; ɐdzC z>P,iPC6mRHLukU<5Nɰi7{dͷTrL[yw+1!^ D)k_]e_;=@5t9*))QDDDۻv+++K999.`aaar5_B$q@.K" B " B ۻ$??_. 6M.K5oB$VXXZjR,/Pr@PI{g tZ$88X5Of0 Ra53},},XXWz5TQyZTBFd霸=йZl!>p{CA6zƤat23S4:++5]yefyuԖ!z{ZT_W˗Lwۘf)3=MiJܣR[ݢV!5TWwi׮*qX 7}7jpŗfKdn Ox mʗ^{ASW+ez:]"7eZݢf '1EvTl\=ukZ^vp!:o 5XwZ70>`q Sc[N3t rs O-ЕgiD {NoU|h̰z9kxq>K}@5vw)_uckɧպiÂ5ݨL([P.֭cl\}骂(q&};7vEGGV*m2MSwf}0q~-iU#j?|gDe>\p:IO)_xWgMddGjɘA: ?Wqx]@}Cדwe蔄jNODnRMڐ4O}&Sn~|A8ԼYc9q=}Fhi]~o{ZE7T8ͩGwmш~f}8_*~  rz iR ũijG!Q|*-Γ+Br$+0[O)+@>o>&M]>yBCr}1)zngJ^ǔ: ٭˵4}l-/ 5cuHvNPK5I;NU-^(+?glC,ԗKML~MCY٦ĶU[ryM"ۨYT2fʋh#w+h}Z/r Wlڭ S^Ǵǰ>͚gޙEghX߁jausz.x~! j׺HMc,KvSiqm_.4UZvy6e#ůMx|əUĞy9?CW&{wzw|U>qN\^p>MnASw^Ey2moN l2d~;JՒ҃m;xtXŬ7UNتv du5e@z}=x[ Tڮ5*QNjFi;fIlo-ZG^t@f͚p?i)))술,h|Kӣ@Ι29 74_;d3Х8I}d;FrV#5)Ӱ~u fHEiݦ.IBt&䏪x3,},Xf6M>O65~^,TP @-R^^.U$Ydd<<~WII<"""jtn[YYY t) 'E>wXXXXXX:׿DOS}md j7zxkbNKSO&CqB^r*IS5 t!LJ@-cčo ֥*$; i?qv[i-s*'5YzJ*$B9j)o:8uYG%;ޡb܁bwdks7K0RaNoG26{VQ^ӊgc:kD]*2&WiOjfy8{S>^}v>]pūi͏j{K}1jN={.|Y~='}q1oΑcfn2jVP.~^h?LPrwRA@][uۖ$;v>8B 5i]>a jcI^k׷dզ}{ۢ[)ٛ>y^N F=Kż j!WԘ7ky*RnQӺ h-z?v MDMOBN+._{kSIŕXs>]ͳPӑBܪN)_kڄm <\a=Pr^xsTr:R6zGX"9q3Ѿ9N:}j-Yü?ky1}e:GM|}瞽8SWiv],a{iJ;CtT<9q6 &]FyWNNi~yVkYZ'uS_JtFP혳@Gd>%2cDFIo-W$Ir(vú+ jҲC9>FܡF@7=~Z7uJ?TB#(Sהa3ۚw]tSzgTL c rԵ?ֵ:hC 5S!Gs{͵kP BR#ku(J%jm9ԣ4?Ee&i0|A/VJ\"{˻?!1s=5O:زtGּ`uvuQ3~1Zbc(ޢ̂fi{ZNԤFVPuIiy!}5sr~oz$@>f}2fvhTr ]W߯{GW5銿5=Y2љʭ&iwƦOIZj%4b5X|`WQaVgqiŗsppypv<<cN|~p>)?Z 흲Q.ӕzSc5}' 7:AuMj9*(TQ)S9ZYZCM#ng RfS EP؃C9lA qEU 4[2ҚJ=S96jb|;ҲuLYkiQy9igi5wn̙]%e*7AA'\iznRwFȃ~y1_zp veEkKOхܪ;GGݥKOhs=;:^ߙg8ELP"\9Pg_!/_;WO]UziKcn+0+s\mR|_˘zJa=}W}4UYxX vjsn̰?W}5^(/^ [%JR-ݦFjMosStCeh444sA?tz )q뻗5ŋz|Xݟ"E>+ŒCkxk0.Tw4L$oV-^-)Tr\.CbFTJ-RciRR*bյk@fj]D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A>D`A@ *..t)fr)""al8{kqN>lUV.IMMUVVnqmV/#p8tZ}`)yyyr\ VNNNaBCC%흡g? gl8{k:q=Xh%IDATxt:]*?c{r0S]Ǿ_9g^s?`TQ\\\jtttlU;MJJRBBWXLrrv2RSSWHZZ5kalO#pNOs;O8|g\c>Q>ܹԿ@qB4W1#8A1#KP{PG%Um }NPm }a/74;?t5jPm]T{UYH뿞;_Nh/BYUq}ZgT\9KhɅtFz-XAs8W]m~t=:34HfluEdj)n[Y> 2LDyTW H|O_.MuI?߮O~]{j*h1B7 j_?Ҽ4K ,Ut1r؝ uiZRV;څ 50ׯx T {X|W*:}jSJ5OڵWF'9ڢEѣo7kxq2eՄ#t㠖Yu:XxHw}]ePWj۱3gn%:g؂]sj۲Uuɯ6qmXZJKLK$C+߾ް$ v{ Dbc͐LLbSejɚJ#aG>å?f&)Xe*,/f} m߬{MM aDѝRW/ ?vW֤9juSzgzk3n̲TaQɑő.LElRp\Qz\Q.-JԔ)S\or>[c^]=hҤG?WQuq<(A]^_P!}SWSvuy%õkTǾMUt^A]w};Z ܮ>QYJtWε=s_OBƤj]*%His~cZE^7/۴,TQH_;DP6}Vm?o^/拓黝*N ~'j6޽,tyժNG}> .Iڍ;;ߧ=4K,҆~yp2u.tS|93_sֆq.>[W6we:;747]*yžQn$L7/<}Yڲr%`Z퐡h#IiE!r Rvg QPSEYz*3UI}vtE(@}a|\?M|wU8PWtw/K[O3ct lI{7֫ܭnAr]PavG{Yolq%PL:לi;+<mTX\\\jtttlU;MJJRBBWXLrrv2RSS2p jٟ֬چ=y9c_o)?####-%%;`I> uTޅT8BT8B8uTm]R_:6.ddfmk|ۓ<$͞=g90;'QFqqqѱU4))I _`1ڵk^SPP] *PZZ*׫?c{r0ñ?####-%%ٱՎ &x7(!1K(Đʼn@ $H@ @/\t lut+[۵z_o{yٞO$P@@>$PQ7lШACQGՈLۻ H( D} H( J3=G^__ߌΛ3 s{@>$P@@>$Pigtt4j^9i1D`F 3K.UjL\n|1###H[[[g{Z{{{]Ո+~<1J%Ɯ֖v0cjZRg{9a=r@>$P@@>$P`Lx]|"sL}jWƶ-߿9[ۖS[zu\l֮?+Jt&ząk}Y0ၼn"sC}*|G30ѕK3|+Չ]SkMGwoKiJ-;G3:Vd)tԫ362ґޞt4 oD`NʵלkS?.&R;3_xX9?#z잷(_\zY1w7䩻oɏ׏zйC:R~~7kG愮N1oG('SsrwL۲չ[s;rÚf/YrrUV"m_!#.kϊf乍r93yG'd#NʳVe9fIdGʦyᵉt9OSl͋yg1gը3-Y…}tR-Z4k)[lI__ߴ??00>GI@>$P@@>ThnnNZMsLV5o?̘LNNsd:::2[fLooo*J*JjlתjٵkW*Jzzzr w3\.gpp0ó^3raE`ƕ ]$P@@>$P@@>$PiE# …Af [IENDB`AntiMicroX-antimicrox-2888bf6/other/appdata/screenshots/app_dark.png000066400000000000000000002366331377703515000256620ustar00rootroot00000000000000PNG  IHDR!v2*sBIT|dtEXtSoftwaregnome-screenshot> IDATxwTgvf+,uذł`QQc,g4$F5"(* ݙݝ>va+#<=nv|9G5'\=<0 oWv˲jp8Q8~!.lMB8opD]H$UUUWTT&)2:p?Fq_<W*|[3 CappT BEEE[G+kVV1pؙH$dYV7˲L&Ŝ~@**6 cH8ّ;p\{1''gD$qn[`gH$x<;|L&;H>߿1=L3F@ \Б;x9FΖ2n{3=}ydߨ\{z /ϬiaS1-z>Y"nHk4&~mv";497u?oKFU+\UQ!mvErۧ֫kkujoSr ;C}k{ƮrrH0O+w%3_wfےqʩ-,L 4L =FÒ 3 ]6 :y9swPá^_fJwu?+Imj{ҨNWղEgZp?z2@SIe0R$Iy$Y&ޭGoQ蝧8>`oO(ab`$0h̘a>Eq~20 F,MB諚>{|&gMl=d>6F&UJ64X]|ƀ?,GJl:h|Gtߟ+}OfO >AN}~]~&>n:xfk/[/Y ;,?{DO/S?顫"}zenk`'3[Qz *tr}&ޭI7h݅Bv13LZ>w6?&=xFNɔ\=*꽏˷Y)ˈj'5Ih֤ZB) 4'ϻP$s(Kֶk?]q,ߧZPe)Iro95>t^-'FlK*ѧ.y4jeݔKh:LL 3VCBjRsʽC}Auq"_ab. liWk5޶JsM7 R]L<|,M8mj7uU֣trNhjɣV6X0,žWyEE)}eݨ[6<~7D^)II2 C/U5lL>a Goip8[ Q $!9Hc fOō;R:t}0[cULIWg)z3u%f_l+He+[2)YQT}kzeQ݈T,)_$H_^ѬhԄW^vos:ޑ*6ZFMM kDlL]D)FkS߾w>'GOIX%4;6/kP+Ysî.${R߳ZZI>:Z/Cw8^ռ,ѣ[({{|.O?fwi㛯%ǰ]0D劤}oӤHLY#!<4JkdhP=UR} Kz_;cˬ4ӷ~Jeb 4MB}69MCV45C7Q*gޥ7%܃?7|9P8A{ۖ__ F_<6Iyu7>94UmDh!ھg* $C3]Z3rfUƵiV[:||0ܰf͚>tLBPEʦ !F@%b^zeة5)|¸M ".(aK[$!Py@R=)ː6&̴&" .,f%$xhkGI$!@ZiAIFt8 8NC1H  -HB ҂$H  -HB #./>GƎw^֭;:N躧{S'k./~4_=W|SoLyZ{]|D/:r}o]ɺ}pEVeVZEղVq_{KbP3^INav]%p>N)C=@oP+6~`}_S]Zo_5rνN x}v NzT^qKr4wtN~:'-}EkC\_h?=|z TR?~d o}r"2O/SoA{~y~۽ՅtbW.9\LwzZYU-I jʴ/e{vluMy'UYKe dҺ/SE4hj}hM=^#3{RIk#pRjdzdjc"g]vS{V/FnuT߱궱m*=f L՗UVaCv-ؕu]6T'3\ y]]SvWJNպ4$Sfql;jY&j^-7K iiqCm*zʑvC Ŕi ֗ X’a*߿XKuy !jwRI-r&>ή9Wg]uQ)VX_Z ؕuY¾:\?v|[x]y5&O|!In2:]UQu6ŷ-ϿҲ \=9:z܁.OƤ^mpH-J"TFO5BKO=sJoTazpѥz뾛{Eꪋy1*CJ&6K-uuQ¥C?Tf볆%lg]:ȱ$4tU:|zҹ:}5=twtj*l=44fho%9`dC~S *;:_+淊  kC3Tljlc.ф=BU*UJ)]RꌫtTi_#ky4PVIJ캺& ;R935ɥ:z:6kI":Yo^C^VZ߷E[E9 h/mO岤ۈоW[nEk㛺v&^~&\?NحrQd( Sr&ZKJl5*՗8T3uiYl]~Οt6M*vU-LAAAa~~~m`z4 W+jgm=)kkpf_5~ݤb(nr2si WpC W))XmTqK9rwE'u2µ7/d0 6n\S]"/h(ڄ%23r۶|(UUT+(H2l;]r-ެdLpTdJgc;}/lGgYIEkNrrR 9iPO-7$Ɗ*aJNH[p#;2+Sh+` ֚0L2wЛmԻ1D֯QiL<5tzz;H+m}Hx\5)>21hU6l,R0xG ȑ$"•PTXN ~.|/l +HuKJTZY*fʕR\! Y‘)SNGnm-%c#1l.9U$n˒!I\ɔiIRRjb)I)*Tay퟊ו].Gn)irrlZJ* :ewuvkSެj Uwo[=S[kjr"z]b2s:k2ж] sMn)V^j$ێ"*_Jb-mʰ+TTe(W׎0N$6c)^]ukj)RVwڨuJUlz[eh2 LʧCST*Qwdr`6K]<ӓ>*mTu6*Saox:Uagh^yk]SEV-WXU*ZQQ{fLԨxE0/{xV*V8Tg 3sXu&"A|h,v(wkm}0ԡ{p^Ӏd5QMMB9:!l,WTe9MI +eʔn[gs<5Of}bj3J*SoJd]vm|/p=@ J}QK14IB.Rx*)lpVTmMX {  A+R(n7+OyY^UB[*m\_]eT~~N),Vq0vjoƊU:Q7͐e%Emi쭶m:pjhWm&!摫dZ$G@YْPEE** VU&nu7d*'/R ssD8TTv6̺dI״] O(#+-{'mKڥi vreA}ka2Cg]r$QQs!`H4 u{ԧ_Oy\Z_VUMLyu͞ۯ<*%Wͷmdf+L@v׏UdZGke%S2$%uFm.&wOS͖Ih7Oyj+U)HIm#nd65Ʒf7ħX$p4ݔbIE"q"햢Ѩlc k]uj;Ҷ-=,mYXJ&5% 6ɊԪxMg9?$S>_G]O}v*wEUQa8X<)Tʹ%STzڮM?D>S%%mK+1lQQPwk*.)R %S8I4a)46my&ÐTʲI%ꏩ;0R*L7g4dڐP0֏iM[IIrدV<ת6|{Cx)IJTh]UXUPl#=n4ը?ͦl)|aEb<62H*Pp톌fm`0sevg]#QM$% yok8!{}F0:Yo:.bDMvI$!v[)%bE" lNNl )ڧL[B INe2dtL'hL&J . *i׀d%%i(p *X!P"ٶy此ⱨT"Pi=@CYV|*pmXDbRU&ez5 KɒZ]TNV*e!2\73K!+VeURj d:doZj-+[Ǵ/L*iI2$7lojڸ~#SL)RB˼t;h IDATj!~Or|PSuRlelR*X4%Wf@.lݯk=k|ZvZV2DJHB*_L _^:DylTh}0+XۙS9_m,fkCuPVU32kjUnY*V,ozfWjMEHWΞ5Wll+!K>:Xyҹ iÊ%ԯOӧ,puV$--Ҋ+Q7O4W(5dzx'U[U${v YX˿G.O(TUXfVmm[pKdbqKrͧ]^%ZW]$G![v f{'x۷"k֪"\ ˛t)ߙj־Z9Cg¶ζVd$ " Lr\U |,ԸQ^ JJUʰI5ad&M~V(i7J$SY}PUZ5KvO~n:ӣd/+WFS^fLb:\r{|*Lr*.UUԔ7áxy|7URVߝREYp6Qrcj,R %jTUdW m2!? {yUelZiۖz;r-צ`X].l\QfU! ^y}~efvF;U Lw v+PQ`jߩ.lN/uޖ5O ۶]:͊6TLedl%:4Z0??.\=أ@R\r;LjJfM"\ W^umūJy{ivkɤ%Z|jLZlV/bdɒ%oZ_TTa͚5}+? WjUi9 Qa<jCF5є]v)EkkO "`ؽ :%3G9r͙ #adʓ;@CJ8]vV$!ld'ݐgG̐NH -HB ҂$H  -(tðQ,b?me36XdöT=U9 1|-7.o[A.]%e3H  -HB ҂$H  -ۣZb1RQn4M9NyJousFc숟iOBTWWkȐ!  wt(mߨus:vMu?#ҚUFF\.***Yy<IR8no܃]Ӄv1ψ t:m3fƌg>|3g>|34|nrF]o{=5=hc{0:rPAAAa~~~ͷ/\PÇor]wرc4s欭a0ZԴ]#{ykzЮ;F{tR~/**ڰf͚>Փ֑ؾƎCvKB0 vKBH?^t'L EP@wb^H&,!͖ƈ I޼[IC oioŶ5kWJ-1"UŜlh1a֥^#߫$M6)0duaH]T;kGO_üdYJB*[=JΝ&6Ue(D"ຯU Ru#WVnvi2S$߲@iz{M|j鿄݂kyGhxlyZ_9/?*TWZٹTSm9/翤wZ-i-6vtn~._7^ N3ARft@ieeeSOVA]bך5[免ղvAC]!idH:2JJf<'?=9Ld];="%+UuUP5ф ẀCJժlcH:dE[vy~UMmX!/S~+SMJ5,S^nK%ŪuPπS$+TqI\\yJH4SM$`ɔ?~Gq]xKQ4Sgs=-.#U(R8W2aP˦{vؕd}*|LA j팸B;ZS=Wסvl;ZvS$[#G/O| *XVNykU;S]o|ᖖW*Ty:bpE Cwꉯkp^|$mg ʵx+<\'e&Tu^ղMbJHG ˕=V ^^߿E~w.S KQk-5W葚NhLhB51,KV*%ágƞ(J)O*Qh_AƾϗV=#w xK4c=u߃z2u-nnt^r*k~5ZPDoO_WSK~ռ)ާ:x񈺌KXpeګl"__NQw zzjӓԵ17epmŐ3N72[S-טq~s:B/>p{vY]h]_'9zIz~^L#~~~V ʵ-'CQNh#?{L7pY7WW/"o;工{Y]$ ;>,ڲW,=d}v%GAH:wCp}]~nG?;Ы p@̔T?USDH֯WqدJ}(*7VQ6]^Y[gM:-D#SҺ>ix!1t/M?[g^L_vn;if|QGP%YvvX9WovD4WA,U>W7L#$?NJDO^\PS^ٵ/= h>bС¿sϔ6Ji+>Ri/&%Zkl*{Z]Ah>tƹ'6JرhetO T};!Kz[]r?Okʇ_jya,#!lhcA=IsRobIE/E G~^{km$VKJNH-{UNn[3X,x"H4Tj|x'J≤D6OV8xyFT>hݾ>bHǝzV9 9smf KEer:+i6dDN|edڪRw tI.+WO~[+j}Ax>jWKez׸Ul}2]nڎ)0V#Rj_iEy]=N=ZgvnschsThd(4N]lgWٲ.WQFVLD1M既,NrfâDѺLէWx]xNXm B,mzj8( Tk)zgZׯ*l]{lv eZ!$cl0CET[Ӑ[lۭ{ִ.vn Ɇ/$u*+0.=%Y,~z\O=GE72R ^NuoJKitӕlJIS},//š4%Φ'H&}4%n)ɓGml*A#r隻=yt,իYĢ1 fIԛshƂBEu +ҝoT35k22R[/7v;+G.Y4m캯955- ;OeV*9PT]u+zq*?N)Z6}2} @yꞾNO5Ŷ>ةϦ;9k^=UեZ}*?-hԎ`2fO6as`gWտ{]'ܣ׮j=/6Rl$DYJCJe_!4 I]{xj\owp_8h))X)W]'W6b $R\%~b ITT{wFC&D$O ixNClcgW"Oy;Tsߑ{iҡ eDgSvCY74Mn[ВgՠdREaR[<,e.A_xO+ݽ5ieɟ* )X\r&˦ CS)H{/h]F©_]Hl*ԩ'%r-f%dojւUrIYT\w݋1<-fZe%dF;Kݦ?kܦY+_ %UZY4LՍ }?'5s4;A˦P%*h5}׭r㦜l_dnk/rx]ujKm')TwAC;z]PHj咤߮SJ?x%}|[7x]5a_w^Z/k1tӍw/|4c}7Y'R97\7)>c(,qnZrr45~D m͐)K|μZ'jV5bpLs3]%I6 ~ZJGyD+1X*;-nc~ q'?MP+_*s_jٗTo4^I:e IA -V KH3v=[;agS q*0%)Ҡϖqk#}]i:4_~v TμZw*{j~4'{$53S}{:QՔ ;UIزds>Zs2Y2ڨe76p:D麮9qӯJ+STK)} ck?ZCu*won|L>>e!{='O^3+=ScB7O\*R%*MXaEɚ}tm_G?S#h>RSSfԪQ]JJJ\f+al!/TjV2t׫Ux%e2bbN < Ԧ[գ{gr˥fϊOoVJZgJJ4myJKK%u6p굹sGͪccշSRRԣG#NOKK; IDATgϞm'@n$I!q=U): Fg6եYnq>#v;[0EDu/_G~ܫ'uQnnN.^~󝮺"q D6ٰe՚u%2DSC" 7[Ԫ#-5]G0Īs.#΋ڱC܎IRLt+tӣ]3W5p>t4uP?qRvI4K'Ox/ /h4ޑnFc?V g?gowſ-܂?#hښURuAfԪ*e b“Pc`.l@VhjUxPV `=Nz%04!l6^LӔi2MS]6X]6׼5yk^׼5yk^u؋izq5Ǎ;~ د~ ~< SN|?))Iݺu;r WXX14UVV2EDD)b: j 4dGGv`Ϟ=ۖө"Y)H|*--Uqqq $ƍaد`?rDV~~rrr$+::ͨF_c{aZ':GX^-Z 0n|`Z|D Q,AX"E` !%(BKP,AX"E` !%(BKP,AX"E` !hJJ?6 @ӭ[7m/Eɿp;&` !%(BKP,AX"Dp][nּ/:gwJoI1ߠk{u׷sS]e{tVkPa>HQy>.=v=Ӿ/ւ"Dar%^UlR,@cdE0^/?E02Jllx6[#.өFܩG=W^}C+BJiV* 9tq~gcK%*ƖCϼFl{2JeEKL=:Õ߶7@# +B8tٝ4$ӳ[_?3^T(ɡ'TaZ'Z$ɐ9lHR?xS+od(r,-)R}FCOtbC*0w6~>z>9L*ݮOSהG_PU^az)v([7dEv8gm-χm۴]m)&iMUXBV]*ܩ6ŷsksb|+f2ucժ}ӆ7k]:uJS*nJE)^xyM;Qxx^2H=_4yW?.pt`,Mܒg\Wz\r:2˒4/':ʨVh!\OK?.*s%S2BԩsvlE |$ !,hZ4A|4jth G; ~Z4xEvŷ,Hyvt:B3JVvE55cx4AWzj )\+jq+|>I2Agɭ=3%y.r]p uATLɔM}C,${ҖOkǛ퓌ж:G۩X nRi][kއL1vk*Qj5A4-|vM;l]^|@~7ZŴԹCu0\!9j ' +;]nuNZ1=4UΦsWBu$͘0@%5p 3ƊB9۞AW_ǦFJ,;֍zuM/jڈh;; .-gqz܊">m=͕9Sw(T͹;}fc{&/^e?kⳎe>ɧeP:ֹ;w7W 0TX#Sp%™[+t_oԘkYNMR {*#e0 %",g\rɻsǢd^K^-}.0LK54Mn*O|yUxL$rm_~~CnA:}5.5Uخ!fWȑzp@3be7`ngˮ1iIJΙy.U/B4*oױs`ھ' G% yTkpc^ӛo_W,yTk֍]3whWc 9ݭi]*ց)WYHpJ'AWh ?MNz.C{Nr>1iuʉC+(9Pyez18\l_]96oYS)$Z.=G ښ|hq#Qya1U~`ţ1nռq_X8[Z|5a=tkO.77\ Qd"6u{̂ "g`r9]z*$d]p`9RsK0aSǡ5uh2eʦ֭Z*ԓQ2gF*&VuwdCOpjǵgB̊yknהkgK"͚xUN4jq*cX~Oa+YXVdWimLSe+/m׸]:uWmj4C󛙥o^yM_{ ,6o#ra_}ʹ=B͸f,C<34Wۿzݤ/<0BUw.Ð z2J2o ohMFycg혌UNA|!-*ޔ%(JJɨvΈYaS"BVLT;mc.ɪx7$fTYu#bc=:+qˆKO}E֝[^m=dTȼݐut9_{_K2Q W[B}¦Hnn *}^@p˙5=8Hc_:wD>7hm7kg) SWqb됛y~HI]⍯ibi@-TՐ=. Ίxe+_-վSW*nԶMY@$g[v+cy~#F:IL䯜}}vIxhp-/4XؔivFO0BgZ'1w7ة+k? f6Kjܷ~WcܞRjmc}0{U{EsOU;޽۾ѷq?]WK/׍FQ¯`J_0[h{kx>]:hڊ]LgU!rAG/p, 8:\  ddʻB4e-znGOL.8dzu+_i$TB{[߷ I%ڣ1R [ߠ(*uۏg<$2~gj.CF張<“?O - =n?7YwwO#Kݩ ~Z>sH׶~~GضbHxZ%M6M/mT>:J| h*]UIo\g?VQhhN=|up,ld3ʏԠњN:OHHhW$u֭MII9嬒m&|3pr?Իcƌ~]8HMMU\\\xoE|RC@B|MxI͝qϊhJQA{4eϪn*7l@uG;=zqzZZځ={o=Aд~KOZ=|@A_lvum6ޒFjں:"u5'L<١dl׆unx ~һO?ad)cG $Dg=-2S f"@@)frwoQ&!%(BK`jI6M^W65 |&q &b~ c \n_$ICnP ۭz#D q y!w Pt:UTT|>7(--Uqq"""ꝟ8 1 1 r7@*DGG+??_999n ኎n1Xa 564/n "մhMpc r7c,AX"E` !%B݀@R\\,%͞flr1a m7qr7c ?PPXXhuMPa*((Pttt'B qX=X@#fu_(B09*DDDHJJJ^ q b~"Cq 7+3!$\.97@-TVVV|1a 54~1ܬWBH|2 Ci)j0 A$D qX=@#fU۟X"E` <p\T>3Nw-{ァ6i@C,p\0=ZW_-Ў;e49+!Md eggiÏ|,e+ń~+VVjBZ%(s =]nIr(&TYn2| EĵU\o JA_A,S^j<1 w%I>W eDR|O*nCrV˺vpU *\GnWTefmGTyӿ?Ա;_mjKÖTPPRG>3"sU؊X9Z<>XOS9B8yjOUm5.($TqmDɳgM_[LĨu(Vr)RbU"W<2P9匊TDh-qߚ*SmP=Vm"T"ehyF !5B{]**,TIKn-"fhf\ T+jHV%H-<7 ϒ4+B&W?!>owzg,-M\MXou$;[th~ NFG[߼[K?}46M>O_|Z˯#,BT޽Ň-c0!>VfhY} {k<̼T޹KE4/Wnи#uC ;n8so岦eI&ᬱB9kARi~xs=P{.7Nw Pw߮eڽy}J᪊> iZ1+иuO'[Zq -][l?57PΚgF7淦:OfN}1]$y=}/JG#L8.3"趇\8M/Sގci*Խ{w|)SLL233O>T۶m;l٨&is31?KΧRA~J":Am}Jݗ6 &K}.竰%薊=d >e*ԡV-nvn6VB IDATJٞbM=?Cڪ'9Aɚ>\N Lh=:%(yJV-\+4݊!/ ݥEB; ?h?]-T|^|Ӌ6>ZG:KtYqK+~ 4=YWW˴<5Fs/ ScB*IKvTYiȰR]4eX+s@<2 C={oOEϧT%%,s/zŷ.GUFYuM xeNKSvvRo 势D=VLmfXX~SVjLqI o[9G+ۏ[ZroeM蜙רR"DUw*bx}j]kAizvy+U{_?)nX=8J-/QH;:Fo/Ӹ9UG_4ꞑh Z>|kzs-%jѺk=9wJ{Re4jȳԻ\\"ݚ4a+WZJLc ?MU#NweVBq`"""tjZf4h@kWyZvi;Tp|l̒=2JQNCg3~yMEiT4+3&4Q}ʏݙ*SS4W| If$)U{T^SIt(S-3D_|z:w/LSjF*O4"[]By[ǒpC*<Yd.2G{NFܧ zh@PN9QoM]l-3O|v%ch2-I y-{Ys9FsF.FCy#h0:Hf|{yut 9ۜ^cs.~X9  1Z 6u:QSV%9T\trMm-+V5K`{9qZVSO͛yu뭷ot3Rn߮ڵUWO\ciS?-Y7^]Ԧ9]]SY.%<ʃ TehPzsy){IBI!jwszzq^[PkWI< +Y{z`)z&/7 |woY jԺUKzux1ҽ/Cyfbl|7j 5꛱T oTՀI}hon]8ı@5OI#^xLc'kYaD_a=Gyz7ط1CZ@Vy x۶ ڭթSGEFF*u^VC Rɧ)4GtN۫/k7o^y\szC[G+BԱS9J(-N:sDK&yU+dZ;xel{Ӌjjm8.{@93;kvo=u:8UNA|!-*ޔM(JJɨf6EpK/uK\Uy4MmUv&L^%su# r1ffjM} mLWy3^m{^]uwh} / TN3Sj 4i:):s":F۷SYYBةVğnSvEE/mӹg8l]Le9)Z<PQЩdH2z<ү*TrƪUx\[(Ǵ3DӺ)ةbcc%y_߮yDퟨ?}ȥ.& 4 Vj˚JlVCї+V܌T^y+khmoV}2p*b^Mzc:Q]l]M=I#uA RRz]Ϯkaͨ@4t].Dii[2!r1uiBBB'%%[nhJJQ-glm@=‡=`y(3um$*..yckyծ]g^l6|>uYꪫ4}tf+8VdS#GY˖-ƍGp"RC⸱{9ׄ7ԩܩ6*KS M_:.qr 7q8ǻ})))UJKK;gϞ'h)[JB! 7AˤNA;wR^^$-d%''0 v)0T\\3ff6 6OoII#5m]mhq&CR@Ah @%fvmXVSii]>OGy|0dv_#0Ƚ@sw~X ,SƎ`-vːO38Mo U(Bfp^EڟY1ݽfY 3r1PGrKP,AXSAO^W65 |&q &b~ "Dq 7Դ>Qr8rnZn;q &b~ "Dq 7DBTQQJJJ*XO_c㸱{ G?q; WNNBxx<0r7τrp8  SYYY@`"8мEhBa2MMPa ,q &b~ c \n+!%(BKP,AX"D*HOW[Ih1U"$Cqm9Мm C3˔%OLvIUBѭS~j }PG*ES2U[T|X|zQHZRQ\yiTp5c(E9\BDisH%.L#Tp9"jVAZ Zm0U(S^EnwUVJha*!Ǹ sT| 2Q6 ئ,WY.EGɛb0hbԢ44&R?kڂۊwK~BéQrge6qWN)+=_FSt5O y?/Ut@đN5#G}xU1j1i}}ejqf$&)9'%oޤW}9NrK lȃ7|qW+a-jYs=ӆ쫷ԦD^NT_2tP+׭ן}T\K7iԢ6XI?-Ք!ac8E}^+g\M Fךy:zJZ9G7s'I>}Y6O/>×MI?{Zv/ &-[5/]Sc 5sx@=`߼Cܕ{_ZC_lJq%.V%4cyLפ+1TO{+ l{]}-+޵V,{Sffk[$G?C; ?h?8cU3i5kß7Iy:Nk/tM/jڈh;; .-gqzJL7+-)$l6˖mHjO=;ˢT $5whCtq_^~P=tV] wRW?C6"趇\8M/Sގk(]J޼Dͷ>oҹ!UO3jWܿި1/քϳdF_{~UG>a>q4C!7%瀉>qK+:6{2*MOꕻ2-O ÔQS%iIZݎ3 6Bo˲}Oː;V!1'́Xڀ:C+mʵqn|3Wo^yM_{ ,Z4Cuȿ=)0-{fe=ZM d+;O 噑_ޝGQl97!HAEEQTxв1.YLՊt:9B_CZM:kuïm E l) *X_Ϋ,JM?,Д~%stj-GS-ˡu i]yIKW-q'+ur]Q .ZpzghrY-u5'*erˮm}zvR?ܫuۢ^d>T%K}ma3j}5\'4\ۖmK_[V'>ІgoPۧ/U_3Oe 8R\׫ů]S'A{sʐu=!ד5/m$b8O_iF1-_i؅Wi/k`fOySϛst;R%o$;AGQW,ІzGm{h׵5m|k2ߪ{~M^?k/꓍u]cuZ3Kmsj_'4\= a`ʔdU%/m=L~j=1>,kymDyeu?2Һ2RR0C.[mj-\?qB=Mpsl*^t!/Vv9FF ՃD)wݏpia)s5wF]ӻVͯuRh,ݢK?+gk{hm_DGu:}Owj5c0jUV= ӨڟڒͨvuBڻn4LdH@[פ3ݻ礥u ի;:9Pn S_ [&k]g@UjjjЏ#|k4h[>EI=fOQ\Jlڪ,Su&x\ݦߠ;ym8vgee_~.۞ݥ! mS7ȎT׳)m @Oև~ f4\:zԻZ~uf<8F/iO&L//mcd(кBEkْp@C@C;ޭ1dWj熖@HR{>mHrɐm !@D)WN*儻]WkW3 !p!p!pdBLL4e5oҏDZcm c7D$np7@bbb]~ D&05h[ BHWyy***dYV@UWn|>y^5>,akn?ж0v@b:jG%%%*** wSTic Ї@ Dnp7/D?Z60- c7h 1GBGBGBGBGBGBGBJwo IDATGBGBGBGBGBGBGBGBGBGBGBGBGBGBGBGD->L7\7H M$"R !̎u7tWm+]ZwU4/SuZ:Z#N~4+n˄ԣŅFʱ:ӵςߍ^zj%h?ou@B=lmPNY;tVZ[}.и*Z{݊[]:*1x2GRj:cԭ[,-rVj?VG>Rt>LFI_]puk'H[~Z_: h!Ժi}P*ѽû*w]VitvK2E'q'hQ酫z)؝,غa|}zmH2;;;GPY+}2=̍1Z5[ Rʦ5im0 w\@`C9wd>}k]Cy\ːP~& )wOZYRT3+)n4 []XY;~\S:FK~G9V{L< RSOPE$j0`ӹ^p:%vY\5Ѻy6Y{m#VhZnaQꤚlYeل4 h˶|dU6|>C?U''wUVa#u%j׆5y6?Zl! h7;nׄ@H )sxMF;,E{V4=k&+OкBé Ҭ0{10w>)-*Rs:zFFzfee@YYYׯ_gggwil;-N!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#x^~YЪ)ۭp7r "gϞn RNNJKKxЊBz9Jqqq?l<D/fĨ2wBcY Ðmn a<{ 8;!#!#!#!#!#!#!#-DTy;}JQ$BDCZܪTqnʬe+Z1 $%%P@i&㚽37L.}-+)"M\̕\B?Ο K (`…;!dzIS)> B=0ޣ&haeP"pԂyҷ.7YSO9@[B࠳BvHbUؖlcBl~"_v>Z3uei^Њ1HG%%%*** wShbccx B&_#!#!#!#!#!#!#݀HzeYV@bn>f @d9б% VVV&ǣ={)J999*--i8ܱ PՕQQQQ@'Is}pc39csK3!$~p7V/&&F @diܒp'$˲dlwSh hҌD- wBGBGBGBG`j5=ctuI{in;!ȶm[nѠAӵaFh!H:w,4TXXe?.SIqIT-9/!]>UDz|YLjW)U=]|ڡtƑ niڵޭ :EKt\ SQ1KHTbJ}1\ъM')A!z䫇{ @$UZZ.?(K.EcIRQ>%tZڅ+V$hӥhwԏ n:*-)ԭ40t]GeSl`ppBhlUeo6T_ea0]rM[EٶK5oޮ0Ȳ;0 C'xnݪxC|KvӦWSEԂyWA~M_y~UYzp־|r5A:-˹PnYQ͜%eQ2l#.ѣw]AGzTKQ1:Ծx^x-7cvc!n1v卝G׼߶4;+Yǿt+m ZC҉eoUfvqS: @g۶ԣZh53ꫯgEvF]sgj3uI;kB  !Ua[mrUDNި"Q:5 ߿| z虛ggzcZ 5{A=_lP鯆h̟UԛjӬ-7ViQO|ʪkG_Z+$CVet5']^uNנiڴkͺ5 nk;R[q d(1? EQɇˆyzeO{zrIʽ>1*< =ql_t}zsk<_zvƒ8l|^^۵Q+[S^rv3V[hWe*|ozg],c2"tԍ<`Li:ۡݻ)!!Ai;i>t~߷?J" S*5iDiז (I陳k뚯ܳS+YT6~]qf_NX=JQRΩU5mA~^9Y͜,# *]?깮nd˔i~]s7lIXdK۾~Q//9\~[7)LpB5VpE|IvH`C) \2 mqb1r\RrR;u]3_}z(Ee/Rb-jgilj|ٖBb8Gv*вW~_R?GG̊~zd(]eV Uv=Zer;HVi{PRԔ>UsRc;ۯG._)9DA BGU_alkVV-me)*Q14V߾"^[mNյ= OjpZkC ryv' :ʰZۇP+8"oo™!ROk;jFm-Ta'_Hk6U#tݨ/hKRzoD)/SH!DczmkIzo !}Yszs|=B)S 6rnZl,%34鲻/˔)5|uQ @tQ=,uM))ZJ[͛o+/7WR1cԷw/k Ug-~a*׬ST{#nй[XvbyڣcM]7x)"-K>^媨eYneY|zkt}f @diܒ0S5ǣ)Jx;9QJKТ.UgS+1y8B7T&^$O}~N YG`\-r#A@eicO/ӥ:īueKVH_^zHZVzh7Z}.?&Qٟ,І3I^-~OtiX24BM2eTj9BrlYzXJŒ$Vv9FF ՃD)wݏpiag;jw{_mМ[t1Zgڿdj5rNT 4MkR]߽{^z5{YYY>6*===MUjjjrgee_~.۞ݥ0*p!p!p!p!p!p!pDT/4 d\/$ IDAT,bv+z@@111nh!@ĉWyy***dYV@cY|>^Њ1HG%%%*** wShbccx B&_#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#!#݀x^~Ymir݊oܚ="6(++QϞ=Qii<OQԚ="2zJLLTLL͉$UTTy_@4fB~%''˶p7hn=n«=D䃩-˒iFd64@Wc5{$8""c0LvYn@;v$ In%uTbƷU+W$CqJە*-Y)F3Ǝ@[B~Q7 u;~e@ `rǻYǧ9ua 퇆ioWD΂GzD#LՌ KUdu쐨蚚ߖ8OV;uN-JKU6厉U|b(8֖Te2<>RIn;ЈWD v̕Nq `GvGhˋt 7ows>i֕{ZǩiJ׮LqJL(v=EݮVQRShZ^i=UO!Vo,_̺Qo_[\m޸I[vGxOkܸ'jв)QZmjٔn;}34oR- }_=|:U{c5]vT ߸VRz;>uZPxG)1M\,TYq+2INR|!Y^vJ dx+%He?]jBSZt;E  +7ʖ7=WɗuwwUV_=(8{|;tdi묗4u='vYՉ\.qe+oP]NUaP*ܞ-՜H4h]2uX>Eo/(8D=OTbӣީw6TK^ak(u;Jڶ`Vϭsj]f۲/ռy$IFsT [I}{sl=dFyvLF,qz#<ܾIe)= 6B+uZv e苿US{>F?c}>bl?I!_Rn] oU(j{:\[d?Rk|^7^?Fߺm?^MwBs =*27Nd0]r73םWߪf߯gޢˏWz[apugZ?; p%\=Naa˷#S mRȶ4;+Yǿt+mVB6Qvh ctQݽZ7*m=M:;WoL_n]azٛu\LDsCg]н(} _x+4SgrNhߛNq55z[i%*J!:Pu~zG5`@ pN8ru?ʻZlw͞7Uֱ y m6mɲ%Kmmߥd:NfK}6W~lfC^֖WR@wB68xln$-{vsI$>pFzZoMKqCQkPz[j):u)ni}JoDye{ vJk/W|5 8tH-oNuMuNBX8m%u|OzK饷Ҷ`~ƛn#{+OdФwO[GsԔTV{"=r;>ˏLih-ՋW<σm8BsQj(IUκ`ݵ u{G۩B@PYY+S:*ʻV+ mIXֹKuGtZo{-{/ m75.F4@{zsi!ˊjm V(%Y*Qκ/ՖWgЎ۟Էeq6,_mmFxd+˯p?l3I2E^v&dBR]IҝcF֮ErIUW4lzxvyyJPv֦ĄY :{8>Yj:S+4ӊ׃;hԈzo2Q<2Y.-:mw2#$zR͙*)Iݭyka6ᒰIwim8r{G볗>膻/Q_(wߢ֣*5iL޽{NZZZ}_P^ӬWXXfo!T_ъ2Pyzf)tG .s'9Z?Fq:(ζ*T` 3W7wr>Q=Wx޺RUM 77Wu.nВP;i| R7~ջMKc;F9̿RO^WqqqGGSkHwBHQII?d2)"(bGEbe˺.]+ؖ'+@pYq)REe]qUR#A]Kz2$I2 B*`#G2s{uWDDDDDÁs?vШof-BLJ """""RvIX>IDDDDDDDDDDDN*BI"*BI"@m^/>0Bjbۉ"""""։fP "tҶmPwEDDDDIOOY~"""""QjaYzE~~~#""""DGGPRRrEDDDDB>=e󑐐iHeq5hEDDDDBraj0Zòk""""" juvЪ+DDDDDDDDDDDPBDDDDDDDDDDDN\BDDN,>; gWA_1EEŔ؈G'6ҏ;3O?-(G,Xǔk?(SGkD$QNS#,14n3>P2ˎ"wQKЭrVb"o?CfєdvI qʈmzlfz*Ir>P}mǙ}E%|c*m,ǷpGhWU/^]>=P񺍶OeIL=8Wu0 kx&n./1HRBDA2\Gi9vSMxqF"D_Ca.zw70k]!e7_ۈ߮y"" "" \E157<}uWnga!.|!~G}OQ\ީ=[x};:* LJwU |ZnņeӌF';[q&%YZ ,V6 dDDDDtgR='6/?Iۦ֟[]>?zܑ n,ߕ%H+^SZYDR 5M̌-|UQP~~ {|C-O3`CF*!B48ītk>gʯIEVJ0 R^; \yVzi}f)1 Lsu}h#,8;бc:vlO6N#""""r"2Hˎʋ<-if KtR}ngY֓k?gTfrCg-O%*DD/lgBf#f[IוƧn[oz9;*ǘ Csn xac2sgBL 1[h6bK\r-gUvOm9p~- 9ٔED~ 6{==tou( Uϫ94)Ioꕡ>wqN"|{⯺y,4o=:dVLŠmBDDNBN_XF^v/ȥ3ĞM-[s9uusc`d7b0M/7k_Tr_JY˙W}= o ҾĔgw{),O0z|' `bj<68\00cjG~HC"Hbŷl?}*~ڪ}{]ʍ4b, =Hw"<~+l],991 9'r'5p>u߃偛x"v"`Hb*2 @n ZBDDDDNw$ ٷ;lێb[(Jrgs4gӏMdvO4C\҈#a`4k;@ >a_M/bYs?19]!"Ґ6މyyy ʖO[{4!1\<?]QPqQ1>;㐫31n7Xzs6ǼUzxg\e2q6o˅ν!~m GlqqpeH[wsL2Vn%LT5Wep*w~'O ϱݟŎnf,#s]2tʼlzM>k7_ >(9 !"ҐLkY|!F~l;qJwGeQ|Ux;1^1o+`Vs?U=xd>#\=Ov%Jc׆ lV=2ށGBi<붾}nbJ)K6|&>R73d'x|Hm/C[1mZ72oh}{{ }l|tQ䍲̚1Z5YD}֭ӓW}=55?Ok׮Zs\4k_Vff&IIInSn 2;}=.geee4!^M},%?#o ԌhEDDD0%4)׃ebiԔh[}S ``#E3XK1Y96=JW|< #i2ܙx*aE n?C8F=x'1udz wfdDDEW|DD,͸s~51 ?I{/};aƽvk<ԾPrva-l݋W/Ǽxtim՛ƕ,`Y\QSm˶cp Y|v^ $UW6cJU,8\/Xv _Smk|""룙""Rf6K'7=Y?6G:Pj/ʦ.}y^.K^@ (.Ԟ->ZmG"G]_߳fdW %2ܵ) k˷dj^'7XXmD9WMtݴ{G$""zUS*.gѤi-hAK@bٴd^#)`{|n}׋ \D31NL|WT|VM?~{70C }93'yYiz:&p{ M3bچҊVZu̸nGmFρ)`㼇cC*Io@oD2MS7-4a[peCg{Т8o;jj/^:pEu/`XbϦvY&Vʹ~aҲk co P_0Yl ߬}TִA,|nw/坅 F""r<!DD䄘 ZȼCe,[0qIQ;q$8lu7(""""ҠRsuߊ=2ofzG BZ(-ZG]!f Xi4 v""C.3mQ>LJrgs4gӏM}u[V$"k"ԟiӌf FLԕ15"""""RvjCs>ʈ9JCƍ~/vtч1 cu#HT!R&D GK#F!wLNίc9#XBtӋsrEC;6>9}!""p#)3Byg<ڏ{{,ViӝN"""""XX-`VEU]ˢʫpwc,x3ؽbZM FڷIn `G`,5 ꮈ4Xv]F]DDDD$ ,6 5,&""""`XZyPn 2{8ЈADDDDDDDDDDDN|F /yD4I&n uoDDDDDN/A/\FMHzbik )Φ`'! N+A&ef$EZiGDD~ wf.YzkQ;iY}.'XL^v!Fg{F" {qV% *B4$?X4{ 95L~T>THe?- ?vD^\iX;o Vy5締Łm1ug """"RQ~ɟHw%0C߯3b!tgr`~ sO eidWu0 kx&n.7,-#֧qߍ\vVy/{+9Tip ~|3VԆ/BcYS\FQQ%~{d(.,SðDp6"Je\J$%x8]u~e@tnθ^2Y mnBQa 7#d;ִS0ȯxd;ivVkZ'G`)6 PDvv)1M+dq3fy,.,YF{t[Kd ΄xb"-rՔ_;*-e7_ۈǪAκo<=~ᒃxcZr57)y^[ 72~/q7 gbJEUػQX ;s I{q6L{'--d? +#*BFTipLrgYF\3i?=$DsS^fOӏM ۛ/lFl KKpkL4<ڕWwUdj,V6;{ VJ3oKs+S􉉈Ԩ<|2Pjy C$όO÷?|K;F #׶qRU +nG՝8>:ӈ`V* ;3y/=wu I<̀ }OWjr7}la<3m釋aky _*Ƿn>b:f (@80̾R})n_>M]\0',* ZGD2EdÕ7'xh[L [ 6f>ZA9=Iyfq_L5q,YAꏹGYA_7ſ3Qʹr ryt؁ӾM#Rؙ'^EV]\FЄ.7UmSBDDDDB 7>f?2˳vOzAYd:oc'P`GfBOrIR&ȿ6sW"`djτgTfrCg-OI_G}JaLc'^F玑մm!Gymp\|{c˦&jIȀY>[ aZZHDqCd;Dao\L? y70vwsc;hgj,;4}C.`1uS&sHyxN }Ҫ`u;o4zOǯ0{?wƀfH>/3-–=•k""A]D6MhDdЅ<:~ |ד?ffYG5Iz;|i.6%7^ȹ$tε {xo;,%rj; Ԑ+}Gylct|# !+*k& pi9X12%uc/`f-b{TY+3|#y{E9Yۏ~r"e`_Fᑿ'.8+N2" Vb/9HV~u1AKυGjWm{ F.%l:}?﯌oigv&4oot> y"gТesʈ%DZgmEмytWdLJM[x!f "_cjG~e EhLP!]9-dς}<0͗h"-G<(o?}>Ё7,bڝDD47"" i [w4n{ W<69og{ܒ,LBBo)$Q/ +wxaG7fIK3X;7wi C 3?(G @ E))-,fdfqm.M_Ykny&J|>Jur7wхiYe_l [PM0 SVmF[p6El e~?Exrӭ|MpCw:wm ?ܘx2kVvΦ.&PWVݮ")gkm,\Ǹf=VU%*|ˆȯfB48peH[wsL2Vn$:"l^8۟"g{=Jƻp5n%ϞV}{g3zz2>#=@%0fmwW˩9:&Vqv|C2bμ;;Đq#7*F=<3dq8B^ޝj'j$f'L{<2:pF\Kr=FKM:6ؖ^x?< E.:4PIzS=Y, ?XΏf5dx֛|n$A07>b'1#%vь;u,6A7G>3Ly,p귈.TiPXa~(0/Od[_s n>SFۢCwcY=3f\  'LO6{e` +l6Ce\Wy!}Ell,F}89@ g[^W^Ecj?̇yɮZ}x\iڐAO/!g@XFZ-`9-;I'~_F} LV}9~Nn'b,Ч1*jwuSʶ3k\?jhӇ2< v#\k >fBy7t^ǘ0j\G2[X-`GMHкuU_OMM?ڵ\.͚5;vEDDDD䗕IRRR۔EDœjRf9K{sD7mBi{;I; uWDDDDD Պn'&&^+Z'C)lI۶mC'=="Ng)F}3{eGTTH @IIɑ߫Rn dpEGBBi+""""" nv8Qn 2{8˅ j ˮ4VuEDDDDB4b",$""""""" ^2 hLA/\FMH^ҪOQv6~; gw^!2)+$,D'5#)Z܊}+A_1ydfEN^>!9׿ wFii?Y ) y""""bftjȵ5gj )#;3 2s/*8sf|2gb^T^T9Nμd;;w~o#9<=ǃmsg_J _1C^~%Rf Ǭ28O(' W |b22p89e#;v~Ν_35~N""*BOnǼŬ޴7dL,2K~iq7vlg,3EV bk>x-*jU5|"/æ|_md^of \1ݙطsepƐ2s9c|F,-OE|y V/`ތy8e"|n#tz>zVFWT60b6E#E 1o:Ӛ5S0`[si "Nv""ˉu8R.'{|f˃V9 EcqLSAfZQMqZ(**ObvCqv|x⣃Ƿary8]ug瓘6\OOx˚P|B"""""9S[<0$f$,zg>Y8՚b c f}Ԓ᣸Oوc0(sWj')ю ܱ|ATk-ѿzF=r}ypӒ FOkj`4) ,WcZ6Yk ~^ݹ߱k|POݻgr_;iqh!CW\ t78R("HؽǿZC,L-#DŊя0>N^|Wۜ2w.b+3zV. %""mǵjü=6 _aȻ8O&e߳q~aRmjaA$""""ᦶL},3oKs+*-:0w]dOxK=Āfrٽt/::&{<.9o}5v!sW'Ȟ-ߐt ЇQJ &wv>3vRV.ѯ'~իW 13aWT V(Jeʽ]`ڈY`tfp)>/ʦ.}y^.K^κߔ$"^; \y^My䭝x{k-k3xg<}3ч4^6{6||aT; FZv W^ܜlISBDDDDQm=D>V}D]Lu ~}0]l[ıLxg?)tiupQ;#Xk xLez+7}T}R.zk>y4-L~etYMb׆  ʷ;;бc:vlO65X6=6WH@<ZVyDD$܄Lԅ&S$W꽟wc[3`>cJ \IwO|ћ)G:F]؎U  3c~I)"lǷc)ϩO6{= {! > "МHQn4JFTl IDAT]6\r j 5ccMwsc;hgj,;4}C.`1uS&5dJ>32[34"2•w|i9X12%sUv3mFρf"׉Oજ2s=ʧ0xIDDB*l""r*yٽt#{6゚^WƷwġ6Itzb(Ҏt!#?Ё7,b'998&!XZ2wlHlBΉ0s G=ynI&2Cj@wn.f@ @;|Ahqzz"""""iG~YG>zkfW֚[82~R/%~é40[ 14q J)>eo ٓ>?f6_M\YnL,ٰf\ܩ;ݯ(eT} <*_0|gҡcqQ(8~HQBDˢʫpwc,x3ؽbZM |̥~Ϩq% >SFۢCwcY˧YlX`Ua<K\l,F +V}nbJ)K6jψdY̮eTï90L}L>pR2{'kqkC+Xf|O-8{g̸_;8Ol,dl,Zʋwa+b57Vy\Y?撿VkEl>9OPy?_fW57'mVs/c5.󣋰&He-VX5=ZDtR=[nܼ멩'|]vzYf'ܮ233IJJvri~5)^9{6!Mդ̝Eq;L̻z`4(evz|m]ve5n8x`њ"""""""" yǶoµPwg甍<ߜaj""r un |,YF%26,xs4 BD$̄ejbV&jJ]\]DtULjjiN<Eݎ#***]i"""""u:,P\\LII a;""""" azq?vШofa9tRXXH~~~"""""8Ng)F}3{m >>>]:(HMqL"""""""""""rSBDDDDDDDDDDDN !DDDDDDDDDDDPBDDDDDDDDDDDN !DDDDDDDDDDD䤈ujz|ꮈ4VNLLLWn9N4R!<Nmۆ+""""" Nzz:EEE8ZSn fP "%..(C'::#W."""": ,>L uWDDDDD,ݎq@.""""Zuep S]i0Vk<(V]=h """""""""""'EX>IDDNK^f!MI[ ŕ֨ Q5ԥS'?E$$AiƤ bԌhEDDD'6ePLX/sNez[WD$e3HK$;ύt:]WLA^6gdW@vfOAٙgK~QY}m5{8hߗ9+!1uw%ٹv~篵y9<6$=/b5#3"J5L-4pg V: r=~̪|J ?E9dJVn3XL^F=ldoعk<ޢIDDDDNsʚԔO8;Cm;Ғ-|r/w2T !zVFWl+l]p fQyi͚C0-ֹ誈ȯZ\Y7ezeDD~} -̬5D5]{r9K3k^$M(*;x`HH&>{5+Y||q4?5-ǜ1x#}tj᣸Oو*},sWj')ю٘iܱn"[v<;?wL&쐍+]RjkݭKVZת~ժůRת*(TЪUŅgIf 2$!̽so>̜9{QjCCmKCOK>g?VR;sN źvvg=Z{Jϼ[󶚽ֺԂ5wǕ?Ӆ/eIک `}Z W=h:ت/7_^+HGHxZ+ _ltȉMFq:+pC%3miy{i2s1%< *0M,g87]"˱5s^v8KﴻC랻{OnZN8]rJNAl7N[׏Uݧa%eww,SNE Ou_*^c.y|ksXYSoZM^.e-o^w<^qԝ5x\%^~5?뼳ՁoI6pvRW,ͮ/+(8Gok!t2?U5j}x-'5w%K{}ܨD|p vhތt۽UНUq4Cܝu38:MqWͺ$9ԏV@ن#ҟ9TZʊǘ3fƌ]_ TP3&=˯eG [Gmsob?vgJDS('P]{oO==qD==;ϺE7_YS:#tkt]=~_'mNaOk{E:Wؕ)m_?6S_m#!y 4.p4ID˗>/zjAJւtud<~.{t}>zdҫZlgue]*--7TFFgYQtp|={$HzGdT/ɭnvr{~?씣'uOn?:Lժ֘\__1A555@tPZެ"s*:PN秺iZcjUsܪ)$슗4_fj~S=kQu8_ plo9{IRT_M'$wFz ʚ_;'IoΕg$>vJZuk<ۊ}_w>WZ$.(x훿POO|BӚ%}V=Ek_KSb]ΥMȸ>7&ꁏԋSzbYSRT OM';Ygҫ &G,weyJT^n^ڌnnUU7Vƶ 5}RLeC霶_9[WtVe.PI#g~|C7,-򴖍>I5]tΖX}Gw ^V{}>=eFzM`m$ɑIP20=(':_ +ۚN/KJ{ܸvHI*v$*([ssVgz1jOotLg85fLϖYBlɊw*Q,Pmf{=]ϼT( T t@Ψɤ^8n/5w?Onu;oxTgD{ybJ5R*Vz?kxg2DZJVKk76QOGmẻ)J)3T\#+ب:[rL*J)V{6@*Vc0 INYyzԃu!Cя~4^Wd[#!q4A=s=:K4aZ|f}bSnjel}Fݩ}Y=n9J=?#qpuӥKuQ#d~~A7O#u'O|~O֜Z,}Qk?ӛpM5O2`øfW}+t-Ou ׎rcW;TRoVm3=4 Wu.t:yzx7:j~m}q¹:zw8F'ӇP,6V{Dl,WhK/Iuo/O8['\w:_\Qjt51C7:K47ӘQf?7kw>S_96= HB@`ʔ`_Msι8FEKNBh[9Qw="kԷ\N/r~rXI5oVZ_Gݔ~3%S\.Cgt~3wBNI g4hʢت}Y']tcɑ[cƯtRs=z'jiv_ki)\հziZ>מ[L[;e7=xʇ S!kU)Sn5KK_LuWKVFۯj_,eJiinů5^]7^E5z7-(ix`{]~IOKiiZ /jwer莛t G)G5-WfjZnrKaT]]]WZZZsȑ#7q`Peee].~~v7\~v5>Jwvj`p7AEEEFQ_X]tƎmݺX_SSSrX2 v8i}a_ooW{/?]G2d=mz'ئiʶm&9w_kY$Լh#y1(%Cu<1`@Tv;lh@}2 zL&Ulv5GmK檭dSmrMEhW$Q,m۽]`@m[x\hTG=m}r$$utt\5|>MG=m>ޮM;}r:&AdI$!@F{FL&evoW0LӔl"+hĈ]`Sgg@oW@?'hTR[[[oWp%IXld"L*??_vU* Ʌmۖiɪi{dIؖQ5(܂m̔:9MkB$jhQxKor{[Ɉ:;#'ӲǛ% O#ӳOMNlC7Q0:U_)E5xRk+Q/Gy׺UiJz_:H|9"ሢҶd=(/W Xu#*./B0wuJv M{/zdVH^]dJ.E'v .^x@-Kؒ6vu{e+ jWo{ЛMySѥueVo' ]s3B>[ѶF-U=xJ,M9z+bt$jgܯGm;L;NÍr.TO-ZX~PӴ Ra+QgGVMTKcR[|zeJr"!Ei9.|2ҝjj?kĀW[}2nP8ԡH’Hප _<=Ɗi2s1%< *0 0{ue׸^/=FPWwkVBT<]}M|5gűNZGޤ{/[kOdʇVŠXuOĶ` }x\%[3kλE+Ǻ'׵}Jr4y5ۡy3mWAwJVőtrw.'/O|#4]5ti)dMzRB~n52nD;;<=ڑ_wRydnء:Biרugi֛ #Rη/GꢽjOs}hrPr OqiJ %6 S@;U|b>tW&kÐԢo3tPljU(ƺM^}.9PNΡj{z➉zzvRun7&ꁏԋSzbYuE`d4}a:ณu*C^չP20=(':_ MN/KJ{<.έ"*'TڑdD^oy~YyӇ=땺[,I*^;O+jQ7o?=QIv: t_芕;DfhvGXD%nZZ셺]1 }X7hZ+ċo'5fŠw*2JӌGn݋f۲[:eTS-#UqQ`J9rm&JYkvwزmK-aف2U,Dze$GP<=}湚\KiClW-,*Z\gO8R?/$j.8cW|X^{#}{:C̕۔l+Uc)N!%V98j9%0z=zbߥμ]gk֗_-Vm0!=uhZfݖsuu+'pN-'kYlɉ:X04_)KSE<5JgprQ™}eu&)+G99s|k05׾Wk=T-R{35{o5Z{?E=̵t''UT8\f+e\oMI9z+*Q]]]WZZZsȑ#7q`Peee].-AEEE] Ѧ7vnMH6I}2 aljm2>@?'zJ&mrW|+(1"lV<W4UvvvoW@?'GBHR PGGz*z>ޮtL# 2$ #HB 2['7o^ol9rdolEL2$ #HB 2$ #HB 2$ #HB 2$ #HB 2$ #HB 2$ #HB 2$ #HB 2$ #HB 2½5NFL&e884z78[w &hԨQzZ2Է~)Slq)&}18E@? N|8>2 1bDORWWNO7lnWvmgfj5yO7Q)q`s2zSuuu]iiiϙ3G#Gh4*/=|7XLx\ݏ8Eoi}:jD;l) 8E_G? NS=yivv{ccc}MMMŦΕ5!$ÈkH$6q89r&@|>5jM):bq8E@?in ɶm!q2y` )zSO437rz%NћSu(q8E8r$!@FAdI$!@F lkdDœir͒?=mA%Twmr 5(lwnr{\w,+(O*mK-ϯ@:dU\^(Vl5$WcUJb'Cm15lx,;Rbɷt6O(݋`# 9ɔ*]N_#+ D\>O&Y';_]ޥk~V;VκD qdh^/x`}rIaywx5RRU|=ި_5ԋ֊? N><] ]]N m;>ɥWV\PVV$3WCF U^F,lĩ$+`{J5:ZvUA@ ׅLUcgE:)ձzl*N oQ* =21mbts2MGŪ[5V:nDn.Sa^d)T%L+8o38 NR5ԹF` +(ͽt3*VH-KY*Bo~G .!K{쿻C랻{O^NRV1~IYs4? :-UޫO[[N?t'Sj[>OQO}>0Ik:C5bv7sLߛx\%$W5tU'뼣gſ[]NJ X֢Ȑa^PaY閷cr* cUUەiHQBr[!"K⩇x!ryۇu߿R㒤[]6!_'=thZ#$sΖaԼ8]%/% E{1:6:x4|~0$H{)pU q|Yx\2LS^_)%XP}SG{lկHRnhyg O,[SQ̕!庂j3}P u.kS7Q1FV(U?__rjv-ׂ$u([T8eq˕$suN#M<=}湚\KiCl\nC2$9tZLr hAg+Nӥ~sT޾^fҁĖ8R,ǖ+GGjt'jY\O;Gt5%zɶk YaxguA;3/X!ߠJeT7o"ô}YJ#-RGK6t{m]YTZ+KZÊLwmrk(!%'Tx_|鐂e*(Q˧D{67VyVuUT s=8TFCUPU:y `TR^ Аud+Fb}aVmd;hTq(gJ5bӱeF>ŐX9v- 1WCނ8- e9nVmS~PY]A}I-ƥμ]gk֗_-Vm0!=uhZfqq^Ǧiƌ4ZlwnR;ZЦO>DHi@iJ!SV0zLL_w;HGwriҳ{_^ɓhꌏãauS]`YՆ;TRtxT>t^&t'9[j?كTUhB&mV U^5X6Meny~y7Z^MU*,9"WWyijU{^(*YZbq }r-k#$ڨȞ{iU7mׂ7'ꮇQ8)q_}μ((3UL-'_֮TcyZM,TtO:Tا"-˔r-#YɈZNV,)e ̸ڛ'(qF9z+۔)\szޗO\o0ӯA4q'vPUEXT]Æ$S$'Z:EnUThȰ"%cМۖ-2UQ9HCIDVX 6+,TQ2MmpiiW#ʪ4$ֳl$][Y%**stҊ구)N<>VRIWUǰGԲAMc>%%rWJRV;7:-e(PMp ÁkђKK4-J)٬E-bY$O֭s^mm&<]"T]{Vۏf׏c1Qϛu_Oxnpկ-KeCǧZp[V-[Ъedz*INM TUw,ljb1ώbM`jm>Z/溋dGt4ne&+Tݒz"X1,[6,G$ Osh?!  JbI[0HyvH5O@`!N}8O X_0K/YڈSu(q8E87ovmn766TlǖJB/ #HB 2$ #HB 2$ #HB 2½5NFL&e8aioq} |7We53z0Ip8@ #FdT ٩@ У |?We53v?`FhTR[[[&O$;;[Vb6m'U}͌5!ɤ^o&O*++KDbl;?2 kfl~m[aqLa=׍<=`AɖAUfp_3ckft$HB 2$Ȉ.L%\TdG鬳Β gg~U#0B7A99kZ;JxIDATZhfPK/& 8|,]pcѺiѢŬx,9J‚)h34{ێ~r`U~:::dFoWkQ6t]R|U%,WAL_= (ye#U4|:&x:eFت:C!\م*.u^ eY),+t:-q ?Q/[tZioWIWWuUwo}'*++WsqN:H8h<-n d}mA%Tn%CӳOMN$jhQ,D [ÊPAYc7ʽz٫t?՟ǧɈ:;#%r Y>sstr'wdZ\x)ǻz|8YfS)҆]YwʳYMGPZ#Q +~5\erFe˪>F7t0,G/u׽E֖֑J%im˲jjiԨQ;ǩUuU_}k.y ߃>|4Mٶ@)˛:Hnjь7fl8;w_蚳&h*ي5jg_Ղý~e]_+.m{g]|qξfBkƞmk/㥗.P 8'Ԡ9үVMucJنl+wk (5+]HD=N8{o:i - *`Ŷkª "(+]]T@D (HQz1$ L I 뜜ܙ>Iyk Ԫwpf~‰Pm %88ˍjŨq Z}L934"4Dvy1!|z:OA0 Zؚx>co 2O搝Sf8#y+ũ;Ⱥ`<\]yv]-lg}ۇ@/$Ӱxj&oMIiѫ Nf}vּfdtefwRey3W>1:DJҩb,< \ʶC:Adn6}F_=m0mٜ^δ5Æ@/iAmk*WHkRƶ)O q܀h c[{0Ͱo8Nsev{'#*/̈`o~G2;lq+FW2ug8=k: jy(~'4qԦ统BdsGc/nКZiۘ4q.-xZ .1O (&O^wS};W_,?wL\mc要1yM]umg"Yӣc ts&%RoVw(wy>Z 5!G鮪|yYLria\y+tbj' #Ikt?" saqF_<X 30hҨ)KCf>1>I1fuL 7|ЋȖwngVVՃMLJ#[yfbcciۦ 3g"6Oa.L]㎻hP~xmKISlseC!g cL(!ȋ=X5m&N8q:#vFmbxj<יQ 婕|0~2wNb#-o\ogo.{dn/VV~Itğ\'| 1K`S!=Fgb/?ˍY$(jp[{"}=ie[I nEǛR43bnc7w 7cp4?6}9ܑ|\\fiyUr\y1oµۈKKE Á#/4M7fAf szE) : _'\ uM`ޱįBfBl6l6>E@Pd8<iB7:7]uVy("(nO>$7mǵ~qmX(ۍŋb߁}m%$&N;BLӃ{;a6ߦkh8>] g`;MNo#07e?Npl"}v.c| V(PI`gS$3?[8#rG[>(_@xi|tw3#zon$3+<nglH[$,7 V0yel/񹗛} &i¯]NJTrM !v93%<`٪ TDDDDDDD4S3 յHKK#  zLbY0};ȱeײ2ٻC>IĖ/pڷu⩦1b) $o$ѨAϹi*ovu`l 9r0k^o7!5פ 3bp:  L$|_/;u=ŞgQ;as@c#yx48\¹\3vLܔ(VNyO8 uyWQ21LuM#))G5uiy'}"'Avr x2 w\NQ0Q76Y(XLPB:FZZξk 41,VA8y/c==UYA =tp~bYI4  %i28McI.cyr8zZ[pV]m v-3|FL[gA:1'ݔkqlԫ_$itCH^͚py^fq`lƬא_^bb]o&$'""""""""/ mVXfxէ`4k m+Uѳ&Œ_ɯK٬XJY8tfW߉w`:|̉ؕU%')' u cNrRY% kS`bqsdziyx~p2E#V+- ~9d'.F Ia Ӷ6zr`%sn!jYT&iD4nHDDW2<=lXbX5g żڢ)5'VۅyjOHԲeKZlY~=Q w-x {S*oN}E4/#^͐0ẙ~pq``XJe?:X,$XBʑCܹiޮ+u=$x'e=ڬQMOc8ƔRM]oȻ^;Y=jU Idd l6RԪ]cGp;Ҿ}{֭KNvV@?a-Ra as%fάXj+qv4?g/Q/p;9VlWg@`ִn"#5 v2I^SizAxrEa;?z6S ֈf.6 } :8Lo_ _l,<=kֺZ_QxV!4$!9+O3=Gme19vQ~G/vh'2(y<n0+`)+6pv&5)۶'MXewp@w EG->( O7aIK|8y?Y!O3fҢ85/ߦKO_?ݍ~otÏLVj( ݌_˜AKm5,V yYp ݇gKMìa)4IWs^ Z-J_ʶ±Zqo0d<=O=(PUvzNwDA'l`^%=ʐK6 >ƫ|N,7q|y} +SId}kzk0q:2(1Oe\-L'}{pf6 1~Ѕ)eĉԬY}ʛcj  *O\EDDDDDDI_3RRs$f^#mYTw^Pqt7̬ 8^7CQl?fmyl\2/*^ʊkLL Z*q{RRGu*$DXWCuvh1 ՊiAVV6'O-y{> Vy;ԕ2޻W2DDDDDDDD xgҗ!rIyRSԬYvϭ]y-== YShBp 6ۍY4 K{ Rv•6SSB?aܹ':I=LeIH勎˨Gbg114/S>qӊWhBX,xzV%֯R摏V~Y7eMaDDDDDDDDDD~Ti6J_տTIjBHPBDDDDDDDDDDD*"""""""""""R)*uajłbQC*.W^)/Ny*"""""""Շ'CʡVYԳxzzp8*;p8*s?)o\EDDDDDDPb^U9q9뀕ڄ%33lnweJ~'n7999deeSظHɥQr(J+u:&IMMS7_9X>W>T?4WUŵr\:`7!.iDJ)']9תGtHPBDDDDDDDDDDD*"""""""""""R). ap\u-"""""""""""r9NlYRAAAdggWȅȕCpppuIMptVt:̙3UȘ IDATxw|TElI6QCzAAł(vQA^Tް+]AEwP顓 K}!̹笰s̑beyJK(^l-,I$핔qlT988kݸBB8aj.,˒5322iӰ钶JZd Iquވ-];;[YYYz'lplvN\.ܽ=(i8eԍ{dRSS-4OfI2MSWnbLLL#)(e؊XWpDDD11RSSeZEi.tɒ]CBB:*'T嘪lbH0ds:-^rQE,7BU/ӲdXVYIE9I@i:OYB` rlQvWԥ2MC(:pq*4%I^CE!d@ Pc2US)yԾDy)%P{N/6.ս ͜?S vx뛹ۘUO38[.} "LAwlP灊|泣N#g&EqyV:U ګeIJ5U۞͗ w22Nvԯǜ}Pw)O[?}U?nwuW䬥kGKkioV6Z/CT׫w5`Nuu`yj+>zmڽ[I5=Z6U W"2pO(I EIV/aTijx008_*C-i R-P0{i̬{u7ןGԥCR)[kΜ⎚rҘYrLܫus>4j?n۠m#,F|_&M~էOwW^3k^&OI\ gٜck558 ӛS)vWc>+?HP[_MrO=[I@T C$!ru.m^D{->7iyd UkQ͔Ś2oB:+ʉoxxz{}[~Y=:]"*5L>m#syon%>;8K2DIkLqF?ȒOVf*ȹU߾6Q[\h?1*uj.}xLSZ(^wiC,g{͔^C>UV.u)}O^/:3I3+/VFW}@.f}ջML}p(R?tk)ӣ }q=vI=RM?& Td+-+룵) Eio!'z^Ig!|ŗ lձcU9]7~;TM2}2=JUJ)~DYZ&.BP-yHEUm[v;—_feld*~랜ZG(*BR>*of4Vj{f߼ CMI^Cceru:g@zFıQlσHB[Pզ96"wejТbI$"$]㫿tØ*FO+-eʧU^Qٛ yv*HUkT}fpU)#{v'XU!_1U3;{ݨC',u.%N)NٖtED֑M6}r1Û'ʐ9+:O;}$!sMU:vT[~x\T3W {:4vic&kLn]5p/OI_Fݦr;fhqŽdh׿$%R |^yX)3З5iW\+8:h+Au4񭟴Ôt[?XxX}b8c&I@A<IE-uFkN|`E>~em rL\@h9&SLEX93 ~L9SA ̏)'á~YjQ:jNMg8SJx)I.@vw KeBm6iC^$!e[g3/HB $ /HBpd\`Xf?!E:_~AI$!_~AISd&=DHuS̬Bynh~k{ƧQ~}Gܛi^|Ff^CWdT& U%)Ï-?%u1Qg-Ш*YkQI_|M^!K5e4>~m{F{5O#}Z_-LR[Zs`uproqmtL}.=g~&e.:]7w4+c~OU\BvIR-mDՂԃo6R̂PQ޹]#KSq8 Y| ckpM|)9Yz ( mF^tyҖ/ҚXuNޣBTZRmtmպY%˗J?~X]q5kվw? Wv[k5Lu@5wVS5[|[`Up^5N[}BKʙPؾӐq$VKbrPvjlBڗ^u]X4azSf};)M Ti>V^fmC^Иj/5\x{)~iSU/Q}Sicǎ#?uP@7iZXv{yUcUDOpcRڊU^֏o6"F2|yO5UU m}5JN4ڔA <~pQBFRҭBۗVR%B .R%<کzwWr}{UFު{z?W)ݒdUդFպzMMIyNW/PQUTYU*$Gݣݨr>VӲrfKķVb߳: X@/rLVLSݺ7wk$&ᴇC1ceҭKS7 R`z3,YVZmjqh{m(v*DEz<ҕZ4+r2MSM&u>N.W Z|> ^##?8J[^isNC|[)jtؒfbM5r5Ԩ'hkWU_1Wr%a/4k4S=jݳl Ҧi}Kx~m0YB;mJ!ɣʗT.T{]~F^~ݧGrcQBAjĄG|NS.\Ŕi?wqǪx zi@z}jXEܚ=iڄ5QD"}O4T}2#i:8X5(0_5B#f)M7lνRPhAAu;ozz vߣ5pT=ضs5ekjW)p#X6Q}CAj@G1J[ڲ˩ڗP)(_J? W$![4 j1f#ZM:TYZѿ$"3W?SJ馺|ȋ(TAgW?wCԴz썞jZ&P|yxln2*䣯4rh~#R~ $Iܩ1QmWei Zϳ r^ЯCNQöuO osoi!!HOw:Yi5\^}gʹІsFw&t.B$!_YEIv:\`S?.0,$ /HB $ /HB $ 霼vj8i8$$Gv##35Xa9&$!_~AI$!_~AI$!_8vpީ_|uΪd+?͞Rm:v9Ug}gnF4TòA:z–߽v?˭il 7I]->Ӯ2y9_]BҤl":6)k(\m,xڃVz4 M1iė4z$dȰ9^RR2!fN}V6ϟɦd+F]B@#T@lb.a~TWnsϗOۨ  PTZYg'u6ߤIY(J-U/[z/yh?:1PڵSlrwWchظ5޲jVAiG6 }5s0wkwA?nw-釚p 7 ѣtV3?jj ӗܒlT6~(qwbe :y܁u+][}W^HӷR׮RuNy@~@c}U^Ww/SwTZ"ǣ;j{VQe-ڰRKaIC2*Z]o)dkӼwG$fOAd7QU! nbT-*E:nS6avY(-ס4%l[䉪+㞡jJ5hŚtfd^lo,.-Z:R匕(^[oRvvmش]{TjթT;ު *8P=T mc!o9e|KQrڶi<ՠ~WsN=HuA\l>Z?6]mE-jDHۥKѴ;]Wq̷=Q5԰^lJsUT}TBDUސ?KڢW'qQ:%sB 9WQvo<1դ~/jm=={z^kXz|Ws_īu$!p .@>5^/GO\]'gY˭mS_R~[~U Kڏ,\þ쨺Q4eH$~{CO,Y5SO'}s}KO_`iߢh֡o*=sNWsMh5q^JpE Ctg}dej뤗ts?h5VS־Ƴc5*Ѣ*&,;Ͼ a}5Y+Ez]=֤K׫#oTHD;YJ8N1[njײ) ュĶܱm/RTW+i^$EQFed_OMUZ {KVxVvxB䒥 c$K.In[Rj7rI>}uL읥o.UTgS[g .sncKtp ޗEVx\kN$!*Y:*AW6H'LVB*ljخ")oea2E(Yz} X/Q/ohmѤWG黵nY|;j܈;X{+%T]u-z*po􏷦?D?k)Y ΰ4+ɡn[QԨZޥ\آ\ePm$G=sR=%ZR-ߜ Г%PxZZzx(ޟݶP&IѽQߒ{Zq@V1!J m~GUPp\=6ꟃJ$K׌xYRXJM4INI֜jn$☧]RpvxUUsi留yӂ﫣YJ^H.ݩwr((^8غjݺ4'SoN&.yPONU=J߿nXM*VKwvdL p!a&򰔸|fpw~6RM>+a|-NrU=1MS O )Wno4#)Hި뻖!SUU̔MRҊ='򙚾-WQː,SaJ-?{]_v/'{k[VBWP?,-`+E}X7+!ŧhݖ=ʰ**HdkZ")ګmIr'ju{E MFU>q#1sUG_MV+^2dU;&2S\QQ ȩ=-y%PCeZ}xGyE5iT8*jtS9/( xxd>_FLԶd)P ,;j+K$lr廜VqŮB*G4M%N=%w[IS;۩K 8]p09%yԂyk7^]RRZmUJ޳S U&GGr8ϒ$}i9[Nt_PdʊtII)kL5;g vUp$C6qr@rTXx^`Ō$E˫!@]*+:]snf,j"[J*Kj.Ce+5W;ō=P qMv$}6VuT5S)6zgtMpykUY  (SEڵyf.nvl?Fq*u:!03oVm2޿Y'I.Ewn sHܢu*&aRܒ$T/ӿ)r4OGP' {LF "f)},Mڐ&)T ]hCVZMBi 4m>u^JQġ_lcaOePPh\;Ҳ,)PX.W;l^9Nj{iwĦq,z{ ?>87Jc/[Ͻ(qU ͝][T[G)rvr}v^s-q)'-E^I(1 E࢕PO}5B7fgUIK=n#ePX'߂zzP|VZ[WU앚KL|I==~3?Ӹ[{h\nao{[>B{놦jܼ9{ztm;_,eRd>BS [^*PTl ŸkӿoK< #*D-4▻'np뀖M]R~#n*eH٫ =zjKoNǧ6팭&aR|*mcyUF!i:Ub#'3r؇9q8G~< {+ WεϔϽvK|%A.[*-EׯX$b(s?PC^jFp]]7-}~MҊk [SGh>Ԅ)˕cWZJtٓ(c-ۘqMնV8 zE}_Mjк}ɣZjmgn?:z(y>\S6A2WWQng5~4mtVjGo{@NKe>*K%/c_SɭձJaPTp+*bO7OQՍO3h_2Vg^k.4hzZmU3!U.V|;^S|)Բ+Pl^ZbR%HOwƵ+*(<sӵʬꥃS=q^)u['S{Iuަ K?=5j)o?i8d&N& m#ia&Nu@k'!_=aWIumZD1|TAL-:H ꅜ䃳q޳mթ IC%R{Am6_ ffUOf!q[*p5諆RqŅQk9&$ /HB $ ? c?~)~+/N{&DfjR>[  qqI&-mq-۲tb)_~AI$!_~8زIIxDu-3@Q1%Urճݔ"aܨj#A\ώwߓ]oz}vjU^nJ7*~'AW gǙ;¯I[6)22F!aHOgU!Soۤ q#8q=;~}&DrR\AQ݌1n?E{W gǙ;¯I'[ӟU SlnF7=}pr׳LS[߫yq>$øGqz~rLO _}W #/}|e*==]>vnF.3v-!CN,wOeɴ,Y@zPҡLqOX~T.gijj]'+(˗qRڃտP})93!S y+W,W*U"H}z jװJD/!%CZ^eR /,.O>Wˇkx?vi߭o,𘶝k?5=j$!1,9Qzz$@rFǛ!I| ,{R'vj1z5ޢvV$LS>2._Q/}LYYf, 2eޭ+iPyoS )El[QzdcgdEE$_4Z}Zup^n*ni?wp:qXr:`B-RMmN)(5-SaAw~y}9oObrbէ]mY)Ӵr~,KiߖjP糐8cv.{ʴ|zl|ɢyr/ Q1?,s5x@9x[ywpa*C0 ٌaHLI>:|^ind +ԮRQe] Nu%;ˣ,̔k*u20M-odĶQ]u|uxuz].ݐaӹ)et}ݟrlT%luvE+ҠJj8k֟/j+`w銸,ܣOަ+OWRY/.atRWk[%NZIC.n)_5>^*Tm۷rŊwEoEEEI!CN![,$Cs^~;#oKdf&jj䣻5݇&|=]6twRR3JK9xt)IYYf4NM'v&ǜ΍7gܣoRhۖ= w8/݊qoCmGElѷ}X2{;rL+g_%QϐzMgxdFaktuT)ȐupF̞|ˮ.TS蟝j}uʽZ_jٗinZʻ5/^u|gWPhpת N^_ h$yV}^EԉU85̃4u—ijuUWֽ8^~Q2MԿYiԯ^utpˈUti`W[G/Ҩ)zJ?K+כú?z䱳(OgU|z.zQYN 7x\.y|g$r߯*y̎&CVn2"MC g$ɦШ*.(rj.D:N0vtc44ҤGm^;!ɷ{]cj5SUzFL˒er::|ֹ,˔SvzO7JyRcv唾£uY1-eZx?_(,ojlU@ >Y1O+]ꫜL|yUoq++l#N!SES=}Ck( jjh^@ g;m7E{.{LT;~[;VE$6L~.UoJWrZc3%ΝdЬaC;xsYٲʴ-מZ^K{\3^ۭzfp TИ'zKzkNbN<{}E-*s~^wݪq;ܦiUt 7ћeֆ fp ΅kl//<_w`5+*{f}ܳ!/#iU[=u45:hM\Qܵugm^X#;Q%{8w5W5>|b8ÊNGSXVFS{FTv1V®Гc_Ӱ9}:is)'I>m[:W{:%[ SfGYۛ5n!^_LPPW2L+^{_IV=z_ϏU>?WUРAúaBJT\ U;aKHW'[n<>I^Y3wޫ/UV}TL۫nSnըBJ8q5{JztJMiZd)sz$y5} OkU9gs}*+st}U7 j:U*N^!ɒXW\VjUUmիKem]IܳjݥTZmKUVqUT^lijɺʒ{4}^V_Īn!e;\V˺I**'X3/WJtm\7]Ͽ5f&lj7W*Tn u͞Nӫi+[}P^yiمw~^Z]}2MOkup^!8嘲=^efyeBr׬X,״4-Y?OYf,٨c:M1#;Ys%,SiI{<'[qZ]dPk삛TRW٢ʒĬMڱy{Deeg)\K A7 ISIzН/+kb'Y΍ :Sm0LϻUeFh_ t$mq/mڽpnJMޭG7;v,҆~5TM{74>9Vz Z\5d(82F=;mr!ɔ>}=Qn.S NBV;:(JRj桞6%d_ʷ # hv؟,K 6۶QJB\J*<{'_~ ̡Dı l )-gfmyEeٲbT%+d)e)m][@i6GF(LeͺWE\'H!Q%K~zF#CX(##٨rמLKC IJ޻OAJ+ Q.5%噯Ӑ3=:gkҭrrRv>8A!.,+5PPNKқO; c)iz }iICtlɒШǜg3fwnZ͙\{iU_o: IڲnV;81D/~N4iY`Y7Kno$J5꧛]ۦESTd!9q\%tj%Y$IܡugUԭo;'h&,_C5pT3dKUsJuF4=ʌqC_Ҹȷ5Gs9 g Qi:;b>4NU5C*tex ҵV^V^u:jȑ)$/>¯jRVvfY1Э9aDO6{h}9O/ +zG"{VSHn0i9L?Se{>#e,=-0chƍڹϔ+bkoNXstOLPJ w8}cM nQ1MF`aؤgã(>fKnB Ex box\ml\k\}jc~wܱ#| *,# xчE}jy0?Q,TMs&i7jʡ۾BO xÔ'ڹ$GOJHHԉ:ɓP7,KڛS6S^a<4]yyS;7׍Jh\T;ީ}˿U9T.Ӽ;*vroH}TaI7Joo֍dYqr:]  t(p_~YJgiׯiҾ%߳NoC=J]IWTZvlPWGv i#&jTtttuvr>am(NsFݙ(B2<]uɌ`@h$áF.Ϳ7(Ьh+?N[b=rڦ>,>C ռ[^PV:e:GKfܤ'_ҝu^jޥ\I *'3S 1Aou^|jnv:k٣tġ]uS}fC [RUWIyc5{CpF`6OVrIgωʾ>M>Cg`7r2M߆pz%_ۣ6IB )k u8k.z=H;.>%=<_T=+ywG}>{&=t=w6QGB hcȲ,վxaAi,mYTɬ⇩h ;IMZvt*j| MC2:?I#(E IDATGԝS ѷZ>gVY-3P0֭HMq&r:]ڱcg%Xr5PoǾOM5=1Gm8NgގM묛(TEz=H7:kۊEzMJh7#R4i}j//we'׭Y^WЪWa]XԨ?_LcmԒdZ.x*DRM}w8(dr(tK~~?y?YON6D R/ע[Irg),zʈ'%I@r}]Nd W/oJ̒[,?[E'4yk^jtGzjwq+?'B *TAn n2K?PAvٶy{UzPs T/bZ_L%;'u=4/dԄV^3T؎V@,UvmEN\x5hm۫_[` Kl8>SmvϪV9fA*]s߄7_]5աx۩:,D_/ Z|HFF $58S+IWmV}9js)t)|Ͼ;wjUo}{.NG;(pI5iQ5jpN$>.^(K9c5ncOnQv5684PElW{]c#'[.[PU`P.;ݨS}>=خQ917VA~<$;Wr |j$ݨS}>=خQ9+!Zm//Wy R- ʗ_ZiTF{AͰ]vHc~*fݫm۫K^F8o׫g lȨapܕ\fzw DҪWsʋo@IV׎cE` !-(B[PlA؂"E` !-(B[PlA؂"E` !-(B[Pp }]׫^uTJD[EI"'589bHB"R^3skDoB[PlA؂"E` !-\@)ܬeOE~ TFȥf%*,f_vmra٩˭Y^9}trVe5LԢ]'ujX. ֊B$G1E'4rI2UW(wbxc͛K=x.Ru=I=IRP;VэS_ַyʄ{`Z-z-d9^'nGRqM=ELT Ɗ5nUM%M/lAد }z|K񇟪ˇW[3w,}^ַq jw }GFNL{ټZrOz,ao]pn/%g%R! 5wգG|Mmܭ5.֚k܁؝:{?47z[_Q"$Lz>5h|?8N} 4e: ڭ+vKS^ dȒ+.^C23M4W/]p5q z)s#YOF,|Kt':dLO^7d)g.%9<)J _pTQ,r,TMy7whƶG1WXMT/ۼZ ydȐ%I2jʱ*jɡm>;6OWkk|N5n.4U,IVNth=`̺P=ܒVmS1Gh .-;]qb>޿\iՃ֗e(ϙz-B-$g[]3AO\g6o:|P3}}H<\]xįBsEZ0QOW+Pu?r8to钔4=g[TrJ95#F~H.۟@xu\l4@WO:K_[_6-h~}uژvG /iu1j5_^O[J }y+rŔZN[5jpFU7ܽW=ޤ>M(B[PlA؂"E` !-(B[PlA؂"E` !-(B[PlA؂"+&[~ݠ}{W tWzSZzclӮV@t G@B@onGtWڶU?Nv>F@t!W8PC(B&ȗKj@,iZer^>0jr7 !iߕIt7T*sj#D q ~!wы Pr# p Gщb_M@B@vL,+=g@l#-nP!:8b1 @l!wvL\ Qp8b1 @l!wQV@#F [&WB+@#F [z!1vbq 6bBEK&^{KqG'gfz3~aLy/hb?Hw Pg(B1vAhm dROK4}"%^:C7PFN!p)e'>4]puHqֲ"Vzp7ВԲ/7(7PG ;Y[=Z0F}xzldWyʌL`F6t㳓54-sizdh "8 =iktܴܧ34gyc'İMlU,[fĆr~58+〾4oWf]lS$rr:u89k5S]J 7nP3<K;o֒n LKz.\nC)߆5uܯ'67Ѹ^Yܯw+]ӶK;%eI iߪ8+q&RZe5swm:G\r9BuK[uJ'\ +r9zSc(cc;\rp cK-Sc'İ=U,(==YfZ5 RoUF>$z%Ӕ%\)yzuFF`vpTtz߬aN-6rs•yZ8$/.К~4B]8v>QPѳ0AY$9&RhLߧ/>|2URmwo9O!)2!YjNGVG;?61l㳊e3N7jq9dZ-۩]ޮTPg)E5u3驇:}iᇕ_Üh}5/,/_: zb룔@P$˴\^ "fZPqJ `Jb  БgjeSoז[?hj`Wzw`+A ȷa:lgZ=<<:ezgS[ӫ }hHus[-ڴySYP5dw@̲9>[xzA~ Me5k#䑆D?x69Du? [Aհq}--|MJ2+!Ym`I瞒zt@cYR[2̝[zEk{Z9'Em/:-/?ɑdʗGfJ0r-Y2±[Yfz͏ҥ,Ս~ce iߑn>R1bU^CiݫEWN@EqI{6WO Zbw>bِ%@Ko9KK%p*pe,m6oWѦqu][!)7j엻i%OUjVx–BFk9]3[ 8rwÐB!ǖeIs}Db*$)NC&>ى]c5SYj6oW&SmH-f:1lz, -> ]xVPCtj~jj޲*z܎ Kh3oSg=-e'{Ѫϗҭ#j~g+;sGvaɥC脤z YP|_UƥC饋Fx#tLP_/ ̆xw6j2۹UjDi%aOmeJImC;.r8P]68hYA׍9]g? RxV !@p%D .CK+BW9C9h=iʨ.wgTuO:[s%ڴu3MƖ)tKCRZQn3XjV|Cߢ#Q5TB^bq$)Gýjrȥ͟酅~{ߔZ~?A b>|u ȑqnC]"u/kh;r*uQ7WãM-9kSˮBM> ^/(Bn~{j]3vn}jf]b:J?AO<.ZKjZȣOӴ * _Ȓ&P~~ԯ-[z+ԝxӂnW'ϼOvW WD>. px]zhё}^_Cy6/$"HҠk&jv0tgaSӏh|y+?n*7V+qSZj9;|58$G~ Ny=rrg)bӖ L›YZzd/ I%$tȐ%3Wa~%׆e.\ggt+15Yq#˗T҆V^CG>H ǹ0,Y*ߡ:ppE Wnq$QOJ(3y6|5c f9e֞1O7M䳫#^\\ey&9jYإrf+ܮ7M//^\l3r7ܪQ5} m+Թ{J{I%}Z];ԪKqW~2X|e]~z1Gs4oљe*p1lhWP |_YF0O9ݣFDǑcgv%@WM#F@>bݲ *d0okPW$ks4n7]6*λf2 XZZM 5,PAV>vH]^hE!HQ䤄YB>8&b0s">U qNHZ$C.#K/yF\T n$O(B#E VD1}O@U62r6$ɒ2+21V8\?^mdkEd@ @l#-nX+-3xм@Q#8b1 @l!wQ,kP8b1 @l!wpDDBV(t7T  vW;q D'b}5c ^nц1IJKo|yI r |jޤc :@i_@"w6\ !UrPor  ʗ_ZiW1]a 6/n D+ع_Jkk۶Uc @m_@!wF!Jңo@#F [:܎ ؂"E` !-(B[PpEd˯o  PqJKomj90hqDr7c ;(B[ۑ}#amӡ1]a 6k }1G EU|SSMN//7ԠLYmh_1}a &k}1G !iߕIt7T*sj#D q\[=@#f;(BH rܑ nj#D q\[=@#f;S1ˊtY1ۈa!F 8P(B >m0P@l#G ܎ ؂+!JPbq 6b{ @#؏"Dbq֭_'%_Oqnt.!F@Cy IDATgciVxeYԹsܹK.;=>+!JPbq)e07RnnHXmp0_Ń}TY!3d* ꧟~R 6+++[OoZQO+\f \QQS'<*%ү`~hi1'hI7mfA}y| x3_ѣ"z`ͣGME\<2\ vZ#&i5ypMHM'襑4{H2\JmI:M5DRlpyEèx}}W =:u}?!`82,˒a Y{>PBW)I쿟!ԲerKzw鷿h:vS>[Ƕ-ʹ4f`jG)YQ? \S.WB`G4 |q'U̍D [Ćr~58+u\^KV~[JoA=3N*Vz v^%/4{;9t 4q`;dck5Sժ-! ]=VK9Bq7ВԲ/7(7PG ;Y[yt@{MizdxXlp5c̓J!sf-fp;Q4eK_|tؠaqIVu8(FS7\r9 ܆$S K5kb%_SOl* #NCoq}*/_c3OWF,v*n7jGdVu>޲Inqʕ`\n2r%vϼM/XJ&뉗LS\r9/7j*>r;e]*:`jߪ8+q&RZe5swm:Sy)7OHR W+iκg +K_@kӃ InG^wk؉쇺Sogn;,]ةOޥ] jƽ9qlr1P"D1nX-55%]fX,K%I94eK6vU|[Tr6ekY0RNa4*:a!;у}Qg}0Z{նܹ7*!ף42훐vYڜ[2-uh7@|d'}vg';[~ۆ=2s6גk3P j[q$9[u.>2搌jz0:P_qSa_[*s~[Hgٯ O)2!v]a)XPPTVH2JiT}JbhkK)wa,ZYfJO?^ KLQiR[ S-v;h-gi$Nw?SL}`xYS=ʍk8x9]49m Isu`>s29|0`Յ IQc{fM/9xx4SB8^Ke&cMYenQ!Μp޻!s=6]P:ʿ&D~=.N<:;WV[و4.ňaIRMߦ)wI>(5ݯskӣ#u*T׊nPn߳HӇfe O9yJ9V>6Vp믾ᆪ-[uV˕wߣzP];kQvkh/T|~!\mu=v$M:K_ԴhWEeٵU ;+)T%I Z#jR/Gщ}asoL|T{mճj`s!>5MkڑiSCCg鱅˴|UyDw6m>ňL0F~X% yR*>oZRۥX9{h#Ҍ Q{MqIrS;,ԗ'SS3T$e9Voz{$}8|:z!% DFBky:;iM~}m񗙨yG>_{Hf$H Yleg+yV2sa(je&YCtȑ4pۧkjRŗa+R{O76` 򲕗'5]zfkm~U91"cN-`F.mN-F恳mסJ;dR9.$ujjoIˣ 8=]eqvvg/fe6>^7owXkT-kK_^8!/6*#'WãM-9o=n͕lfjӪ54{`]KT^Sx(N%m~26륙S 4 hOm^NIENb/bOkrԭOMӬKRd~}4}Tw .e1_BM,J~N96hOV U#$|>%z_oH)~|ءޑS5KFjriQ#eE49wcC V]rhœz'ǞkѼ:wz6 O7rt8Gӧlҕ3sgnɵ< lɽYAC>^-:Rs.]Wh?]:wՑ֓u+/ 4蚉f]TJ zwp2]V[BG}hPaU W^SxO@;U>z@RvtCŨj~?֬R~kygkފ}1EӪWa]#ݍz­$9WXT5 ${*/R|B?<eYL›YZա,8z4Y~2s_0i|֥ ?8;UC;oרMFztY#y[m/‚| 8P ZJ!h\wR=+Aqqr2 2C UPDo\S_nySee*? %&&4$+`O< I&:˖_.]^%'9T#~pٝ{-kɓ$g G>)]JHCL3PP~J/oGV>#/םqm63w)yoq1(ƌq㈗7+W0Wٹ 9 JH!KfЯ|*7CMks)A\-(cnқ&hlDN^ڈyIUR?]92ى8b ̭58YݗV}BtǛ4PҧյC^_{&5UNjTUA]0R׼W<~~Q v9X!>emBۇ\ Fg*f &c'9%E V^^~ݸyÐ\.cN\.n9N9N4HaI"f?6rf,ұ%ɐRK;?vJ0F]X(AQ';JǶ1dHxna jc%{a7F\n܆$YBfW5 ˽3͐~-mp؈\ Qbq 6b{X,3xм {}ı}@1ac @Cbq .P(C(Bm0cuEI.[P0PP0(]|1a 4k}1GcXx"0I@t"W8-Nn @lkI\ !UrP 0 B|y9*evOхb_m㸶{ Gw$q%DXUZ͆Hw@X۶եGOхb_m㸶{ GwP(K^Nm0P@l#GclA؂"E` !-\@4{nwevZ81 ľ?r7=E}tu;o l׶yw:58 1 ľ1 Dr7hDBEHMM79EHw@XR2eM*}@!W8PDMIObW{vW;q D'b}5c ^nц"@/nVv>N0jr7 c*fY?8b1 @l!w }1ۈab cJ|}1ۈab T"Dbq 6bB5-_bq 6bBգQc r}-Z2*_;R7?9S5՛Yt {eʣ|AydD[:C"S ׂmӚ< YiO^Kg =$.G )^4p=hzE_ɸVso;U% jWZr+ݎa(XmMǜt j꺁 BuUWHVhkojٗvz㆝<2Bkr;n$Y:чt~pݗj^; U#mVq]Zwy%:Y׼s|hbHӺ:γkmz-xt]/މz3jm'x?y&lxsU˯6ҼSz$GjƘ'tC3zZr28vQXw\r9 ܆$S K5kb%_SOl* #NCoq}*/_c3OWM?r)iIK.<=FW:##<@r;e]*n'Y?G;~\G*-VrP#:uŗ}k~tnK%k݊uuޝNw\[{c6]zJ8SR& Q!QW.?#+IJUYumX^ײkwUTDD&&!dʽG IHU&3|޼.I3799w9g${tz)$},UGUnc;uPJq?_˾^G2HI+bc:=α$kEɸf&d(61V @C [Cq JJ%.}ʉ*D ~x^SHaj+hšrQM IRĿc]fOc ʶ%ɡ4l,GֺʽZz[zxetݘߩdVɱuyه5:=3x;R8Ft=S54wúwA4OC*>Uߞ-eM[%؇:Sq`:R6ns~WKjd^;?%S]\?{Ǝ-%C;u_PM՟rF.T﴾LOo-M%7O+\NPM FX]y㫊\cS~۔i s+߅;7i %FmU(lԁg =;k~)) (+rܥ/VnY^@#zWQh(7(N>O@9=Qݳ֊u!Z.Y-qǏՈ_h醠֭X$s`uqШ^׵^Vtz 5Njee˖e *.UҎ$ ME6PǾj'Ti}}{j5&5hZ Q& ߀lI~}rvGGlߤ6'Қ_תgZ~WǞ_Գ܋UmJ\/}}t/]SO~.;4ve&aSiתOyi8êt$[V|:v*kvא4=g^Sdݢ۠  -:_'g]hh\P }[|)NKTaG/`( H(xnG 6!T?j ڗ0!S] 5kFM~wCz4Y) QplIӉ7ީܢHѽןxz̺R KCǜG/V%>A IDAT-+Ke _l˴Z뤫)w*1,a+g̮o&;9xB^O~)1b vhO-%W޷G;jHSQX-Z1ʶ~cqZ0MS~qCAu]k qZZ0q}ۦ~NWɠkG 68tuuNœzppzoCO[TPCu׹/] kہld$% Q dUqM{ϩQ2a?W9Xؖwmզ͹6բus퟈W1Stw*E?(֋*{uLKK6[Fp~tU.Vݝ7Qm$+GKմn[˺;k蠮x}_{;ƌخ߬^|oиzueJkۧz54$@ї77.TEuK;_Jǩ&J4$!^_:M?xP?pEy*%%߸HxE $Kթ:T|j[2F'Θc{)P˄#TaCչyIm5x i, _ۺ>%AG HCc{wHy^IiwH^WTk|-P©z9ZwdiE ܠ֥܋xkէ/]j 5kuQXW,ӠCGsӜdFzJ-Pf.FV|J\{a8IWAJK?IWMU  z]Z&)_WaN%6 sT/#V r-SǶd$ XOjmk[j!;Nqq1r:2d z4ۈMR!\r&+c(/WԵB׿#*-3)I1V}ߝ鈕'#?_%i#U>B.@B1kޛqVغU5j.R\$|y/qkퟟ9EPް;6k$M>~o>[hzTzOBHI_vrem8~ysTx6*\y})G34gnUp1՞[d v5z|QVPڷ)w/W<^v :Z<Zhrݴx б%ygAnmڮG?}bu'ԥPQn2t+{dɣS\\>@A/J8cW:ےiY.0~z߉FT?(ۖdrDv9ó4%$!JC @Ǒzߋ:CȐې$[iU9"1Z8\d$D" @t]ݡcnD# m+h HB яz D70х $Dhna ԁ#II.[ w1T rkݎz D&0Z4-n rDc"Wp@%EEjֲ@dѯ@B"@a$2UX|AD3Ta>zծcZ: DcM :ӥcUXڱ%=4Wj>T/)>^ǍTd+GB$)>vF|Yy"}T}Vo.)͎׽/5+/?kS!kf }h}nRyOWv>YXYoA4j)MBIiܒ^Kr4S~é.7`N:M' mXI-kFOX)KrdIrxqI;F>.B<_UJ|~]=LІLi$]/E~=o9S'Ȑdm{[3F&TJNZz'.{K;>Sq5ڷ3}`y RQH%-V˲ 4Mҁ MBVkU4[P]E{UNzCCN]??=_Oߵ]K_7}&o=}ԻɊ$$!W|3_.͜PuձzߟiFv~3ϒ]:daJ[Qڌy'w>?Q֩&) K]ߨ? aWXA |9 iɌϰ;6k$M>"^-[@= v'!qj; B$  $HB B$  $HB B$  $HB B$  $HB B$  $HB B$ W PM벵w.pFQjZuF$H?^4<x{g1 ~\pFv+c:&l;%IHA #!@b,ю$H|$я@H0D(BHBDGD$r@17.[MZj+w: z,u=st=Ք R#NFk3HBE8K.uԖvp-%#FYҴ *?s>=~IpIAǮJLMSrl ܫ翥7WFgFCM Im4̠,G1a䐄f(qr($Y]ZZ5 ]A 2:%y CL*Q۶%Q1̺R KCǜG/VOf |HBGrh6ln/CdiRJuH$)N'=WeH)3KhHBĔ-@J?>-\^~կ3oV?rsD$cmnu7\W*]B$L "@ A}NJðeA|^%-9zhUԑ,<m7gOC@# ")IBHBEhGD$RD? 2٤!vp4N$!@q2`@gr.hĘ DԴty$$(4jEEj2#!@i)S*ϗdD ` jױs1FBԭg?|V|(uꔩ^# "Vxq(tL $HB B$  $HB BDM벵w.pFQjZu\{cs4 Q+(4J;l֯P}="6YI#%%M I*,wqh5%[mV%6zf"K}bs43!$ݳKqpFIPnGla,uф$@/bnZ#60DhtLl;%,f;(AW Bl tL $ QtYDb3?%Blcr:]**V]$ ~c8M6ɶ={ira.hH2Blm[2 e+-iؐJMMu~HB/@d!6 a8d`P:mT^^ڷkZ4+͸ٺ}l sBlI02sז)QdnjV'T=2wUw;J~O :Gf'`"6 öm!Ӷ{o񧊋OPJr^Hmiva(&!]z ёǝdgm\JiCC8AOz)Ӑ- \{b*O髕kR 񧟮1teKuғi\Ҵw24뉳UGg1:?iTFB{^;T$DS@rr X]r9bu,MQӖ[=ElI}}2b%M\" u5˲p8c}|:%&&jΝJ ӧjIzuΕǛtJMܯ+Oq2qv @Pvns6U^*mӆu۔'%Q>2nNb>Iu_ǧkdjMj$!JnS $9-ud2-ծҟ͕tJԲEqLY{ QG)0Zwh֭z'4m_dU 1sN{nJ){dž(о->{@䢾]<CK]>P6oQuх*)1YwnӿخN4%jYJj+g̮%`֕ZU^:\=z}2{ӂg5qW48ɶg +1SВdr@â)xhM*_yG}|<ʐ!S uζmp{[Q];h^60(lTдj)|5@ HB ?Oy9xД!?w?xGW$n}#>ךUԷot6,VʖQ A{)9-N l^~qW"~U@d2>>x~&Au.kL{޹JdPbj l6v |ihW}C)͔zHG]u%ҋs{zpБ(2 lٲ}֭?_e\6:$x]ڴ9w.FZn!. D+p;ᆪ+~ppcjڻw;0uQrԦGNVםAmݽMIiIX1>ہB^LoWǴdJ"?W9V4,EnmoЂ+tfɐHMH-\^~կ3o.:NvP`'뚳?%л'4D ɼj"_ϺZf%I1Z$ӛ"GdU܊OIÛ_51#Vf0G~޽[Oj?Ï?R.]+ IDATr uP~>zZn|E^>rLmF}ztJ۶d% ZbRǣXSe*h;6|ʔd8c牗)Yl[/OEp)&6FnS!ٖ)UQQx%)wG1.9 [T_[=vF<ɉҊGt_צ*m3uYjZ;18Xc5yT&QiVK-[@= v'!qj;#!$>~ysv[ښﻧڵ$H9Ex„ ,+W~ر|"I CJkJk\m4r]3F99$xt`}9vߦm/ȕfj9El+UQЫjR< 0'i3dUTwǨK*" Q Dlg^g[2-@(E @d!6!CO23u@)+I4D )" BlG])" BlIRU}b3 ~G '\.L3b\nwhf"K]cs4a:&Ii*zIH wQhԊ x{g1 ~\pFv+c:&l;%IHA #!@b,ю$H|$я@H0D(BHBDtL ",,,]5zqy19Xel]kkTngzjꔋӭG +%6NЩsVl[>]cet ?_rq3@~|{;}XXJ$!@ K2,,}qQ5Ojk֫Oܩ+ǵ'jeK2wSꗵ멺އkkf^q^YS ۙCvRU,9W?,^*_p>]^i},UGUnrHyKw_l.S%#׈,tL 2Z$9-ejӡLմQοY*oɲluRC-M}Cv)80K|UOSN9?ꫥ5eC/~֟..ɟ\ cG떎&hók^uzfҲ((0hlS (+rܥ/VnRQh(7(N>O@PO>cOT쯵b%@uHKlD{gic5bZ!()u+5X]C zv<%46-@e_7یQRC }*ۭ|OkViˊOU[Nz-َokyjV֡[w4_kL˝6SŗsT2ш$L]Vrv욦-ء=lT}4k`!YNu2Fo.chIƜ*ے9T_^kiю4[LlVktT}=a4NeUU.Q l^~qCQla:&q>X] [v'Z/Kl: Q1ˎ5 8Ӑ9wUJ?Z\QzQ_VhH5[,ڪMse {2J^Ғ~tU.Vݝ7Qm$+GKմn[$YGu 4nb;ƌخ߬^.7RW[W1Stw* c@|éԶ=dN1[S(([A%6]O>^JVǜf Zp#5 }﨑/ὒTKf Q_zN]7}A?o~KK?d˪US|ˍ'RClYA|^|5nصlC}**KNJy.0T+YQBqLy_|i (GD(^zB/onykΖ(Ta-}yUSE*)\IHAHBDGD(D; " & @sq" "i] =3w1@#tL ⤦'!1EQ+**T.h "NN*,WA~ #"8`PTTU]Ј1Dn=˴pFSL?(Izċ#D1c!AI$!@H!AI$!@H!AI$!@H!AI$!@H!AI$!@H! wji]٥@MԴtعNoV}IWTjjMΎ-ԥgG]IM법d䇻8@ج,mCgdV v |g{R'>4'A9wV~;^#ADr:]m;E,˥?Pz@xg9D !IT@;faaa=@Vڤ7G]Z/^Zԙ:ȣ5?韋 =\ Xj򱰰Too~AN,,,,\"#!4^=}29LFU7 Zѩ3_UC+~iÇ*[FUCNg];bc )ZO;]g\ٷW{wƦּp].rhd+?'a=^_*u1EzzjYqSȫ+R5aJ)93>i%\>~ &oB7xqo"HnK('YlrHyKw{Γ;t%)]lYڻi]{7  vvi_#"`𐖞F9y(ÇS/ qM}-*l;_6Sזt2s@j_WĚfh{ 16$;w6'Qvqn+wNDkڊz1ty )ڥJTuMj*M3vޗ3K U6/Б!c0ܾe7&gWٮvץmmۍ)7Q0z"=?ACtkY|=+2 XکUS;Yq\m4`G' um; ׈(N4S~t %zW}ͣ5N""-Bh,"~pćwFUvcLKh;&Qn>DabZ2;Hy)r:K:^>C`R㔿,g: G]6Mͭ(i=F=oܜwypјÎNcZ]>  tdk)b x| D Og h)=znjOPĭ|UmIDϤ}Y +913 e:rGەE.ƊR\T%K0{AMlR2_}ڴۥvEDv@rF* tvq>%1DA(DQ,zK-Dq,o` }&P8a.jɼD>/7NJѧ7@051^Fݩ-lg@rF VWvJZo-kIH"Ƿm|a¡'V@.mʧd%LM-P >7S95:~ ?(#;?9?(4 DD}WeWnݷc>“@rZ*hEUnwr{Ͷ..t{rq]jOۡK)G !"0śtqSBѦ! 7O3ճ:)m}S/`f(;$x fd`9Qvmֵ$"kW9_]D{r{(ȟig=BFl¡SRj{("";aC[(yuu4qj}?.Qzuk;p8DfV*+ȾC}oPn鳈HYfqYhּ%˖,5@ /9M88DU..""""R;jAܞ%wbPDDDDD-ZҮcJ]DDDDv4׶-Be؈"""""urTS"""""""""""G!"""""""""""{"""""""""""G!"""""""""""{PiHmEDDDDʦijr޵6mbْúPDDDDD~%*})ԎfEE05HR/Xb9rZ\F]DDDD$ǃ,BlڸVSCYS^'4"""""kg=e"1:5^h$Z|vڵQJg2"""""O]DDDDDE]M%""""EDDDD:q[U"""""vZ!t.#"gkyڋ3>v#'4d棯b;t3ϤoU%wXq'62D䧹\7ڎ2`ZV`Z$dt:#o.)'YesaOa_@/oy+XeRI&R4$CD6i/,"J1cA"[b1{@ZTM 7p92WuNS߮ IDATE̺hUC"`-^7cy}x0[>]- ^CG!n: IQ~\kO;zKpq/;w"*+8]uJ\hڔVz0)Y4A#.r_}W' o}^K^$m7c۸"e;c)~@:G."R=C0=TlN;Xņced+&/OgGVC12JE2Iz!3]dU_MYIt@V<6o̖>M?""ߋ"j""{)Yo7-fKsxe?aR<-uxLہxZ,vXNדD7.A¡P@_ŊiVr&3NDDdoSn]eâ$q mSDcE.bgmzo-YMvI,v.A2}+Og38KgL[भkZW!tS E?-_?bk{x9ykY=97 ENLḢZ3o<\<#w|K%jފ~#zTg+7F~a]W0DogE`&"R(P¼d޶ tvO|c=KVBXQQuC߫59^ňO/c6Ro#a?Cdd_ާpZ+%*(qh Mz0hL/)bfN",q% 4<]>Fg'}N"(u[\fĺNmoD )(GDDvruM;c@Әtzq]V|lvݺVBpp܊U1,Oew?c#ҙ:LoX;1ӭ, +օq$qj8;0nM/k8}6il !"RWmBoV_rOk죞b%sͳ3^{ )/_kو)~"/q`[7ySg}jߕʫ'1a`ՖFAm^Pt-C5\޴LFT=""ǔU:ZCyS/G nK3|=\'ZS~t繴K, mtډSN2ipqRG᪏saξp20eQ2{_θO/'x:q[aHDdWr>L΅|pBx](}5ݜz:9lkiw zpG8=/?24kӉ5! @w<[ x:3^F=ED ޛ>вmz]pՍϷg׶huƕӅ;I`W3ti?N~G&мCwNr''I Z_] re8}DwB5v/E +O\+Kp &U.' 8M.+""5`I/,OIPa0 B[( ;I$&&X`\;$%TY;q{B""{R{YNfwwN4Dq4TE6n}8v}m@QHQn]곮SBa|3a~Q6a 7cLwo!\\ݸwM>q(^o\ODDDDNpl_|vڵb=Je&RU\DDDD6!2T9_]DDDDv,ǃdY,[^_\SDDDDd6prWrHifq{&-[^CsZhIUn+vQ^Юc}b#e"""""R|'T=BE#T=BE#|=M7Fj{("""""uߟ@FV6MTEDDDD])n˖|MFFֽ"""""Rj~\ rWrHifmqYy9YS(.*ለ9)bXb9rZ\F]DDDD$ǃ|'Ħ$'0DDDDD rrHYfqy'D4aY^h$Z|vڵNj*."""""Ո"NeDDDDDrT'nJD$?{-u0S﹔,P㌜c%Am*gNŢX&sgU/6')hLgH/ i#;j_| Н<>/9ɜp Y0shR94qѴ-:gu + νs.Uq}v4gs =sUyЗǙس^ˊ~#n:CV2^q߻Z OϘGֈ.c E̺hUC"`~_Ddї%lv\)lgeQQ<~T&n}l䧹\7ڎÖy$(|x=~?׏0ys FuRG?:7TV^($V7r92҂!"RmB3""XM8媿7p{y<|R#mq/;w"`I*=dBV q\]I+"[Ddиc gͥם89<\FFmc8]u}:ԃK(ek1CJf 4ląWnˡi򒂋l-ToedY,]csdFMj8oB"dl'pO8a^JΤqF|,ecg|ޛV\U^!b_E8ɀ;- &͛b_-ӭ$7$P6x*W>}DjenY_~)D 1WT""{xg_'s]'?ш n]Iïe+mhPa!^`b^9U"">EDvO.. [u3st#ˡC'yytm-:t)wпMBi~we}EwBә0:l +913 :D`X>{c'>3vrjKqQ,.=zR?|6I|jnHK#)0̶SO" Ha/ɩPvbH0=E(+xӲ""Ii›)UcqmHP4[^IL Ʊ8e%3R),3RIPh= $b-Sy1Ng>ƙ;mSXc%2;@)g*JۥvdT9?9r$ѝ""Rs&J)<-(|jQ~6J(ڴC ""Rn=QB8 n4D(Z]޶o!R\a7\=n0̞sj˵+|~-""-BTFDDDD$)6RUZq\7DD꠸,B|~;W9_]DDcWUٛvAUZQ?pHMp̬UWn]; ./Yjּ%˖,5@ /9M88DU..""""R;jAܞ%wbPDDDDD-ZҮc..""""R;jk[!uOlDL]DDDDD}"""""""""""G!"""""""""""{"""""""""""G!"""""""""""{PiHmEDDDDʦijr޵6mbْúPDDDDD~%*})ԎfEE05HR/Xb9rZ\F]DDDD$ǃ,BlڸVSCYS^'4"""""kg=e"1:5^h$Z|vڵQJg2"""""O]DDDDDE]M%""""EDDDD:q[U""SzfwbHomGDD:v_ȴ^&7CXcUW ry̽$ƄGpR]n%N|y z#.ɜr˿#y%""q)~:9Ky<GF-8Kt2]&F},/>/5wWCEӹwΥt9Ͽ6}< hݡ;'y&}[0-ya4;2t""w)@YF}7xgXPYk:q ܇6iUT+vFjT<lkxGwd==`r.g iߺ'/b+x$Mۼ|s_zw?_NaF+:wF'pDg)?_/}=aa(a.C`M?g.\ n4YWt#qw4c!O9+{z-DDq[0:>|wْOLeLj.Cf0{Z'T!\mGae-+~^K0-. x }!~[*J""{""%sS! t>Ybxs'ry[ƐENM}31k,rZ;6gmHgBKx~ګ4LõҌzP;y vIhޫ Ϛ =3ΚJ┧a#4AboWlrP8JΦoO3<r2³4Ywb0.foI dc3&l(WDŽrcлsZжsW38ӶfB7:%.VZؖի:pq? z^w /s5iQ0ٱ?kq[P5[DdO(۷۱~X#Nm |3ԳrMqf |UrDs𕌽s$)yzxXSڤ ӹ&N7S/- _{u_ŊiVr&3n׍泟g29og$≖.])5݃Ce '""UPn.S^Г:%R*)Q!-zx =`??nnWs-02ťmD[LҀg1isd3v1Tjg38KgL[भK.Yoo. +J4jѺ~=9<.?}1pt[U lh6 ;^̠rtFǩG$"",n:yםɼm: xUvScN׊?N җ繟e?{qX if7x=3F+=J`.$q+!`gΜړ;fyLx*E9G 8-MhDW xi)LhD"nQOXu;/ ضx~jd؟^@%^>/u'S4b0V+$rN^ƴ;0m-\ɱIʠg=[M>"|cx[ #1%v";9ap>wóF1Y8SJQDDZ!t$ 0O:)\c'09x7wk-] k?`j3sIqJ @gkf}GХM(!TP1l-(ؤbȘ"V~>oϸ_oaY$nK[ZD$N(H&h%k7ʹ:;ÙPyE[v(ܸ۵$XKƵlO|9\ nuٻr?[uq׃ƮH*Ⱦ"n:lfsхcL`޲Uc 2֛Y=6:"~r ց a(kemv!TÎ]xtCɅ WRxvNȜK,3[:HSn7ng"ɗDffZe!LqYE0>_W6dh딣K IDAT>>)9#L;)D(qƼ)8}6ilq)7'g*|fwY$g{vx'@@Nǭ\=krǘciP>sz 6P"֍$""7ױB,J6~[z9bp[ 9~7cU,5^t#O6+)%^^I'^{m-vQ1ȕWObݫ-ڼ&ќD&DD.vsb?AuP~-;“ْ wM, !8c~5oMB!|gy!8mv%NoN40XOH[TQ2{_θO/'xVټ@o-׾1n>+zd]}v*9m,;g vfy4r yEt,+BZVpMwԸS).,纸Tz)GUx,</ yvs/ |]Hg0Ft%H{^~e1VGSi֦=kBH+PDDRn:$^̇a/?ce$V8i<ҷ-^g8-w?orHJ)};;&x#z} 9ݺs> k 屧oì:utnEq ⍑k`ˢh#/&ftڤCssÃs%vu""nmۍtdk)b ?>[ԣsat-Uu]1HDdPER\T%K0{AMlR2_}R""R $gP #׵ŔDq-^,v=΁%"?.t{rq]jOۡK)G !"RD(ڴf|bҮtv-JSm 6m]`l&%Ż>hh>! _FDDvR.8ˡG)+T`n8a ;pJ(̯&ͼ\=k2'6PmTGY8b"ˎm;D^6Q+G2ٍ$s:+q(^o\ODDDDNpl_|v8g5з >GK=[CJZXg,2gU}yp̬UWnw^@@BNe ſ?2{!DDDDDDDDDDDdPBDDDDDDDDDDD!DDDDDDDDDDDdPBDDDDDDDDDDD_m:y?/g DH'MhyvkW3{m"IJ%_šu9|C..""""R;jk[\!~^Nzz4 k{8"""""uNJzVXN1Qn=5 . iI= :-99H뫜.""""RvA\ Fz}cj{("""""u#V9_]DDDDv,ǃBDDDDDDDDDDD}qy'JDDDD$)H5S."2q렇iv,/nKoojNy̽Rn_c£pR}a6<wuvxz뵏2z$&Z`/GB̺?k1zrYgʦm^/λ/0;u8YP\&_;Л\ \PvPQt}?+ngH/k]>7x{ruJ^3^tl3q[BDd4@Qqtز?#S;Z:݅6|< 3>F$%)fOH=rM"Ry,|~3uhn:S/` [ VT)$lÀKDJ8!L&-S ߋG7sZ?g7%x K<ϭW|9m+"*n7CyL2)#3'>W`Tu= R4>!ݎK:`|̣,1Ǐ$m ""{CCvBo~mO\P.0"xl˕10e ^|w?Ct<.ܓ$ SS"ڳXq.#ڱO;{dU;C0#TlN;X!ZD$(H]TҚ2u ъŃ4F>MDm\,rZ;6klg)ԛ+GNfP02jY6HMM×Ŋu)`٢$q*m""FeKLUS^'tO!R\mC㳼@di"JΤqFˆfF1˹ ::M GgظN>b,"".nFG &n3jͼA~pt.RHOJ0ɏe\La <*1'k˟n HϙgpdF ""vC ;yۦ% 0KDnRn2u|OjDrbAl{xcϞs0VC(|b~|~^}aʈ5UenbƁӮbħ1CRw *gp2hY搋LSm1 G+DHofq̹=> u G;Ny,ǩG]U""{Il҃Acz3dL!+?oϸշ0e&[z5k-6C~n>waBC)k#ɷart,cSj3N`r1=9DDdW(H]RfB`\/sWٔOpF.!7~^ͽs̙<3;)s^-ޜwO3;g˪lX2Zqޟ$[Xz:-ʭkojz `,pe;6tl$BDxv%ѹ]S9 Xҥ{~~/ndc-vRXB!Eϙ07 +ф${b)sodbJ [p`/wy00em/$1BD$h,"IqgZWRS6U}LmP:KM}0~`' {mNmOnJs/J°v wi&E5)'sz#nWeY Igڗ=x;{fp Ҍx3mkf޻IRLDWh %;XrmE<33l>#FMpکnBD$bEnBG đF+x㙟yI lS7tt<2%1jLt-n'G6bjcB0^ƪX|ctҮS7]ן0""IH}'o.Ns.79TL* j~ /^dg0z0f;sU]4&?KgwO{|:<3֬3]I$[̼kW0M]M}3eq|81yd$<_!.LqQ'ql0\ݙ<o?4&4xrcxIt+={,H]t8׮WG1we>_ټ:kVmGծlN8vlXfP Xw,I  hh 2m8l~<^6q b0=˖qP(.S/X"61ҫ,L3D VJDDjM?U+nRZ,TCayȘ2Et Æ bހ7-6w7OY!61F Ppc`wk'XpEs{x箛i\nW|r(8l N]%=yŧ lQ18v ,̠K \Um7hk؂< W+@Av>e?+4L%[$s7oO֋Δ#>%"{p;j@m;X<<\Xbz:V"[ Qȱ ̼a0 b|`^x.ٸ~[*e0Bck`R>X9ĉ8 ;;`۔}( ny˲cGsg) AhH<g+Wrs u]Oݲ ïILg> 5-c+kɶήk^ 0(y13XkL??//޶#v t:Їō>/ n2_=vC'ʴ_ߋj+V(c#r6-;va;vTL/""P&!,D^qE197ӻ =}gnwb n=!o~ك;E=EyƻG_Τ/'m≥@nll6\ܱ`X8p 﫹<Vc8dǴIL߂ݬ_:ް 3uŁfpXnY37y63j ލmBټ(]qj>z.=0\ߍtj"08G DDE|\Y-Pyc7>*L?vKUL/""F&!t<zLj #Eٰ+@˟Wp:+1E һڰ>/obo0eM 0-vK=e˳?z<˄v-,k,^#{] Z&Tf>^\ՙ{n9 p\t'K.{_o 3l@b8,r/sM+Gޘvȟ%`XStp_ߧ#Ѧѫ7_e֌\hяYm&f8 ͆1uG\[ |bZmYijep>$CeZ/ODDh("ma>6.xie~ %lG܍kj3&~Ɯ箷:y5g=7m9f}\vpBY?_AFs i1hz8Gk,^ITP&\1-\9.{.d k.eεnEDFElBYi_yVP8v~?6YiR}h=w>3Kvub4|;Ǿn^oلP^#e[-v޺N>xu qdZ h/ei9Z_.U_ad=s{ncLI-AA|ZUXnx=zgbmgmwc`&,хxxٛ IDATn`҇SxDz~Y' /:(nߓ# R:Wğ]fE$311}7o'V[;eR,˱pp8bx{mx-ڢ:-1A~t&s̘9'&pꭃ醙\NgӋH $"RX>uK ;懯OA8cO>ߞ%pU(HϰF2jpβF # i9;20јV.@![>xLs3 Z2{=xfuwI% ioextBru-VpL"m+XFO_}{y /TVxn`ELf]p`68 YvͼrZ2P2n""~T yєFNV:KZ{s- sp\喏9+߆OX5&L;{bdwo7w M5/?w.1 ;S:YXV^DDj^&!tDz4)+fiF(l#y?.: S ~h:v=Llȱ )doIĪ^W9.&Nr2 YA%uX tLFG@8XU}&sdI^q?CMmDtodPuY3Z3|{%52>3w߀G]Qa9-d搆n[A8 bd|=P5G!b9"{aqp\E`1``f{T;&<Pҽ,Y$l g+Kav(0d!7Sö&\U@"0($O +g;|QЯ/6&аLo"u C>yx ,Rz[dYem81< ,BUrJTlKط>yVL 4w;rCKe޲BSrMyk|[#7gƭ{ VϖUzتXVex|9;[\rsJK^ABf0i0Bv?NTTTTo9ʱ.Abl 6)FL4UmNlsvcae$7?\_YT\'8:P^EEE%J;!DD?fpЇhnc"zB_ȢmItnהFqNֳtߋfUvĉ:KM}0~`' $}6I!ܮ66c #b]Iwn26ؤh=dnw"S-f1ݼ;ϽʮF*[.fYX Igڗ=x{Ἃ֥f,e޻IR0n/k sL ?ߔٷe4j(׷r}cUh("1yޞ85p%5IRַ ͛WZ2NcL4=D^M撇3I[|tg|S-^1oq7/'jX[>eO!ζpu>Zfw1~vҡw: ,* 0|<""R"6 ÁW` ĥO剅=4~o<?3iޝa/ 1]h"^xEvi١lN 3F䇙޻r=t^}5fLٍYgIL?F̼kWNMǃ41xkU+XnNnc n'>`xvdҌF-!?tmg3yp?w4&4xrϏc$Uq$<ԕ:>T[njA'-)ͳY9&{e\OeC j{n$gxNۖ3bۇtGf }iсG{Us;iBSqutʭeY>`WL/""5WϪ__^~ܕ|ugjY2]-xllbj+""r M3\w6EwƬ""r~/IɩNW."{^D8\ "2 Ѳu;6_iY\.쎈즈T U.¡ͺp(W%=K^)tGG!?}m;mڴs_BWBqH8ҘEls^ub#gEDDDD:>) !"""""""""""5BIJBHPBDDDDDDDDDDDj;p(l!;k?`"""""Ro8Q$&ТuqشzbHۮl^."2 6L@a#""""R5hŎm[h֮#"""""uTD";k?ؘH&ay'D0nw`YVmwEDDDD޲;ay'}y' BDDDDDDDDDDN;!,.f?j/o 6LM=;'@EEEE p &)'f2 ͍Q29[oK}Nolapحc=L 02_ǡwm E'Nx6D{Yq%axjZ>XVesm:qtE_{ [x =")"""""""q"TR"R8pآrnφp37sJbY"u1wMN7^=BwBL~Ԫzo+7ͬl!YFxj]H𛽜9i}92Ê'@@(:>MB4?6⒒IMI0Rh~8>[4 CXg*6]Cwa|rk_2a)_ɤg@8w#o}_^ pcNjsLv5g͝6|ǜ f}\պe)ЁxҠss i1hz8Gk,^ITP&Lǀ.Yx.d k/ed7zM^`ⶲ5n7eķbف WϞm~MYheY0 3!L u/!ލ-J}L̰QwBoUTTTw0ÄC!B~?6DVrlvCMy` oBW.W۟~+ '>;;f?63xqm͉pⰕap[I|?3O2y <07m]o{䛴KGzb&O:?z-#[>e&OcG G1jm-{Q΢w#eؠN:?bX%}CA~~R&2ٶm[q}=FTTTTj"NKxD^KNr+!l<'oϒKYgذAєFNVV:KeQ^{snc6|mq~T}Ϸf?L;{bdwm\;r Rm&З?/s3\0S2,,+L˔!(PlYw҆Ox1Y ^[m)p5G )( ‡Yxe=pD='@=Ŵ^;yeL>S ͊U~⩃0釦3m``f,PhG+_+#2d|;f[Xx!7Sl>[*yaшx@~7!K\@snb=m;{e<5d[~V|zx m:2ӾA21LZtJ4Zv:8硅ҰqLV@""""""""rMBN_,,l$4La47k+v2b|< )=F3wbvoTZ~I)8wmgפdi`ۅ ?P|()m ՉML!&n$`p ))UnUYV{$A0M!?~`?csqT{?dKl:uYl3']NAy%776]h6a9Czo;3ʚ6bh4 """"""""G,rBHeal{~<'K:_oHI#OϤqzw^6bdm/m*9s gzF t|*]tW ]X4/<";Ѓg6KV<~CwB1<$ESDDDDDDD$'xVUr578<;W[gꕴۢM+~A-؄x| mN8vlXfPĴkɦ0`':ѡ< Ch\1D9lXf@a` g,8lfpA6Gl!ױmUp Gq_ʳc#`":ƅa0p%Ui('HuOG󋈈HsNUj5WѭWcqSwBH}0 M?9 zU7czdŸwVo涂Tl0ru^ C˰* {)9CcU۪t9drV- V񽈈MB(!""""""""""REdp#{"""""B8tv7DDDDDv(w"""""Rc~/Iɩ "V۱iZLrawDd7EDDDD~¡~_."~n~"""""Riӎ{v7DDDDD$@GDDDDDDDDDDwBHݧ$%!DDDDDDDDDDDF( !"""""""""""5BIJBHpւܿ-"""""""""""A$!_'!p)"""""""""""@$%!DDDDDDDDDDDF( !"""""""""""5BIJBHPBDDDDDDDDDDDj"""""""""""R#$%!DDDDDDDDDDDF( !"""""""""""5BIJBHPBDDDDDDDDDDDj"""""""""""R#$%!DDDDDDDDDDDF( !"""""""""""5BIJBHPBDDDDDDDDDDDj"""""""""""R#$%!DDDDDDDDDDDF( !"""""""""""5BIJBHPBDDDDDDDDDDDj"""""""""""R#c!l!;k?`x,N93Zn{Tiߎ+Vi&|>_ LLLL ۷gȐ!G5ƩO4F.8@TS q0ɅU\v 8䌛@bb2)M7k'y٤gt9Rv$$$pYgpDʼ{x<Ǝ{D5N6hJ@TS 4N.8qfJ2vz;-Fl!C\B.F!2!iJm:qb 48N=)Mtta8ڤq*NcTS 4N.8HJB㘲ޡ&!RX7۶fƩԦ#6msXuz&Rv~R4N%iJ]q*uƩR8=j`Y$ƩԦ#>STjƩ&StRhJ]q*uƩG:N12yRhs5Щ] 4N.RhJ]q*NcTS 4N.8F$"""""""""""W?IטKq*"""""""""rtnWS tRhJ@TS 4N>DDDDDDDDDDDFqL"ƩȱWIە@Tݢ)uiEVsJĈ?̥N#[٪.{[hJ@TS 4N>wB"Jy쳥ҡ[_F\pscT7yϞ}SY~re73ow (w m:iaԩmIT]˲U߱aErtBƲvso Q7Ү?lxJzu\"˞aW-p=[2͜xqVZGe><]6!zeDZuh;Y};QGPG$"xٺ)#7}6m퇟C03yxkY2º IDATJ"?d٧߲.3grȓ[qbez,^)XiN:_%$>wO)C9_k4H#t .fOtdy{ .Cn0;"]%;;Eo-Ikٲ:vuVw(K݁Ő[pcx@>{6bܛX LqBenL;U-x KOi  ӎtG~ՠ\7^n=#n>X 9M ftیwVc4ږB8=q.Nժª1b[XG; wΈTd:s h[NlCHbgn>IX~ VB"@ױS\" ONIJ@HfpL[ObK㘎0{֮bcuzWcBwa}Wg1 Wc@ ?{ 3(/&0𯝸G۲?zZ.{gZ?v ҡ}:˖[w駑ذ>8Lj #f:##'>OrEۭ4y cZim;f *S3lRtga g_~>^|]vzV"R"9.'Nƕty786 [lJ^ {u:Ihp-/ݷ!m_[d}I̧~gqiOo|ngvOlO9 gZ^l'sկzh.}H_!kAwZĕm]ELj<5К/gS\g!\8q|̯?ݕkْEr&)cEoԳ{H%f0TRStD&`g՗3EɩjDʳNjm}=ǹ(,n~אjb&>of{0ID@d:wB6R;<$& Nhl%Vޘ ? YR9f|'.rƛD;mxw㖆!weXN$zr~yJdz^}eiYa1R2ӼC&[_UEij/mK=f`&,U9x.q5stYܣRߞhҟ cwWpSRVQR b%ugCqy)6[No;X;bI nヹ/.1k$ZV`'+63FwfKQp n{q'ʇ7sv=@*moZ+ڵ'B6&ia*.cת2d];|\=Վcx\θJFM<مc߿Ǒv9J^ ])1ymXs4FRf-fm:{霜@?xk &),uYQ9s06IOi g;SN3+MD zRc>ӊJψUV8d Ք(_^%3 `p,")(m ‡Yxem[aH;V&yޕGбdJ8H=Om1zAG,lj+|NNkF"N LyVI\~fDMNϧ35˳zk:h6swb7[9Hkͣ银vbI-FO?t mfͺD^׼ Ϯ K84U3|5Վc+3oHJjMAv}Sn mTьpz| =^gEBs{ǚym7falS…͔Εck g3``K︉tN/H1CVOt~\´('ck5W);N+U8mFSwkڛ፫ k:5&9\䚳?ŏ''A'so?|݄&$͡!761:1! *퓋?Ҥi<[fٺݜ2M HDpbp:O`ĨoM8cf>}i=fQl g#+W7ֿPᬜw܀yoSa`Go~Ɖնݺ'6Dk}4[䔸y6y;&W&ouoGuq u Yf]ʼn] יcⲬFa_.b&)=ʼnWcLL|}qxWy'YɦG~ 9.Þ~*v/5Th Ga6J anW`3ojYHpؽtf㙲u=v?owq-}1qoHxs><MVaʄ

}9r4FtLWH 8"goDԺJIӶq v 3! VJ39}H!$i~l_&Oy煷۵/?m4'I8~{|l1o1Ю4/b듪fɓ;'|OҭW[HHLqcV$H( wI8f`i#ɟe rI%q+" cYZsE+SW_}ŬYjmhH:4|uSS;N܇rPDDDDDDDv4-;>f):)EDDDDDDDjIRCqm֟dSNxLJ;F>X! ҷO@8 NDDDDDDDv4-;>;y JAq;n23ؾ#Yq w`ׯqOӥK<3iiÇ#3#1ӌ}v^ܶt}?"crprJ[QRRC(ˁN9""""""""RO6ް[vme.U5=\ ȢˊbZ&eb&PZqޭG}`} ec&?hRXXĺuez8EsxfU-ao]ĝ]G}584."""""""5jcZcrСCGoYʻoEKC.ߜ:iӷfƥXh"FˬFQj ma6mMoXd?VARV}_QyV 6lruV>ڑ¶mHIaү1J|y Igsεgd5sR,g}7k׮9V1W^ϯ{׾Ѱ8>Uq{Ln8'6ffi>ZSc橈_C/-ksr5Wq&sW]΃E==qIyXzꨃTMf'g9?rs8g|??rs>.2Ͻ)!G,͚Ck^*|mǿ}>:tFuAqUWajXlZolM([sޱ7^|?[`&+=syINbn,ߏo>cE#cOY/'p#Lii8v#sR^[I?P- :8.v A'/7nW>cҰM .>0zgC0Γ&c: m]NěeFŻ0x%9^[[|sZanv1˞[ԗ9LgH ؼt+:OOG=6t@.h+O<|SC+"""""""rhHSUy$N820(Ͻwyw^uϲ- {yg0 {=z4k/,O?03lЋMiV 5wX [&po=7>GKy}2JhQENm;tngٚ|2R=fOu.>1p]WKC+Һќv|ڤgؓWZk8VrG3x3vV<8]=?LFN9y;б&ם5vy/F'Ǡvt9 ;5-%ߩŊNJߎ[N= ΗA@J"(6VR&]( F:4|hΛ>^1=[݇Snљ"|}rcrȎiƯew{߳=Z[ظkƏ8V;||sgSQ55" N/s S>BjY?~8gϰ9<G|&L꨿96p)A _f[KnBx?)زu󿟿^&3XXLsJrR"zר*0pp$c4v(^K$tc1Fk BS5XFM8 ^1s9<ʻx},cr/watԑߝs)i|\Hǭ[tɂ>#]1HN&d=[ zW[)޾I1Øv$:vY\B)+ۑѨlqOmc[ S-!lJvl?\0=\Qcň> X`>ξgIigw|X;œ\ 6q}^JIXU=[ UmJ0ԻO,Kā4{G =wȡZ(i[o@AVR0`b>o|g2EWHͥczi k?^ 73'/vSXZ)o/~Aas;/,;IA0b:kYP6D3"Iƅ7v:odN5o?#Ybn7}sѩ(mى?WM)3Af3찣ƴ̽Ȼj=-7aD"Q&˗ߟJNN;~1v,G<~}Ggt|k>%c׼2x`Ҳ*> YW{+9$WaƵl:t@-[Iؖ4#Xm~NjN_qn$m]Qt(:V`'fYs朻ər/9^\ٷ楜S7qwhKa~YgVLnd~8SO~is4W_ʿn,h.\fm ;CщiOcps 20!3 h3d#:0vÍX\_.YRgswN:tLpşq}`U˪fRZo'$v>̾{25"o|L sfmaa0*6kTwFbϯ}Wid̅7M̳n>I{w"7ҥpn\.ǎA~~>Çsݷm̘3dӎͤfV0S8'~&gM X=h&g^ΣO$qbw6-䉷9>$_VyK#V.D#GwO[Kޥ$Jر}9Ix*}owϷnFvWyc)~* h&&'uB7M0$.q^xwwmOBw~2ɢoZxXμyx`'5i """"""""4l˛7pPb7Y"/"h!<>|D<..1#!¡(;_ۅcD6%aILM#,8hb}$lbJc')D7VҐ]{ Ý@bǍmsKRF F@U?O2)"EE $zaJ_ptߘ7öJ E,Z9cg]1xtʕ\3z̗]V`e./U~"DMK )ML$1nп}MRQr%O1K(*kYVz_Z*H%?d/bUlOI3@z1fBB+TDQSkABfzzU<<M';8 XǨgU9Բ󢄊*-I PbUbԄ_SmdTGZĮ;E %(MqMKI%?'YYٕ6~.ϭ\QQ!III e'L"`nii:rߚx<ټe ׋vanﱖΉu]$\%k/~$Dp2u> NDDDDDDD5-;>c_|~SkpHO'j{%WB?ُ?K)#v8|D:Bx).lP @4^}刈HT?iZw|4 {wq_h1I3c)ɏqOm Q\RJ9("""""""R;Oks,c'堈HT?iZw|(SlǤS/rPDDDDDDDv4-;>fɵ' """"""""""".Bx<^,ˌrL[g;`7"""""""rPq^k|4e01ef& O0r deraW9p~8T5>+!:vF PBiI U(wi(-&ҡs:+맡q'FP\c~c}7KXx%.]wzWOC*"""""""OUGSz(-YTK0xبFOK>YH+)#uDDDDDDDDDDDE -BH\"%4\DDDDDDDDDDDd?F"xFk!2(-*jWRRHzfVOmrڳm&wn'"""""""""""-U4!6vlBvOϾv!+[6o`1Ƙ41KzF4^IviH""""""""""""r`"D?ed<'"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""r@z.,D-УIENDB`AntiMicroX-antimicrox-2888bf6/other/appdata/screenshots/calibration.png000066400000000000000000001355411377703515000263640ustar00rootroot00000000000000PNG  IHDRifsBIT|dtEXtSoftwaregnome-screenshot> IDATxyx\e93dkfot/KKP@Y(# ࣠* *࣢ ( ȎVZNfscfiڦm3|^ו˙3g$sd> """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""+O  BЙP0?ò.LDDDDDDDd3DX,X,vO"X'PVVv}qq)@ '3ƐNX7ێH3O{VTT,LRV*uݝ\DDDDDDDDvȲ,,"̦My0deee_)--=lQ,4Ƙ].^DDDDDDDDv8$Iu]ײX,H?' .:u {]$""""""""'NSTTTJis`2T#"""""""D"aB3GŸP(t4/ocm఑?ǶiƘ+MDDDDDDDDFeYA7}$(,u]M˲bDDDDDDDD5~vf}jċoegZ(#~sJ#KRlɱy.=!ӻ1gOF:>WE`LP#"""""""2.͑Sz Y.?Q2""""""""22*8Ԓ('F?"""2.@q^;ԋsVs9{Jv!}rw٦ڃu??S)xKS֣O?@yQC)"""ϋ/ݟpƔ?MW3ڷ3} 'GG&aۿ{1n608@$sDc1bX}jNS~',sᜣm """mҥnPbSqѭX.[g?ʪ-Yr E#(%ۆ4?ȅW{M%i_ C;.P{^|.j#{;\G?/=# m|-8vp㟹 ~T\rtDDDd m7m-ۆSsG-QJpi,_6gx%k~Oj缯^#=E~T"x?-_>i[$>s-,+ n| ^R;,o}s)e?ar7pZ~ܻ\p@hk(G//"""c w5GDDD`YX0?o~Ϥsxg6,.O|/9Rl\9& `HMξ4%9}aO)u\15<' Vp4~ ID͹Ary;õ\{}wukF_8y^?]<G|Ҽxm.W8K9m  8ywc3i_{ x?"""Xx#mCovW9Og}l8?m5+嶱bE+f)ZзFPc4`v$He3 Q֭i5t٦t4 $kWo}JMv]0\ű~x#,fjœ:QcS` ?gPcڔ/P#"""H7p;<.9Un|9EQW+f/ e5[k{ьm[ǭbf(rޢm$cG3Is]z:;ISӰ^ -!Ysݾƥ{SIf>9?Y9=JvPװN6;cp焁K[6zl]t)<|G.?"""[—XUs<'<*,ᠣ1 1(4y8/Yë;͔{ʊ9O?? o;`cc i/?/;#/q7~ H>'t$M'CVyB okv{y;˱`nj_"""""""" LᏈGDDDDDDDdS#"""""""2)L`H$Ʋ#JKKDz #OӾDDDDDDDD&0?"""""""" LᏈGDDDDDDDdS#"""""""2)L` DDDDDDDD&0hߦx+9 n omlCm e=gV2 ܾێx;ma,줍<|$[P\\̴iӼ.EDDDDDd܌z/Vit0Mڟ 88t s{7c()-ٽ2] _ʇ?Ǘen~i&T /c~"""""2z#sIӤR)Ry)4/6*1˵'dhV>?2< RP2sFlvl|/3= /-UN=L&hrې:3mHRBA}IyB]!:nJ~>""""""2z-3i֙u%ڰN0(8R> u+/壨"ҁ4ђV=Æt SbSh5F"""""" D"jz  'ץJSvM#O)n+DaȔiz\ /v.EJ"SDDDDDDvŸ,EXSXu s)MSTS"9  q|́f},-j?:HّلB.""""""9IObmp-yI1f) `j9ffTJew̴Wb` 0K 77ogVtBJ'ttvZ{ 3`dB -(1ݸ3]8h`Yhc 2+9"Ojܢ' qu%.T jdF C,:VuPVV6i49ݿ =a&|LC+""""""Lq<9FǹҡF?9"J7̃\2u 悹[㝧ޡBöq\DDDDDDr4%ؐڐ }7AQẢH$BThlo\fS!Zh&83w_Ϊn +\,* ~,2#}sOsyTjԂ|fyd& 7b xl07 *DdkܥgcXr5,#ui s`.3tK|z_=UEDDDDDd2ȟ1ÿM0|O4৏sCcqt*tu3 +#74fͰuF2D_I}|Cu:J d՟֒ӒK4g^E羝8:P9}}f1v%냚m{q~: XMfe0nHൟFe{%  w^A~3|̩-#dt~snߺMҀ fj{aRq FY*8p0R2u4LCgt:Mwg79T ,}gV|3‚m6$"""""jQq}mP63+jPEIeS:kbo FQs3wcY9n ״P'47Ec|`2KïQ9ڐ> wMMiic\E,U~y:1BN+_yv\thY\8y3)Hp_='~F[>GOuA  ~[y?#7so@O(Yf-#rpsڐ>%` }ͦobj8\rwOd3Ʉ+^`#OvoﱯEDDDDDʷVs؁|3/.0~-zfRĖ *Ku7)nV? mt*M2I9J^ݷ14πl2}}{TMn?٠hk%T!/L?ɜh΍^bښ&""""t%]kyGfٺt$\kyk@3y_JNds-췿_z/?W hӯs~5ί\FJ}u:ޮ{!O!< ~x$b1 p$s(6zMx5òe.1O棧_ȭmϟHv[6x'-Í R, :˭ M?~ 8|.S^w^<0d{ȹ̡2&h4J8 ͡V?`247ozTY3o^P0@c[]ʨ*.fU\S+xko>OKޘ" ,O.!fydz<|6]YճdR wqh@60r lN2DgEy'/ZH?߻EDDDDd,8:Ξ+ԙ$XkcALiX{[t²-44=r:'\ Z~*]S2~WdHk.Xޓ.ekdz$ S\{3p_;d@N@fi9yQZ2\ץɬ6޷mQfI7ۧSW]}"""""2b&z޳?|(-v4wpO1_Ek/\gկm\cS0-|b=Ze6>t+M_<.񽊵9n6WIڗPn~x-r-;aDpuuuHݸq#ӦM%ߎMCVjj R6{OgQ"+ip^|yKe046|dϢbxRX c&5JDDDDD&uh?RXH?K!5%E4I , ~ * h>b97oxU?;J&0Kt>8wۦeSeLXD^#7^?`[^ǣDDDDDDdW)ŠM O7Js/uihxinĹ:GF 5櫆UٔɫDDDDDDd(`0o#Z,-te^+1mhy]n%|H7sa5aϪ*ׄ'HJWU> ^k͛ϛr2`&Cx0,"[_NIS?lфIlMc,^}gl^ݮ9VYJDDDDDDFh҇?BXaH󪪱e}ҢMJWWfQLo2'ڏix[D?8 )!g3.MoR&p$sm6zޞxl27tveDDDDDh4NmPRR2H z֐৔NH{3ݡbP1㼮d}7&^C]l),,Rd0mmmL:u\;)ßU*OLbLsthI(klĽb'W{hl25vOv4d IDAT?DDDDD&. tttx]lC(2#s$:=~ʁ\ǠKCGYV̥Mf\y&>CIݬN*I+߸#3n{s{`0H4jXFS}}}v$nܸiӦ^Uc$&(9}TEL৏}M݃uVW8c /ץP˦(Psd֢Z}ׁp81&kQ"""""*S[nwQGOz\ 4wH]]nqݺu;<ФqV܇̊E`ΕM&yƉHm^ʰ]NNyUHȟ1.o|y@2AOGtJrV27 '{]d>[M+UE"""""}P:ymSI =,*K4wj `.SE!k Vsk<,JDDDDD[5ގMĠyUQu%9uS+6$˔m6g%Y_UE"""""}P.iJ6{x/fɀ@g%*heF'qf51~񍞕$""""2sίW>TePV9|rñzDӾFI,cCiJ`g%厓!!L#K. K$&4Nt7AGa⓷{٦3̚իY6(8>w=\L s miΓds?#Nӽ$|_Ҁe7|Bok:@AW 9֯p|jocyOg@?ΗW4]x:ϯ ~20zN&[E~" V<#̸_VI.wWrG2gmO0Ѵݴ޿@MxwV-M*IS{b5b![#⬷OEDDDDd$YjzJ>  vgW^_I ~z\Ջy~~gm+[9Ӌ:y_?my73'g;˜cλxvxM N/5͘4xYI9͹ҡ3z]JVkni\gTl5'jB LDDDDdBN<ۋ7rML<(. .\?¯~ oYK{%ѹ^_N[r\\#h2SX ~jKy[{ԟal= ?),+ӫ]wdc#?o'\0+G w L&$kakAוYd>}9<+GDDDDd":vGwz_\NF_l+ɋw9\at,_/vsl=]wd ~ʍH>Tyd{n1;.#k{8ϵYd2U00,xD=W"5cf8ʩ..%dU\x퇙s=˝wŝw޵S$;9@V}Dl2RC[Q5RN$!U$|V_"oGh~@L acY,[$uK8v^xcmSyks O;/=߾Jהy̳_=k~΍wVsgq[5/wl rrO$yF3Mct S:ܢJNcO#5|f IR$""""2Qltk=e9棟/cg|u!38Yy_O߁ǥi6zYHҴ/*gŸuu3(Iù¡16b1u%X!P|ȰY9"""""LӾ}rr8W4xXdr$| וxjs t?YU5""""""JӾ#SK6X ""cν̥2#w\a6`sGqGv~Ƿ^7ѷpuuu72mڴݫO8&0ľ'G|Qr=S+p^|q=f^oIkxJ/]~̠:PۇcF%""""-AKH$iJJvdKsssuv_֎q]= 894&ԯN̾Fx3=7'֧{VH.2e XX,^#p]xlZ?9?7u7^*#c2ʺ𧧧^Glϰiu%cum+el 7$"uϚqQ<*F^i1ռSYјBd}#\Zk=+GDDDDD$e7H,BbfVZ6A,M$1ը)_٤+U "U՘L58W84Ne߻q绰Jd Fc <+GDDDDD$dMMDWtkO o1 \ݳN=Wِ DDDDDDFSք?Vc0M-^1$DNJ59ưpWՈ䔬8ݷ&/\{&VF̕Z+k 7Ċb$I/+ Y[FE8z]ɨi؊TOcp V{VH̋cSKm/YU2bg@WkWN҂LONV3kE^Md%ŸHIPw񋋋_3}fCϫkm| >kȋMmHnh6Q[Q;U Ǔċ[G9AfT`OǷ~1H4w5{]Ni4\{&,_԰f/ I-pO-ʢE,`וbXXW[[M&wD"`וvuu]mSxn!Vbczt_;,GUDDDDD$Ky#=y5w}ੱTvsCc$7V] q>Q?YIîq kW^ - KNQ#"""""2OOKo mg|>UNcZ4ڗhdAhV+;Td/4~i8tuY^W"Dm6TK>=ҤSⁱVDDDDD$gȟXql] *//g쑿7cYؗذ~+={47^W![<S}Xe߭d{ޔ8f ƈLv1 ӣ3B9sx>OuF2B"CKgv7cjԌB˻{* ||}N _? U [8?4g5FDDDDDDyW2?ٽQ?ñmZj+k\I0q;{H_ 0 ]M]L}ka@וLR/M>Ԕ@7D*?pH'ɋqEDDDDD&qՔ*--eثt/6lϳ1=\={#|꟯g~KU=PhtCdM7~5x:F^ PU1~͕C9""""""ո5| $3kG U 4T5T 7488:pj@\Iii֌9 ~_V>jkZRey3ʗHH3qJ(l2.#C:?~78iUU,yy\R]nc}ł^+MΕhф{e"+dQzm)Yxۛ}ϏcS+اa;)ƺ΂6+nCkkg8߳r;ćղḑ${XX -."""""ޘ?$dw贌\STTļy,{jm|'_^W:¢ݓ7v5^^?#ֵvM%iþzﶁJhw]"4O$gztWN}Y;I'qv\.g5RNRSI$JU⋗LVOWQ[D*'@`p#M7Ec&3+vTOjf@nLkL" /Q5""""""'Ww_҇ξ>!r(t߉u{ Ӽ.  $ ȯXlCJi'2@HP?#qs+ Sguk(,l9mfظhV]`QuUNR>@kd4Š)xnOڑŭti}Mw5d uur/qYL:q%Ns oya X0ycdo2 %e_ ]?C=|*VM^@5"7#"""""2 i ,S/lۦ::VwxD^*IL˩m9?r2_a.99n6Nz~_KyYlzysnoa}" Ql2Sy<% @@2w1 Nȕ%GSYYeeeb1HEmm^l[b깷wc;wEa&kx[Xg6oM/?M毆JLPRᏈLZخ=|B!ff3ji&EnfJq^W7VϢ[}iI\!S·uDKlGDDDDD&13F캼<ꩯVmwwal߽vO]-ɖ+o bB @c _MƘЌp7LqM-VԮz63?;uif|<۹ݝ݅yߧMds߻\߻7~<0VB \uH4uOISBZDDDDDg1}SMM NIBͥ55&W _<0aT`S6 #`Pub™ϤQ/,HQd}Y\۟VSHXSbm.x[B IDATE^_s.)k2 =^C:n NxU31͢Ȭ(k8#HDDDDD*Kqʟ;}iWq|>7g~|qqL3%6dN/Γ9kKDyM8UK{ 4xvVR돉He)oFVSl t˩JF];G9㱏Gk!;'iy9Oz\?rʳ9dT'xDDDDDD;E)l{10mMa-he-8{$J`ba]hc'5~Ӳx_W_* fI?Ulpg-;DS(b2mÙGDDDDD*Q+[/Xżyl]B,8m ώV'nw?$f >?Ip3YXNuuuA03?5˗Ք/qڼX^Ae3&8jn!K&.%]}lfIէ8$>l5{ A#"""""H#*H$ᤖx͙V|gf#~7X3?㧳DI:w~wXX,?sƢ3XXAMMMa9A?"""""Ry ^>w6フF;0H4%8Y{)яDX7vGTԥ4~fIc1\9+a~|~#ng$/fNȟV[[˩rjݩ4\3a X?cVus>Ox3o,5u߅S ֻ-y&ͷ7szLֻrHffǜ~H)?3/4B!y ݏvN&>mu46Y.­to| A꽎&Gaf=3JDDDDDd+|3cJhOiil!|'->u-c ¤#4& zIiO/5KDDDDD*MQv[#ʑw>r~uWCg*~ʐ(,?"""""RY[`8.",ohM\=^(q#o:1!cI#DDDDDF%T,cQJ 6]Ʌ^GYGDDDDD*MQG)Oy{1JΟw;rTH%+jŞhuqxCdEedOdhqy=xǓ4:#du^Gc|JSyYyhܤRp1JV6#j:#,lT0?c~N&)n?eׄ.BUgXas2ǒT?nޞS~d=={-|4Sͪ -İg5ʟY? g[д/,Eʎ?YO+{d;Wzf1V:'=9iE}H)eP M*;tgO9htr4KDDDDD*Yw24%*&cȱҴ/`_gI' 4֥ } )i\{먙swM8yk+ﺐ1h|+Km ~n9~= !J妣:)n_~}/-\ZRjuYgT?nNum5#USHuA>:xtϝ}_B!ͧ=370h(### VxIDDDDDd|Lª?~Df A1JV=^ǐcI7mg PESTSn^?A+@1M[YK"""""Ra _;O&YSE }د D=A+P'7msE_'{wM*?vvu%K/` kWu!.5~bi7cr4KDDDDD*Xw}|r==?vc7ϭy6ɤ((叙3/4 c/w޿ۋ`o[c_t?Uo.~ض0dp}c610f3?DDDDDD溢L2߬gBBS&aݬݸ%m>~مڃ?ۗճ|&x5=߹]6c–q4ҭL 5KDDDDD*OQ~nekԹ;.66ȏM,{_x_񃖘;NQ,k޽ *d4GDDDDD*(O ~۞i,tw`ކsuR>ux] Y1|5?xy!878phR___ܠrXA%"""""H#昡!6wnfutE'_hOʵO,g:) 9=l&~❯{ͻPN֏vDjc gIҁ+a{ _1X+ ; >T又T?OPO8޾t w,qÆ{Yٺ!+sZ/ᴵ66;A477w d6'TH)ʕ/뛶 09vlڗֲ=d`?)4pv=,8=# ]7V8lH]A-<`8FHE*Ε;}O&xKwO7ֱſ7rqnvrz땼jΪdOk30z߱ޞ1G?Y '"""""RR2 J 091FݏXu?x?Ogq^8'S?~yﳱj';Ask38MٟAET?KXY0{"ې  ױiCyCl̞Bvz阴S0}93Áau{鹶h(Jkjӕ gSZk*He*3/4yU{9vԃ) L'v.ପ:Q?ܚGqzZJK.N#lƋ_deagTE+fu奝/);pɎ]qEk":]?tvw.?i3~n{9L&NV29d:?mbyblLLLΚkڝ$MboNV]k~N~<ې; \]\up{п:YI>sh/LE $򧯯wƑ~w :Y ^q9'|#kƪ\ҿ ^~בNg]6j뫼:{:q]mi?sZ0[DDDDD*WQA&LTOE3LŬL&ꦧ&l8Td.:>u.,u)elYGg=ׯϚwNڡܺz < d-_DT?2_9IL|s[{߅[iNEs.V(J"꫱`QUr5}1x VN7f4dE-?mZi(pPD*{؟^*_~q}m?w"<<󹇋_bKuG}wN؟8mW6 qZ[,ȏ/sa3st9n[)RTQO7b<3i]:U12I$^K.dr!ϝ7茐XaV:.μaoF?NUi  L2|}ie-`ņN\I6ՒJFNW4gM  EDDDDD;`ldfo^/^*m-mv,IhC:T+ӍlO5O.$>d,OD|=dBء{$|t A3QX pqW  MPur|Ӕ/tE/AF;MԯA&(fS>FE/||j6\ץgh$ WcG7`b폴B>W􏄢KFn'%)  L['MMff^ܳxW$_ w0on.oꦺD,A,:qKF6ӗTϿr!8>d8[ p s3붯d7d=!7D(tcu kg/ 30x [[Xc=}^';f..z?7+Ƨ.]%imt/a;7 9W0tɺܢ5iT&`ɚukعw'tȏ-pz(C#"""""Rfe57d,:22Bh'}7p>S;xdo[A0ciacq6?a^k{Eb$ NwHggH%?V—R1o|w.^"[[fwŹNOטk^r ?[-c9 4̶mk[޽^';Ǘae]DDDDDd\ϟ~ f}(ۺ=d`esou7FSWWOW~&4޴&R)_""""""9WMKV%qr]nֵc 5rq) u: tinhυr*8q 啽c#CCCƚv{gH' `fN7B޵5kװI&ΆXWYV{L-u-7)( K\NF޼HWO;[lMĦ>Š-EDDDDD&Z P__==o_fg3_o9৒y pE~h$ {d#oX+ |X "#*DDDDDDfd䏙5 λ]2{?g ?ĺ¢5ZۻJKM MH>6_Y]{wdͶlۡfVMEDDDDDfJ5dvEi/Pˡ KC}IIKC -1p^Olt~z6wnfdd1LDDDDDdyV;Ӹ\; *:`,ˢ~u9*pw~k[G{]EpbINHsC34_F<N-{""""""yXq_ԯ^ yȻK04ID^8aiRyDJg$nE"∈˲1X3yEJ8?sijl:IAģq9Rv1ZVL$"""""R~%)%"""""r,J*A>ye{qA&c]sc3NBh[h4e"Sr?,&;+_)rI^)[%YAɼ#dv=a+L0:ɬWűϞrmy_S1bWDDDDDDVI?'Nc@*uEk&3^'`x[^)k%[,/'oW;*Mz̗LjjjN2%Lϸ`>a!""""""rh%}uovOm^&<&1f IDAT]cC#\H{15oWzS""""""P1~N`س8CKc1<ڈu6ULiipJ∈%_DQ:`؂ _ ;ݦ.P=PM$0H++,ocښ RUʝn I*yNCS#"""""rʢ?bn@RX`&H8:ᄶ} cΩO Y<#"""""2M&=能rSD(*m{Cihh^'rnA|M^&3ʦX2fj'0)=3PWWuДhŴic<ܳ8""""""sMY?XuuO]2"c6WcPVo1F= / dJ4< . kZeS+y,BkHH1mY=F&M^&*o֕Q]J6qʟ{` N5O2ȜVJk%-yL=HR/{d"@ʺ"KxlԵ`ܬmƧnbgqDDDDDD*͜*Ulo|"Ճ>5żNR6~?H:Ix{pqgDDDDDD*͜*qc;=TҬ,Q9Vhj-|Xꧫikm)4ȍ:g+0U5ν ^');555 uO=w;N*HŚ3n|w-=ac\gВ(\یq9{ LVeΏlp0 3y^*!ڸ1VK} ƭ*I{pN99]9]uLB^')[>Xu ~u!JM2J2'Xn,Ǹ&sXdJ=2X1^"F ?%j FT""""""B?U*-¸=)%vYTUUyUWWcn6/.^iM:djdh 1'U*T@SĦ@ˀU*oW$b޽PZjZ0ot!yѐj*䩨+ỵ_@vs9& \N2g47~R^@y78uȸ۠I""""""%%TSd\o4seY4N2:duȸˠFN U*9J*&-.dy@)-l[Z[1cqsh~r!kZYl.( ?yc\W䶴*Չ3n4h\uŰ:nX宓k?o*cGDDDDDDT^/l䲮" ́Z0`eJ= &""""""ŦE(%rیi`x#xfr8Hܻ?c^ۙ6ѸӠ*5%Jԛl""""""2+Tii$I`^fH-ά,k6hil)564́,%{u.dEv,)yyX>GFr%!\(_xw/5ߘ;V8/sV,}ͳEDDDDDD<"gGϦgMMgx dpBmS-U" ~--%ښ9հ [4Y|!""""""%EWE(pM7o"4'7@XWZ$b޽a}A ^S;},cpDSD@33XBK x&`5Y pg?'⽥*c.rmL/~> ~5bg`3 }4|fFK77r1úҢ5KYCCm(p])}3'{9%v DDDDDDDE39uǩc=cWcj] T)ބq K{<'+}79u?,pu~5 t.k ZZ{91o<]kr]xK ~g9gG UDDDDDDMH" r` L!oC?qA$m^ !B=:o? g϶}z< *IͲ&˄}lH# #~£a#a&o3Q5DlL(sCmnA˴̌ $jx+D  P[C:?j%:pjLLL`:fJ'R9fdBҡ\fK $pA"""""""BO%q?jlM*:%ǜM?f:&T|~|i]S!Ȓ d'96].87?ZŇ"`@:֔I҇]1Rpjq12/gƇ12mb:brL'e9~g6Y_O>8<Ȝb&HjP򧿿h4ʢEu 9>"e(H`0@1N!""""""2a 7F#De͟ @1ZDDDDDDbAǽ!e(#0 \-ӋT00%"""""""2Ta*DDDDDDDD0?""""""""s9L又H^<*DDDco/]ttv7Xlz?1=ݟ?Q= """"eH又qpnAy>[M\mp?: """"%@_KDD8o\]}P%eb(JUS U]{ 6Pea"!UTG3N_(f, mVS|~0ãd_ L\;0c,?BUM514cÌNq ?Zj~ӌ 1Z"U5T}8}]# ঒d\X 5&1R8:Xj`Yj,P#""r̂3izWߛ!dB}:.y7=??n^,AoWΚQ梏sS;>m%99.={5訮FV~EnZDDc.w_Ɨ?/|'|`랸ovvֿ,+?׌16$ ׊8zW|S# Ⳃ?{:Ua.7l玛C=uxwonʝ_\qj/[X]-~ ŷwċcl|[H |,SO9G>^sϲ+X뺸G?ߩC`#83?z(s9oMF}q=-oaDsEY=/'{;z/7ƢZB_1@.]?[墿^?>̫7WLk#B'w>s 4I@/h|km?}^ cj nMq鬋aI$M{\Lv/Kϸd?i]C Mɤ'$JH/H ]}WQ/+. MP KH!)$4ξ_ s]f`.ι"7Gq̲yXe)ݯ Wzs'8*$rr=u]ez,=Qs?bڰRnWcW~;!}ᯨ!뉿ܪGޯa߯[!$oOE^,WJ ,2;SYyroJҬ2m #3EG^ns)#;_Np5?y)U\>>~-_␚˕e5K#Yiڹ;N%iK/QztveSئztv(?k<|dfSDqףLwԜő3ة駃YڶRJrTPRb~f&eLLmճCџRº:0&]]:&etU7}zv\w!|M'KJ7WOo)*8ITt֑*9+cl%ǟ?ݘZG^&\x:ϯUШyID;uQ#{@/Jeu~jO9 .4vD,TE&5>N)rUy.u ջC 57 y~]JjUj oSrga80{4+U=\L[TZezyjoiZ;lJ+R~t3LOT4 umZv); s3+p1_CG/ѺE]^yV]k &~IڦLPڼ[̪0vnAa>ve%׊frwexCO(w-6uw.bUejE qwVp02 j]ppjހOK *}w)tLYf? >tJD?Wjxw}\7Mjo_C￱T;JMMNYS//St:yкsnU͢q{LMԦG{EG6}X_:<柵me3վePC@Tk|58HŦǧ8=Kd Q&`11Ř!ڭTԠazv|׿LD>77K[0۬ZlR}tV??*Qd[4V̲\%," ,4~HyYt'??vְZUW {Rì[٢K˥;wjҍ<\3 x\VP=QF=Pj2ͬ~H)/Ǿ|ArC6lVYPQ;>WoᏵkU_vj oR䄉lSW_IWgJk3D^j1V4]ye[p RwyX=زuk u(sdpѩ-#+[jঞR7+OIY_?QX:m8,u ;zuPOhyf]=CG? r1O;+ݕRr7YuO$Divq=tl*"?Hup2jc1J,j Wo^AJm6cVoIĉ4pM^'?C&|ҬEds*q'z# G o 2jsWWcl];)Cwt)'eNUY'^AL bP=)))|\a5N[H^\."SᏵ~tapWvt8%_󽖩&^>5Vh}`4J. U/̫(iVb{z_yl۷e5EmozXwj"SIMMݮPצ:|`rLjݾ0j]̱J?z5tdOBoޞ[^5g5f>@˚ktOmz_)~ͻUϬ ӨiAcWV~xk>n?Jn#i+M-(1! @4L.Z,//7Rm­J=GJ%SOC:D1*RQᏩݪ}/תMu>[Wo,e}SӿoK7K]lNn\fU`eu{!޺r8[ݮ5<ce3վePC@Tk|58HŦǧ8=Kd Q&`qZήuUJb~Ѷ46XJv|׿?_҂*{kzscڬZlo1은4/`Ll pjYvTve.~w珥 /?G.\KJaOju>[b7|z'NMqޞߗW?RtȤ鞞ii^:wSxLVwN ڛWr[FQⲙ:40X/|{].yftbW***i"SoᏵkU_vj oR䄉lSW_IWgJk3D^j1V4]ye =t ĢONs4淗tݬժ7סΑ{96 n)% [p#_[{Leӻц߾eR/hjӪ_|fi3t{ZXɯ!wOsO]*(u)ԩ=FytËpj޾)-a.Y\G.SV3PQUz,FE ]p-+Hi_د[5q0x$\m.{>Iߦ'4+'@}FjJ^}/F~W9TM١Z:[[w꓁FZHdddRXXXD]III9P3m_o?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?F``?V)vzfW}_֮oOzpj N[H^ӧS =ƾ~5N^e~Բ~В/?W#[{d;׋wvue')>.^GR v+ו8Nɿkը:ZͻU,/W۱ou.DGt^W̟w;_bI^fG[is?0|JگoQ-{תhDjkZD-l95{^{c+I^1ɼ*v75oR ׯ%nk9HG_ /\gqΣjlX^ys:T|/Q%J{ּGYSO4Uk?1(?o^gq9M2o WRVd͸g|%ohg^YJ=]ꜾLo<I> MRo׆L27'ESkq7Ofc}WHj,MeiѼWѦu[߽yI .zn|]٪G+W?7kCOsd󧂟 b҅gA}_Mš+ʶBԶe6}_J*B}h魥Gly[Y5-:yzZ~U=noq|?* 3ѝ?&vUW VcG|9{NnJ ֺZ k@p>{]}쒴Nt͟; NT[s$Ņ_ԻT|-+ĩڹkLT?ˋ%k:_zuDGQ_}pB-Mf<ۼ[ rd&+4VıC4ճMz JSovPVC={\.Rzu-wNY^W֔EڼlR]%M}jb?vFYܡGу*̔R\Nn'FFF&Eu1 k{ܟ*ٵtҴ7^9럿mј"o?hRRR%$$48v=_p _ai[KL߯d>JZhhPΓnE~[K:SGVhV~`Zc_!])vzfWCRgcm'^H_>jci.w?p8wsiv-^gn.S5:sj~m5\7XI?^4%zOmdvѝs;OtW[\ 5^(KnN*^gKR5_s5:huKۻ_q5 jyl\I|jrNԤ|z^*hb+6gAieWiiu9^APPf^YEzf>W빱ZWcPcH\g.9I>V@mS9J1Z%*Sʊ]5JݫuP]YIYpDRQ%Gy^lfǨ#ZtWm4'.^?Eeܬ?NWV(?bVne}_VkO*>+\箃45;yQw^BI^CgNW1kf[f}L^bҾUKAWhTjP_?ӎJk_3BQ5[J k*{GY.lħ״Z4ouݪY{otsq9AiiǨ9}xMU҇O=uck5BרgԷJ|9&MeiѼWѦu/|m¼ʺb҅gZ%]$yߨӇT\5-%Iw{:xkp]߯iq|7^*S5wrL PScĘ Ƽy UL 2ג͟9ѳDџߏznǓdwK~\*y哛` ~){y^':Ϻt1oUT5t*^SCEjhEpNVSZ)IDATy]5Rjq)'ᰲJ*:<{I2)R:m7Fvm%H{ϗK\u9xB=Fw@>`H Wשw/O-g[lY2w4煓ǬWI!پZWk$ɡ?_QA?+RmPЎŦ-Pr#ź\$אtͭco>PK%#6oaeK\j];wnʳtMUuj3c>C''fEGԀ^ZvV+77 WUFI >RWՇstI\tXG]")m߇j?%Y+ZgxN9{*^s1+uԘՀ>]RCƼV ~Yw<jŒK=6[ԇC1 <\(o픇q7_H?.&9sw)R`ՆyO-RW=ݢwNR\Uה>ںo5px gO]֝ [չTW[%=qܿU>'bրz'NMqޞߗW?RtfuwuR]2 n}Sz"mTtKSQ_Ĵ\@xnդD^6)ZnU_JlAҫh]hQ^Wzs@6OX>"5&VEZxHy'cy2u R*٫z9=j'sg+[A_LUuk "VF$s}7VhN͒R^MGhjb^T_{>ḵj:*U2_XevLV,UoY-*yɭy%IFJ[ [*V)71IU|SޝTѺt߇-ZբelG]5\kn~Vz|}S?3dVp|jĥksʟ5{)]JU|^uL%Mܮ5ʒKJjK|uqLMz RE:x8YSIޫ%Tv. 6H.Uwj^zw$oJ֜K ?)whR|mFrTݵ^\Uu\U!KG|_Fȹo15ՀkF*(;]z+~Ynׁ |*[ oGcV舻1r]JbݍKuڛ4۔er۩y>a׬}ۚ̕F*{um|fP݆?#o}=GN|('@}FjJ^}/}.*hѕ\2uьGWJ]obv`yy_&(}uKTlv\]}ɮsBڝ7@=GkC$%hx]wIvl}|.WI+ Y;&zQg)gs7pnϯ.;RݨΑ藵yUצzKmJz8SEhcjοꎇ);!N.yV~uZtWƩ+_scչeT+%o9l_(u4N7c7OKnݿ׸T'q/jn/="u&jܩyݾn>ѿFg+?Uj?7w}u7v5R5~}WP=Qԧ_T ó%=իK+UtޱI[4tqFÇ?$rb7hK|~ mM݇ kڞUE^~q̕wHW]AռGȾ}~\RJe(/7OEe̲y+0GfL+9OUR2U^~ lY\i5%UA]&Q?lQ5r@Ԗ? %@KkTMcO$QլEʲ^}uSd)ڿyb$s\Gi& su zv:ݜSN#GSY [;*vZw\Z+m.Qz M&wVϵ&&L(%,_s2mӺʗd ~}eMlz79'}TQn4,W=|@.F s[]Wv )y׏z %*s4-q#IޭۨG|G^VJCNۿ*D=ж)15'B[˧8IQYwT;_j//])eJ,m W_%Y"iʐ&:C* .bnOmTJC+{+`6^;2uH;UJ}Vޠ?%*#Y9vEGpKE7V3WGYRu9C{7o۱hЕ^-WLS^ަ48!t~sN#IN,[蕅z=py<qo~ssԿƧZ-wӥ/Q.8Kɇiح֟<2Q޴̇{Dy(E G[(*C$.͚IRߴ11P *C'D=I=OoWY*MWKQҫDm.=gqL&|}e.T~q骬%9/GSED8䌷wԍC**l1O4%*d2{UdlE J9c_\Z4o*-Rl|"m}n3b6.FeKճG 0ic ~:G*[),$gzgwTT"iqP~]h4OYAj5@TvIZuPEE%r:3ۥڞ{vRWFZ=ԿGWrNU9RQQ\6?zIG $ɤSM}lJo.X-w1uj./u6K\ 9=wTyRna^%*-.Oea߯[!$o'Zu9tJFK-*qY6אfMѽuvhZZ^4"ı,Rmt9L:e4x5索=*WVࡃ:u: ꥢ6*4ȡĝq*lCW4-QrZ URrsE**"jRIA2}UmYϪ;qJG]R9;($.>@s%~w>ٷ=wҕ[%~>Z e)8L&W}*lU)6twGU IDATxwtUl˦WBI & E" MQk"PAQA4UJGi Bz$;?BBʶE9Nvg}n;;w!B!B!B!B!B!B!B!B!B!B!B!B!B!B!I(WG=OOG<==tErw`B!B!um6crrr,=Q4; |׷W^77S!B!BGTUl6rrrb333ҾKII仚Fy&=aaa }}}4WZ\!B!EQP^^WdddZW3 |+ &999lFUի^!B!UUX,)Vժ(JxNN&Wwiã^pp𤠠&骞"B!Bqf3>>>&ibIrƕ˓ !B!B\WwiӳV"!B!zQUFSnWwiCTUUPЄB!B!*FQV[͕e]Pjʭ-B!B!TUUEqeYݵF!B!0:+ 1.LȐ\cCxkVndmlXO_O}X1_/>ܱۡw[ʪ=Y.˶Wس-oލy9 Y^BE0bx^.RͿLU9˷o>˞]ذ|!35ǣɈطo/O֩_|Kk'}Б[w:hCغkO)a2k]<33[Ư#6ȎcY_9: `'=l}oXNৃ2W/,y.W^Ɨ#jt'+>h7÷Oͤi'>DB `֔u3 5?1H5U,隣5rB"4Qҧif3jGF;Vm[YFB-|p^mʪ/ӳ ?mڥExԸ/dƭih@˵ug= kf }x;|K_-,c4 6!=ldWZMxq-兦z4Uaή,y:^|c<ދ1-c0W+b'ҬH a" vJʹ8k.G[ 5o7fѴiUI{}c/i?]-X9-GPԯ %v!?saY{8ʷd9l6+wk,؝ʗˤу b֍KtN~;Uwg{n7,}%&%r;vJINuPdÆy[l9g{͕ᬍk"n;5.)d_Q+>3\5?#z] >d`z|V'xrBߩg[D~BL#q6'< 2!cDh-9rqC!kA!$8?,d7H܁''ᮢW{b}lԟ7fC7a6=HVv֥u繳Umt{Qxj@Q0z+=-Oљ/1~A Vrbg-V=;xf2'^L.Y3n}"kvV6?IlX?>KQRrmMї-洭Ϋ&_څ-cI+ߗf~> r䣗0v;s(2x@Nۘ& bmG?}kh81k,c:S4IE*>`Jn3zsR>_H.;e6f5<8oo{4ԙE9 {vGttӛu21]N4 v+*m@UCH`.]f_hRb|[vBQqqfɅH5Eo{G}S2!XRZ7{I+yᮕ̠~*tc q' "+kDc5}o$- ~Z @>٨ʡ5}u5;^-ZRI\@UGf$2VKܙ3NHB- tIMg7XRH^e>tWG%%|{~Ǝx>wkV*;mUTj N%OY}o??4>{ް`sj2aRhDć(_fU[ܙ vJQiu ]MjbM<ÙtZmz5ԩ:av3 +wvhmPN;g'_U0\,ZD_1ؤ5#B!QWV:? >,qcvBQq)-٪/䏜'9 Qz#բq<@noB[6ł'yU_q|0~;&3W}..C%=1hR\fYp I[Ǣ_JVZ[i%""O%߻,"v+kҒ@UKJN~8kK-P8j?IOKǂ#UU{wu3kTk#/׷HZRd…-@Hs/ltݸc}Vdg%Bc4f^~cԄf8^U#TؔYjV4xw3< ݶWWpk\rB*Lw9e NfwqtJX7a!W7Z4{_z嬋Da0ɲM1^ۏS}by%0oPBkQ۲&L5lK#oˀ6-*: ƚ…h|:FrbYNQAz~U'JAջYdـwn/~vC[ҿ')V-}_Xnbwz:>緎3me^8T ᧜ 06,=ʓoA66ۻ]i8dֺ6Zݶ#sx{ޱ+t97aStՂVK˃թ3QVy; _h53S3~SϾvlq/EcL|Ɉ}'iE{&B#xd &F||vu*B?extjJkʼ &>2[; Ӽ,[rB2TRwMd x5]MF>G,*)gцx#wp.@ϼi6b.Us/$*5s\- ٵtKw]qJ[ah t &fT{ɪ߻NM^;>aC7-n8NK([v$#w^iMhK=VoDφx9nr YLMZcBAcxndw #*~Ai3lh֗6US1 Sewr0-6=x|)?ο|./ &ФfASh8cкvSmSGm>Ɂå&X !no֖1aﻯ|Iv<""".5g!B\3_/>u~^o.gW=;t86_NJ_}?w(y#1w`ܒO3RW#} Ȥ_&7g FGGWq"B7%ɘ\HgT6T`Zʮ%˗(u}YZ+B>_b2?۬\S5E&=B:<^>d?o ɶ΢fܷW`Tyg9+W\G![}}hG|-<)ӭok)MnoB!B!5cP Lg[cC8s_K+!B!S!&_ n~+-B!B!)ɤB!B!nJ2!B!BLz!B!$B!B!)ɤB!B!nJ2!B!BssseB!B!nG@@C!B!%.-'!B!$B!B!)ɤB!B!nJ2!B!BLz!B!$B!B!)ɤB!B!nJ2!B!BLz!B!$B!B!)wB!B OѣGV(-L+p tJ,1hQzAjmҀo7i^=0ҨxOhҁ8I܇̜TIx)jsFBԅ/̳|F|dO5 bdo:Nx͗A^\&jxVx j6)fw2kgSZ<^ *VhX7q60`Q|1s`KTWFuQB|g8a*ܿJc ˍTN!e^~e"""hڴiSՂm۶ x饗V͚5+ /``ٲe B!Y7Τ*QZ>RȺVj%=;sR?˶{(XrR$Ä%A1+nή\q&R-4ه MڍN5b6T"Wͩ%Xz,:r7Um$1Ft*!kU_t;+Hpw(Ә&?$FHKK<`Y|=1 ZӵLkKhy֐V]6SݕuƦq-c)Ŀӧ۷/VhР/vcTVHϞ=+NˋE#)2!Ozّ=hU?\~MPQ"3p"ƈ28u>Epͪ{H;3?ťCt|3?r4cD u)ش]Ag!̜CY:ybCU' /s6|gʧ]0~=*goQ39R;OzVg^9ƒIOu%㟟*OTMakJA jm'͓3,^ƌO~ ܝO`yIx &+G ;_dF{I>:hg?աv7m;R}eYiv&0wk`d}VUܕ->euPm%Zv*a;yڍ-X6x^d,c{|dwWlS\@@@UWKꦈ(x`nEyxxcǗ"nU@IǏs?bH':]G'?ESާx>O6~6]wqƏ-ŏ@$+L5D~sٻ3>3qٙ<7Y?\"J0Qղ<-NSܑ3>f\+=\zOn@^O1L6~iф鴾 ?iƊo4&AZ>ߟ!(Fu ',ݲ.ػ8L_?aLgXUrٚRqy5 Q@Pz4I 8UWQ=LJp}ĤQ)qQDo^4[ \G4f0ɇ+wiKUw^Z2a<&FW(:Túy3:Jݞehy6oi0x͆؉$W\ Qt ք]| ޞN^fB86o6. gwTvǩghŰqб^K۩;ֱ/͛S&Mx@4y$:i,KZ͔nSl[ihglreexP *3폓?jqa\ ! @``"#Gj'=TUZjxxWz-e¿vni@n3ĺ/~ t4-Zԋ"{9Rr䦜𑓘%tٜ\?7C= {<İ0ϫwI۠S,} ǩ( /( ?V>'XNãg ؉擕K.g~vg\qf8/&|]f2 +-ΰOTuhƒ}:O]~~;;sŚ+uN݅viRsU*FkòuK-Bģ`yaV3Z ~pK\Q|'~ȹMj#<ԣ3=si8{ ^1[`Dj-?UbdY4gK°2cI'm<`UʣeӺAl?.,bVw"W;xqtGmgΧLBVZQU5pE>}+(DEE|a!np* ODk4@DFW3(/8)ZW#Rn|P :V `!GYjѲᕃe&!0$f4 6 :~clX8֗ k¥m ᕃ3% -'ߴ̮(}M=?^dW@vLyEvV.`#+'O .ţ5gS)x(9RATHf}<3\IJޛ5Oc E<EUA,z_GPl<"JIc1U|)_R,:_,8tE_eO,>0˿>r2mWMTlNX<*[l#5}6 Gs/@!ѯ~V4LR+ak-2OZ\:ҡ?ʳX˞{|WK41/Q9,y-*q}gsᑧʹipG A'W;^:mI-MR^aI&c{j/R\3ygN(SF a^ZFŧI^4ǞtcgIT3SZK$Is:ӬtТZ6b;ۯrJKTJřFR)>4bb(*CG$鞾XŚ*Ct'R)0`3HɍͲZ., Xu!j<:\oWX\ߺR?FfVaYZjw;I f l FRj9'TUQ#&=3 %.eAg&pOyNr՟ ^Lx3~3uOL{ne.'+K`=u]iTL x=Yc;3)nbA4'[@3F!5U'}zebmWzEs99v#;N AğlݖQj=-hނnॐߛ?fhY&uRe|y?84T:m܏xz7QyvPڄPhks㰍lUIc9?\mq*.?Yk1W5+ĭӴi-iyyyɛ2DNCTDΟ?3<ĭoe<~(\mҧO7E(FGGWqܺ+2&]i]-? !vV=77W^**LQe(RRR/( oo/jĿR^ZvmIhA>wU !pH4 VN;w_~ Q[Nd2 .z87E'!vZ};H.B~gN:3ꊢp)MFHH#Fx?‰'2e ^^^nP\22J??LB!}Y&MĤIvAtt4l۶CbXh޼9ƍsK3g7IvHMM?,zumEh$11M q}ȤB!.xIHH ,, Wٳg_ׯ]tAѰo>Cxx8zwүo-[K^^ݺuCQt:>,֭uʣPJعs'㮻⥗^rKBn?ʌy_^1#Њ.gFlNo;s!?.oOѝ|4XX:bU܍UR"ɪexSsZ9s& F|[tNz9{ 3qE ]C:i^6y|8ysP6kW%@[ݠDqt= >}&׺fjkV= _ԧ{;vлwojԨiAnX,( 7.:`UUFCZ۷/111L0-yɶnݺYfRCUU6mnJO@@mڴA-i OasYίkw79~B ףiRع0f]XRiAch8kփ($[tݿkqק^{?=z^ͥr%>L^^Z.]9`-C]I&1qD-n|<͚5#""dF Y&'NpۤԬYӧOSzuWνދbg[Ŀ'=^f%͎Mc-dj\u|iU?\~MPQ"3.S7;Շ3^\]t2RꨎYSR>n 2]PǢߗYrzsLGP.;| 6T6yZmվ6zDs>XMgc9+fK1s$/]OW]A:bo:R SlW`1íc|(q+ }8#Ⱦ~#ޅ+*DUbwxGKtŷ̟1 x^HBbT/z~-낥bA7q~˗*Nb#P9Ɋ9lM"`D\.z` m\0ЙqG q-NOgs |iKW d*u{8!+c'>J˱O|Piٳv%[H=WMb\u]t$˦.L c_aIuG'?ESާxbr[%2mփӲ+XRۗ+`݃TnC+\}XY]]J{4IcԷYq.+vcMye& t0lS՝ }~YmO 8ͭc|'XNãg ؉oǢ1i x8]v]8ߟêD`mQ 0[cby*iH߳`1,$}'ծ'uJK3,z5Ӏ3iZ`Qҵ&`?9nӑg3u.v^Y`#veWI>GJܔs>r3~]Wq3&OER) G'M]=Tza9K_o]: yja\'Bm[ߩ6~eL=⼯ܾ w\WU+(opV_nC%Ӻ"}JY]3nx]3^cool+֘(vc%fԜcwwY{ig57e lnO lgJ_¶?fsLOkBoԨQdeeѾ}{Wq>}m(W+''4zt5 {fӇzGy-ﭷ4mڔ*U4k OOOASQFLZXd  rK~B'=G7'^:Ւ-MƋ2>mbʴ5.4 ?R80&VsfW~>& X/dor}T @["<̖;+g<-*Fs,|ӠEGx` b C7RZE6/C-=A[1X^ cWwZv[u%-\p/tUWJG ;k)O**0Gkrwq;Orĥqa7Rڶ mADÚpi_Bui|( <ۍsaT]L;r]].d}bs8~ 6c=F@@5;hHJJrz]Q*dffҥKcUUVZѤI֯_πh۶-cǎu9 qc8q"{%++>}\+}}}W111h.wlAUU9h #??LL0tP,Y̘1cךdju;һG`8MjqY>m?GgZc\xĔ >TV x%9XK5Tt 6~LdŇYm5~l㕴A(6eHJb>Ųْc4S|QS.a2،BbJ]){IƊ.(2ZjZj}Q(=젎W3f.C9^꠽Wqҟ^Kuar͵뮵o1y{e+_yU4x5)[ߺTwe*`?hLw'Wtd D˓O>IHH7zLT^/Z.77dӱX, x"ƒ[nXX>>>FTB\\K.aaa.EnHII!::~ѿ zٸq#fAa0\P̥K[ IDATjhҤ fժU䐓C||<999xxxL@@AAADDDx{{O(B||ECjte@SmLYK@vDjoE֊#Gu cQ9o=^|8NyYShu$$))^6vbPIزn~w`ò$R2?)͛*'1umYHhlauwu'm㠎ßpUJ%A,뫎üRgk%?{U=LB {QWĵbcZ]bYTEzhҤ@H!:)3G! 3IG? 3=s_w4z_VzǐZ2ka[lW^^Ƈ =ﳏ^]mo } 92*C%xI іǔqPRz_,'zk͇-t E!,zO²[] ;KHHH RZ-{رc( \]])))wwwSH E5^g\r|JKK&:vHhh(7ofʔ)=w3*}!WbgޒPGNzb8g "J>r@49Cf>~ߞ3Fkp]\ !LuI*k?dd]- o81#uOL~ƾ#a:wpjlњasS2_e{ +gtDLKvjlZ`/S}gn5* Y7o*hvN"'@JxHHF=܃uMAƚNĐdx{{3c Z- T*NNN%Ç7oih4ƍGee%˗/gԩ=Zp _sNΜ9-ɓnݚ^zA۶m0ˋݯR\`ĉqU~g:wLTTNNNם^$˙4i6mW_?nt$$4~~~i^^^>--H_ՏڜҤ7qM7,{%ݯ>WRiS ŦMXd UVBzz:Ofxzzj2%"i]>#tիW8p`ےdp)\\\0`,]_///ڷoVm_A@?RRSSׯ_ǤqHaa!iiiTVVg۷/֪RUUő#GPT|ͪDM233ӓ"+=n/toц \8'_LSJHHHHn{v8E)!!q#/6l@uRAӱg aL:LVk2RAח{ j*رc [ |}}MG[q5iDXt)111 8ДhHWU˅ 8p ...D~]wkAر#:u'OgO@@ T*ի111|GͮDCVzJdPK<ƆoLQ6J Y>9[yDBB۶mёݻ/65y饗z*(2bĈg AnJaa!sTuL[vv6-gso^eee]Smj2,Yruu+oزe FBVs9;FPPۻ54l%:3J%h4֯_O6mСC-ZD=hժUTPP˗9s ]v%003f4컙/s郷7M^$X~=ӧOGRz 6裏""JB!6R.^ CjՊ'N-%>$i{_,YM61dӉcǎL:f]QQQAQQQRRBRR[APh4r9:R\\\sɔd$IsB.]С;v#GApppΎq5[w7nN8Arr2 x{{ӽ{wʎJ2rh4_`0*0*"NNNjTTѠRppp{{)ޞ(ˆe˖-mۖHd23f`MnGBH+=$$$$$$$$$h.]ʚ5k$77f̘Rl҄xE^^111;woootйsgjMZ͝#hj|r nseŅ"ӑdc=֬Or!Yx1qqq'PPP@RRtԉ.]V[lL&_.6A@ӡVk%<|2eeeIQQ.]ޞΝ;ӵkW1 N ѣGٷoܹs` kܒ[nPD>ƧLoi&{!y;aZ϶бjﭵ\nIv6rp#nm]k~MCD˰h"^u"##6l{6oj,d2&99L233)--EPAhh(׺Vu͚5xxx)**"''l^Jaai+J2`h4&Wt6LR4]#M״W]+],mA2멪Jj \n:& JEEEI7㖣 DQOOO<<<9u}R #<vvv׽gum[,Ҹ|2999TVVhj兯/ZR`ئ=@FFk׮e߾}L2/i$&^0&U"Sc~ƒ3\W㿾ocZ'-ܟ)=F7&> !&<`6f\Z^<6՗Wr|yG뼴"͔gl!̞=u1{l"""ptt8k"\^J޽i߾=jヽՉ_sMu{%̭@3V@*JKK Qqss}#˯k%O1{II 999Uh4VqppZ `ZP-0b[t/9!utʹ*77lr9M6Gիzooo<==Ͷ'[_dر_Kaa!{1mUgA&cp#['w رMӣ]vkΔYr%ZaÆzݸEyϔ)SXf Eˤ '_oNս/v~u=, ]b/2C `/xy ,ʟ>ɚǸ* e.˗?'j<3ڽӉ,ϒ9_ga2(vj!s_ye'k\Qj}:6V3ny6-W[$ӣ9+>_zCyH`oFYVbָq'yq>`[/Їc,ElR6 Tg+8^/ydg/4]+lɓ'?… 9zKkzM>}9sf&!B[8klǐ-dfAĔatw6sMޓMͦ-kS17C RJBNQBXK}- WƟ[v‚Q !Cj'>]ȯANn4Nf[+7P3lO}AkYGOeClUKYCj{"<応EI<fjHv%pذ-nsn{>ykm5.GG }h_-6:2/iw3:+4\*#Zb~ĩvY_w3ct\[`_oy|&Zy?5|l~ɡ.n[ܟQ00q] )hz={`WG0;Rv'܂y;WyhXoSa|/s諻Ô`|VZYK Hgv5v$$lV\ɓqvv'zΟ?ϱcǨ $$I&ޤu OQQŦZP|Q舫+ZJRD&@FF,;pppUVz8-&QZZN3WQ(sppWWWr9 Lf=h&Qqpp $$P9s #004ÇYv-KB- /Bv]Uiow<xtiG(|ȣ?OW4*T@$o1=.xbbkxmWPQ%"#y%TP .-!>S [qm XAZOꨬvMذ%nSO^@oOTZ[F[^9$!DJV()n&T/VYuWZno Tb>IiՍ, 0ƿvv=yӅFP*|˲+|2'JwNfj` [mRzD$}vN>ܙУ[9X`[۶ҽ6?Scv۔spqqǧl֮]hZML&ZO9|0(JE$puu<==qpp@.SUUEii);wDQ$$$R7n~~~M0a1Ls:u :tBII (Ju(JzPQQYYY jM'ҽ{wڵkw][1^兗Cܹs|j:vHϞ=$ĉ_^FZ(EL 1/+/B_ڙ/$r+c*8> __g얟go }՗xiI^cГWѓ6ՏeȚ,yd579[`=6l}Ͷz J OWLK#~ 4Ez5倧}niۗ6_ol{c|.A'hX7dCUҫ<QTYwz4W,Ԧ%pt gمx-I1rr)'=M!Km'-W]j}v te4ߟ$$,,Xu駟'""{wwZ[]lUUUN#!!LJQ*( hZڴiCNjV^^N~~>ǎcńբ[$nBCCx"$&&2h &M)+Et:EEEdggw^Ұ'""WWWi۶-nnnzǓ` 44PJJJ8s ~!;w&88R$!Z(!'dسL=@@"pzRt8'4;wrb³|rW%Q֖ AeA!(E#P$et+DbJ*D\ z,n:vDvӔl:Ce:inBl?(¬,gd7Y[5bCZ{!mmE2T֝%PqZIB]LKgd3).`:dcwEzdKsu٬A.'TFe"p(SD )!!t;!t\_-aFĂ[C){K3PMăQdl^9ksl'͠"!{u?\T6IKmٗ5dWWf iWBfʕѾ}{ FiTm RSS)(( !!XBBBΎ}Gڊ h4iݺ5={4C8<~~~I+>BA@ӑ>|8Ǐo-Or\F???:w` //Wb0HNNfҭ[7Ĝ={$**K.( 6?5i-:efG]J.-ݻ~ߞ3Fkp]\IF=7{_ C;< IDAT+3oI*NZы #'f=1%9 9;v?t)lX30!Z9~LyĚl8[USEEZ6_}Տ_>u;Hؕ†VlRǧ}S7c-M+fl?0r.swr[.׷S}oXiHsɌG"$sbݐf:Nd+d%RVeMs5!`@#!$G"];o!v@PjǠQ5h%uXe ,+?(|c[JzHH+®]իAAAHA@.s֯_3%%%ѿSqӺggg ٰaǏ'88^zݒǪJ ?L.]5k齖J @XXҥKݻ `ĉ&_VNxx<ϟs=";;_MzG8=f㼲6֕yb-6Z$n"6'7OwBBBBB↱|r6oLqq1=\0N2228p/_F2`M{LӫW/BCCm/w0 `0ؽ{7YYYƸ4&HΝ;Ç#**(jMcH8~8? Nfffzrrr>B+=toц \8'_L-&Sɶwk׮eȑlڴ {{{v LFff&޽7774hP*pk$;uQ* <Ν;s!޽;mڴh: ELL :ubTV-1' H:vHZZ999|1777BCCQ(TE'88~w}FvGFJzX`d*ln)Qd[ ^z ZVET^$`0͛E___Ss$1?n(ȑ#IIIa۶mЧOJꎸ8N81c=*VW}x{{Cxx8.]ܹk:x T2:wO?Ě5k2eBoohi;~>z=6m駟~39ydo-rvM\\'00f$ ٸq#=ڔLݻINNFuɡGdeeq -[vHHHHHHHHHܱ?~^zj]Otݻ///"##iݺ5UͅL&umIIJL:LRDѠV3;C 0bbbwxxxQɝ;A((( 664ƍGiL6RPP@aa!eeeTVV( *++)))`0jĨj4 PQQ^G.VqqqGGGz50`z޴_=zm۶#˩ B!h6l`ɒ%_ӪU+<<< WWF'Z1S^rrr(,,$==ltrd2rRJBT)//^oT*qrr ///;;;SR!_x;wB׮]Q*Җ[J9uC :,..իdggBvv6:J+vvvhZSBĸ)N @qq1]'ZZmJX1QJbb"gϞ%''h(\| ϟD+KܩغOzH'H(" 7x4?8|~oqpPMi [SN1eA`ժU >P>ɇLHKK#>>Q """VJBP>f ^Ņ]mzvw}Gtt4]tM661tPzƍQ۴E撞qsscʔ)8995hEOBB'NӄѳgOPTgCeRSvXXڵ0je˖-\t ڷoOhh(Z2]_+<˖-֭ٙ[ӳgO[o";Fs+O<\&q_onjH8n"-ZESڻcFBVeΜ9$%%Rغu+]t!$$A2A4233AEppp`̘1X|:2A@VӺukڴiN#%%www D۶mC=D||<֭o߾jH8A '''OÐ!C7_? l߾PyT*uhlO.coo=m۶_~QPP… qwwW^]ExV\ɤI￿h7 FTxws!w Ew$axgs&`,ϜHΰ}\FT3쩧ү^U䥝gceUŒt Y#,liV?덦4KE_bO*p'+|%0k3h_9s+OEr)ANii)b(Jz!\]]ME777ƌ͛y衇jZo7;1-s} ۖ)ޜ9NPwq~=, ]b/2Cgy^W\)K>ƅTk/2j?X ,Exf>9 *gsn_!_cVcW 9'зʻ,;orpK=M,;ˉ|x6[]PEp]sdZ gFn^ulZQG]7<-}Y/=hӤ/77~O>ohƌ}GNKxxzz2yd"##7o)c A1bO>$gΜaժUdff >oΊ+fڴi JxdVZŽ˄ j%ܴZ!?k>9m׸|g, աb_fCo#dlՋHذA[Rg!Cj'>]ȯANƇb0%,e6x(]dkV"}sBn-Si5e(hXؘ!p*8~ aDGJHY,G#:ّs?i[6>\lVDZ?gc8o̱cҥ ;v`ԨQ?gp?~lwNhhiJK:/&M">>3~xM)J~RSSٵkNNNӶm[fuLM$:ĨQ9r$vvv6ʨĉl߾3h d2- <==2e c@|bɨU4AYv5(-Tn͘lϠ*~R3Ow}>ڝYxO,xgޞkɭJ/`3e]g=>󵅱s:(rcfcG-"r;5@oOTZoK(?zӅFP*|˲+|2'JwNɴW{s>wߚtVk s~uqdSbFBBgΜˋ;Ӹ EZ:WI_;<^偈]s_v^GOں &xjff*h˰zڪ9]U(HC}rnjVLfٳr1Ua l>V#ʪBeEvMf1mLred_kx.in_xݬz-^Əh{=%e`熧mi#?8x^Q3Cƒ\Ж9̓z(|\&Ǥ>jnlܹs9u;lʕ+^WWW&O|47'Nd|̘1'ή](((gϞV~n&)))H޽i׮iLCG;wfU'Qj7Ǐӧ9{lB$$,BI9!Þerr<rw"9;91YF (kKd`Woj<V鳉dŔT 8t3_['`gA!(E#bqrMeT)*2%J$nI.BLǵ[?p@C^G%Pu_;ӓؗhcaLPw%"YMa+%"l3w1&/7'.Cf?xwLy$ 0Sb'y.N^ED?bdbHdr qkMҽsK{infﭶٺ1hkAČlܸwynݺi @nn.=L0nu֌;={#P*6]+ۗhr ˖-ŅMGT*J%JҴsEnԭѩz )))1Fjj*3h!}E?ңGBBB5Tۥ]vexӧ֭7[=F_M1&fe`>nhp˞Bq^YsC݇s 3-ZDppiba8qUƄ 8z(-b„ 7)Qs[Z`mK-g,Qw KChjRB سg?V{$;8{,"$$<<HDDEEEܹSlٲkOΤٷHHHHHHHHHH4fѴk׎*V\\.o߾Rr9N8Ktt4pk01ٳg駟С;wZUcѣ>|mJ$ ֞I-~_ѣG~zqxkO-RCBBBBBBBBdɒ%Z^xB.]Jhh(-:2NA f2 LVk@ڵRyFD~gT*cƌlj*2d6JAAN"33EEi߾= ^Ͼ}0 =T̶|w 6TVZբIHI ۚ^x֭[i߾}$<A`0JNN大Jqq)Q`@&A6mpssCEVCKŎ;G&}%1Ν;Ç)..W^xxxljQYYO?7;wF&D||̜9 УGub^UUEvv6ǎ#11ZM6m  ! $Xx"HQQdddDVV Ю];:v숛 ´5VAϙ3gԩ} LvKy+cL ***8{,GEv튯M}%qp=lgWZP׮>Zowj!Ԓl_:n!gϞ=1m4bbbttD N.Z͍7@}}=YYY]J|||Yl6O~̙3|ׄ !.or-(^rF#dff:L0wwwry>$عs'C A&?0i$bbbZ7f>`ܹ\fLƤIx31c^ۆ\?EիMDQD0d Sx{{_^$~.N@m>+:$<͜kl/1{c<;Pa lcQc_cz';ge "}9W`mSܧPeSEPfW0LJ ݰfyhobx0- ᵇ}j!o,O4_3 KAw"w"ċ?V|=5>[s-{ V}}U&iMekI;7ʧsOZ6!koK-ODcc⤾[?«M鴭qẎuL ^N] zcIcF;D]z]sz_{|w3c)}V׌=G5->IL*s zOvNBBBBB#- 7|Cjj*sO8/'("̜9sαrJl´i֭[Y0;t tw5~2ŽcȢ?塑i"yMvL\:{xkSƑ~o}r` 1=P rcC@؅猪d8|M'7icǾՉ6,DўZh`oJ蘴d V7Scvub旟Qڛq* K'#zy'懼YXs I٬b-`J`5ֹ){6I?0Hҷ-hG%$$$$$ &vmEo:^z%<<<:P!"<#TVV'pwL!d2=zG hlwES=._àBWhG0%% !qƱ{NY{O?ݩJ\]\o󧞳e ?Y) ۽̌*"dX7'R𑧐>ŊU}§3<|~ 96/ߠ aQ)&cČ{<xhTPpvյXIna ߥz7͡ $E}5-A!@vo=Fa/fb/r˗H2?"6>&*\j|3V9^=I 9Sq _Gg!wѾӅ/CP¹E:JSd+ hXm] xbv< +VW^L0θQgرc,X &гg+Z KX,hZrss;Ĭٌ?dBLL [l6%>d--hй;}j}=m˖Ɇs%䞑}QdKSz{u~w}Pv!Uup!лBSN=d,}?>p/\uzQu@_v}EVJUk]ٯk琯#WBђ]D<$_2zGK-IcnHǪQY>^Gh;H#rbnl=H/&_r]MԘ?UQ͚W̸q4\Flog?*]K{ ݜ/CY ΡC6lX7XsmRb\ET* ⩧⧟~b֭@;%$$ڊZ :D l6***TEY.SCNϱO0apS1@M7}c#oϜ]Ǥr؆~vnOPKYDm]/Rsg=?G12%/10Jck[[`t.y\<6t-.["ӟ;s(.IiڞfdE3rD]J Z7-Z]M]yѷo6]+"K,c̘1W]Á\.箻"))ŋSWWwUHJJ";;`fsHFFDsgӣG HW.""" B\qd[~&9x;hW13f ::[Aѣ:uG}Þ`_IA`ݺu9riӦhJxOD.~O5A믿FT2rH-h4sw_#Y+WOzi_PRRR.S"ӶHnUYO xHHHHHHHH())!99 ٲ2l/|M](&il|tD{6ܱc'NDv˱dzΝ;Guu5y<@&hpwwLJ E+رcX,|zdtFJKKIKKc۶m`ZQ*rd2s,v;vUVaeȑ$&&ҽ{w%ח7|[oGcVZZڦ`eGٳgX]?"!!!!!!!!!ZxQ._#̞=c N>Mff&ׯٌlb`6E\ZFTT*tLDDaaaCE>c8p5,6llN;:vtXp]w*_!"YYYܹ'xV]/%%%,_[ώ;6m~Cs*HHHHHHHHH>9{,l5(i&nJe] "fo;w{nr9r(x{{VE&aZ:J%yyy,YRSS6mQQQN[w[oEHH!!!DbrJ֬YRd]QQ` 44Pt:V 09N PSSoA~{ wo@=XlSN׷E[9?s 6mbḹl߆e2rfsj˘ӇիWRCBBBBBBBBV/td2DDDtH%Kd(  #<<gm L&d2QRRB~~>rJVX#xGӧObڴiZ3gWA8y$|z___zBBBׯ wިT*vs/p!J%nnnq2~kXP{ѣ,]XFN䨙cnqFF#ǏGRԎcgNYY_~!77 L&* ___"77Պ;V< `20 8pR ~̘1VEŋJbbb[%ؿ?}2 ZjJOPP:%fr/_NQQjFMM C ͭzwp{v;f\Rt#bPXXȦMw"3}vHJJjuVZšC* vl6(h>}:Æ kU`ۗg}UI\zE zHHHHHHHHH\1-ZIIIiu pBO<6ZAl6tR L&vx/x\Ԇ whyF#Gf̙.+((W=\5ݽum$$$$$$$$$$Z`(J|||ZungymR__;ŋxyy1vXbbb.(l69s YYY䐛K^^gϞՊVmdV%::OOO)**bӦM$$$EFCii)fU7̛7N̅SO=EDDD$HMMSNRj:u Q]qYhTVVRUUEmm-555zXnǎh4ңG6Rj5t֍pBBBjS9>k:Z,T 777f3FшN###JELLK}fǎdggWuuuUUUo9)!!!!!!!!!qŰZ$''zAUYYIaa!Cm~[oŪUdt֍ѣGn\=J~~>DGGETTt ???IOOTTT8_\QϏPʨdΝ׏`nݺ|rx\0LX,J%V^|CRq1 j2xVخ͛7GQVV֨/9777˒vX IDAT8qO>xzzvֿa6ٻw/nnn$j0@R9j<==BPPQQV%--ARۢ(r7m۶I+,^ԪJKK)**bȐ!mj(ÑraL&v(--ɄݻwgϞSVVƉ'ゝ#RTTDUUGib\ӑFq& 8x3F'$00)ٳ';'O$99K Ze͚5jgGi^ljbٜP9x {b 6fZ#@RiiG͍rr9uuu.u777rss_:+])!!!!!!!!!ѥqss#88RPZZJii)IIIvӦM{2zhٳg2Ç@ZZcXGK= BRQUU^,III#G`XwhɓzΜ9ĉ]ڹ!"TTTL&C&a0Χ YUJ%o~mm-w}7 ۗu8+*9{8\6 }vV^̟qssÃh/faZBb69}4 @\]"77?ؙV'U*j*++Zx.]Pm6-kWRZ +bi~Q۔;s pal6cƌ;vϨQ%jdZbbbF222ظq#>>>5Ln RIMMe˖-9re˖qwKNNO?%55j;4l}$22DQl6cٰ픔 '!!FlbY3dȐ6bi */J;=kVgA(++ɓ;S qVio2>s1vbcc;8uuuT*)((`ʕdڕβeXlJM \wQTT@߾} ,, ___:Dhh('N璊MuKII ;w$22~ t֍h233ꫯ?~K ;///AնMQVVƮ]:u*3.zYv-Ʉ6iG(l6뇛[,EQ$..Nju&nvQzz:70.z98Kӽ{6jYz5:Ʉ իUsݝ޽{ng׮]L>Wpi>|0jZplf>/"=z_ڕvh{M( 6zjF慘c!ؚc999Zʹmxf3=g.(hdT*222>|8N)h4YfK} JKK]sv?L^G |G?^^^$&&2k,ҨhThR 0lذNyLxx5Yn {1z#Ohh(O大Kee%GqڼG(VJE QQQF֬Yiv$uᑮ&إ*rv/qm =$$$$$$$$$:Ю' z)))l6#"9ww֭[Z.-HNNfܸq8pX233))) BTe\^ 7J*^^^r-޽ѱB ::NTTsv;ΝkVCR\nCR1sLlf* kSXrHL&EEE&;;YcO+[qohwW?RCBBBBBBBBSY`A`_7zU oyde„ dgg@bbz4 2UkDQLJ;,"""ȠAHLLd2q)=̰6//֭6Idd$ZѪVZ|&(-JcTVV2lذ6DQgϞYWłBhծjV'm69t:]剢``РAX%CP8j`p92dgϞ%..V@TT hNs9Ñ#Glf^RFӹ%lӵ2 T !:AX,΄ mt:MaZ;:Rt\f.F.;wYtdYQFzL~WXazH\t頇L]Jki{ '֬ge.Jҕti׊._k/%-D}D;j\mJ-!ёdee.(2h vΑn닻;QQQŵiq퍷w[UÃol)**B&L&ĉ.(eyۊ#u1??? Ar[z1A@t:Nݻ;myF#G&44׊Hxx8{mW7]'衈ckfXYHNN6%=v]RFZݑ#ə 6nboFWN8%ܹs߿,† ]퐟n'!!L~{dȑFrssEN<}z=nnn`AUKKKX,.=== s&twwg׮]d2웛[UV<<Μ}1C֊>+KXLYSHZƅOuhuk,Es̶P \صCx(啜Kh+a-w/]x샴_護UYmT;L獧a@xmsX4;-bu쥾0uIG٨|I[ؚ&G7S6"0yk&۩6޿Nٚ;Lh72WFצIuyF=Iâg9Z|!h={QW\y˞FS_ıxw>ιx? 2tY СCٹs'ӧOoV(FHHx8TUU9+5:V%&&sa۝I_e̘1M?~`xyy94g g}Ftttȑ#Yf eee>L6׷QHOOԩS~TWW3uT .IׯqH\txx.x-#oa#+x'dOtcG ]abϧ<_YrtpGʉ 4oGx{x޾FrSܧIޛ;Kp$Gnuf1m!M{c ̒w^}y'TŇk) Ǹ_-?||]hzgIaPO2],tDs] OMb??`.(˃Ėy2+ɳ #͎˜E E\}ȃ@m>k i.R?y/зn'yexy^ܟ۪>5/ ~6(#aC5^.gG6ges\gbޗRkl<7{i3/MȻz[X\M1qؼo C:.|>|/^;s){6߃/sNKwſ/Nl~^JHt!y:l+"ɓ>͵N>}LW^@aaj[<`w.QQQ >_~oLjkk1 L&f3e^{5Fc~~~ <_'`0Ȟ={8}Ȋ\.禛njr9'Ooܹsd2 ry뭷W^/LGjkk-_ PUUERRÆ ksv*c%<dڏYD}]Oϭ޻PK1 r`[ XSw}oz\pmm%[t5"7޴1בaޡ\F&}5?[e&'ess DIf&}6iHqguh޾S5ᄂ@l7=&7idRdLu.|sc繖F3lj\x":PΝs7kdǐEC#GkiXBQRR4d2ɬY~`b2RSS;Hx1L&J}ϧ[nTԩS9w[n%##,j #))QFբ* AeʕL>s),,dɒ%jDQ1cߢZI&q9ϟ xyy9+zAA#F`xxxtH@-<<ٳg"ZUU^zq뭷6݌U]e+K0lvW0_X} G¤mvxoٲe YYY.((\[[N#66)SaIAcŊq"Ssz(1^&CD7(.h75c9Xl=1b EO.u DȩcVt~6$E};9rj|9|\8%OIӁNޤœ)K׸d#ֳݻh)oc)> ik9/EmJU8~5:?n'"sc r]}HzΖUC/d-ׄ> 7cۘd.͋obO8F$#O!A}K ڴp)- ijܕ-̵--U(6}աM5}{1$4Y).|+ڙٻ_pn>]|vߎ3OXIna {R!uXjg*WE9pDFF^ݎdnwXώBEBBB󣰰83 {2fKK>dn4S\hFp?XZ6DRqmpB^z% `r5tZpJJJO>~Qnzu]LBQQxxxhewq۷_Rf, sATZn?(/Çٻw/GnL6[WWG]] 4#F4KB@DiĻ`? يRjcѨhJ">6,a}]?&Mrd2uuud243`sEݻ_EE=ܴ2h}؟}եpk\Bx>LҕI//8ugKُQ1Qc=7Sk+{:faz2iF9$=lmȻ{SCN^d"* Ctqr.= ̙3bR=x8r8x|zpDb-uf/͛9tT,Y8}]3 /rW sLs1@McZx%Dʷ1ycԭJ& \rUjOJ/j8clm3Ϥ5ygzDf|0sX~Ґ}Ǝ;Qg<.0f#sa̤>h38sLVwQϻmMT\ȉ~JbÝE}.XBcYz5'Nlٳ'?SLĥ` << SUUE```no GTĥV$BBB~:$HЙt:f͚;Cff&:Q9tz+mNziV^Mzz:nnnΊ*FٳgyU 'ׯd:wr( B8 IDATs; 0@FqE ef *L6d@w`O}g9{?*C˻a2܏%$:8I^E7ȢEؽ{7Ç=LvAA&q)bbb8y$Clz90ܹOOO/ףP(:uj2L&֭cԩW^Et:O=}iiixzzVZ?aƍ9D|}}Q*dK8v rrrشiNf9sx#˙3g111WL&s' GߋQA8}hGQkPc`1f&^r)el"z}9UԚ Ongy1C:>cBG#"J+AAAM%$:K^q%YϮ812ۂ~&9x;.%\[6G'Zw;7>gqQzu۪aɒ%L>XF# p>0Xz>LJJ%Gb.F[%\Xt)̝;]*Af߾}L6]̺uXlh4DQt0777j5~~~t:l6ΝNvv6_[?M%S: :8ʹJ7XPT3;(bbʞ5f*%6_x S@wĎ/ z, sνҪHt%%%Eyyy-a9 NEAm2~ӥ"ao>g[+Zrj0ݪ8d5wmFWGBB9jjj:mɌ3Ox駉BTj9vzp 7t^TrA:Q(M*77G} W#*ɓ'Α#Gt:Z\g.A.x  W^!..S{ԕQXXF锶DQۛGyO>ӧ@LL Ǐ`0\ .A ++}6[QFT*O?4lڴÇS__L&CR94HjbXX,T*7n m r-!Q ?{Wy&zwΙ4ŒlK%"c16`1{{ll6fBB$al+6[n.YO=?9\%jD8hNyΙ33;>q)[G ʱ͸E}C6{fH`VKTZwC]q|=VJ:v&GUحڶmK.'  C"44_R^Nuxꩧx7 --ݻwc`:{,>I&]q믿NJJ 3fՠ>%hooA$L&NDD(d躎je֬Y5Zvtteݎ@ӺcܨJnoQigt.n$rt,%@ѐ4.23MLLtS9[}%ez,IsC`"!  A/}͛7JQQCfV}X`U۩677rJbbby IPU2:::PUcǎ!I'O&77Պ"H,L&.\C8}4G&%%.Ү?\Z#PRZI@[v\.n۸& JPP!!!FK&yܔUAEpIcZ rؑ$_Ln k:ԝeTPpNԠHp {7, 0n{ңߺ>X_>7)IwT  ߔZ!0{`$''_M6|A~RVVFMM ?я? K;=x<n݊DGGOff&s&_?GEEix<8{,G|RRRX,~xFTUi%%%܌p`ٮhW4n7n"##$>>EQ%p{ghNK݇ &lݝZńG-!ǑP+n/υpgcgz-ՔBls)t2ñ]4WO]y29H]Gik(pX)v/?zi">;}<7!TA8x CbË/ȳ>ˡC4iҠ /0b_Ά O#H6>|RY`iii=z%If1j(F,|>6mĎ;hoogل ?n牋CUU"""5kFBQ+\.PTQn7Ŝ8q"qbu:*m^ZPݳ}B6X)`$?$ 䋋\Tls$!jthkKl6(ZiؤZ_|7-,F5˿<3 W!3ft:΂]8dt32 thA^?^hRwC4ePVtd ]YgBVb0Z䒘ȯ~+~E {S7[OaM5͞C7S-wɞǐfBL :5>jv댛( l&7>`+p>iӗ1y]kw}]; 6W&eѵf'"5X&URYc(_w.Ol9j-ĞuƇV[˧  /gΜ`ø$&&_'Or~݁(tttsZC_BXXg?c|+_1f\eSNQXX#.e$.N8ߍu+/^t^7&(:?:#,GοKݏ1C",Z+.#Wq  Eo6`qM$QPP@RRoo~Ì37nrI&o8Q^^u,Yٳ$<;9%nAAPYYIvv`q]??}vz-vMvv6@l6[cfVΡC8z(<,YĘIp/i6l %%sqQlBtt4˗/"U:޽&<mmmv(f#$$Ӊf#443~x;wp8HMM%55b֭[lK_6͸txי3gN*C֭[_P:f<Oe׭*VlINBC)oolm3yV 6H3nƉ5q,_ڂwx>s\?]뚚.QW_KI,‚$k(٫;d2GGvTu+_8̈_Re#f  wzE6~̙L4Y~='Nĉ\.{K`HPP`6;w.3f 44Ыֹ?cf͚Evvػw/7n &&>P̙3ՅC4BBBFQ#&&`L&>6ꨩr*mmmx^N>ٳg㏉塇bرDDDהc=o˲eˈ2*=o&#F|<9rؼ&Fe.\Ȏ;شifͺfS1?k60PN6vln1_ciTLwM0+\C6=%6'Hë{K`/v8x9)):66vMAAK2aR~M[[]]]FjLppp }:;v !!3g"I>w}ͼyz,|ٳ5kp# a2HKK#33h;k6{UxB{0b|A.Gؼy3_5j_kk+o .4@rn:fϞMzz~=^J$ω'Xx1&fje_ oȌ !<؆ߝLDGiʖ6TI jEͼ ]PgL>{nCn joQIAA[v-PӧOS[[ˊ+ukFjj*&M1W^fn7L<٘q;f1ȲLmm-'N`ǎ\., ^x Ǝkl/Immm/a…555rJxA{1{lƌ纼sN'X$IbϞ=q=\q~c;t̮f(C$ ~HĈ pܝr7P%4d ÆOyo#s^[ڻw/?P[ۤZ%  FwKh|IA'N IDATϸq3fTrruW gܹdeeu>Յx^~?>Ϩa2l6EAUUbcc#Kll,ӦMرcl߾fΝ;~ϟ?n#<ªUPU &ٳ9tPMumFAAmMx꡸nJJJhllӧOSVVFkk+>NLLQ%44DzFt]gʔ)444piz\ =%nEqj6v>E_C5*xe&]^4"e nL<أ6ynIbbbp݃0@DCAA<K $Ib߾}{Ƭ~lcX"/w^TUl63|&Mdc]줺Rv;IIIx^L&&ri!@O>#GHll,X,ӦM#;;>OIII躎f㡇bժU(B^^OII eee$''Ƚ *ͽmx<:u={cm~eY6ޜ9s> Y pŋ%!!EQn)"I-7 22G˩zR>qdM<'Nq?$Y"24Rr1&DSLrOYY`! AAn;Y1Gk$ .Dbb"j*FɸqDKK ?O9~8?LRRQo۷c6$vdY˅EUU|>qnXcZZtvvLvv6?~UUq8̞=<@jj*|nǏ^xQFe˖?mmAAW&55 ݻУܯ[foߎdBVVVEQ 2f~理*ؿ?L>zh0gv%K{Mv&!$ɌLt]K =(=%0"jz  kǍBO^w}āؿ?>1Ȯ?!~Əσ>h +++9t$1vXBBBe7|iӦI ػwQ5Å 8z( ? t/Yr%555Ȳn?99Yf =QcÆ j/GERS?ܹsFFF7"2]]]q)V?0_77C$֬YCbb"3[,ˬ^͛7v(-mM^u:zX   ''.\CMM deeQ[[իYl&ɨӟsΡi3f`l6ٽ{7deeb1#'';o8|0N(r={:aaa1vXinnFUU;F~~>8dYFDmƨQnyƵΝ;Yd-Օikk7%uuu3}t&L@RRf[^/.Dtt4iii$$$ڊ̙3ڵ8Fy1uV233YTVTTDqq`!܂Ύvû  0$b;!)qc|G-G}>odرw}X,X~=QQQL<cA[[6͘[u PuE!66ロF6l@KK v˗iꫯe웓CUUUUUHdmllA$IJPPM… r1yd,YBjjQf麎b!>>{x{g←#&\8~E"!  veeeҞt8hnn&55(VGFFݻYv-3j(>389¬Y[ZZl75mO%1cƐ)//pb N1c1E1_hEEEu3gh$ij>˾}p8<ˊn'Y=z4K.%22/~ ~ox&L`=ֿ5NC"!  vo+;vHԩS4 IhhhwAQwVO?ԩS[𲵵zS Dhh(.1m4Vի)//7w8QZZDDDp9y˪jkkOee%qqq,^xSpp0'-- YywQuƍGyyXr466vIAA $`hiih7RVVaDEE~E!++u0$I`t]ɓ]:AAAL>#GPUUEJJ SLA4^/QU~ʔ)l߾h;c n*$ ֧z&</Gt2sLP $r^/׋GӴmFuv;3g$>>Mȧ~ڧĔnt.44C"!  vU(Bmm-]}sF">Y1b'NԩSՑs$hv5f3IIIx^^ e62e v 6PYYilOcc#mmmNpp0}FL&!!!7p[j[nE4,X@hh ccc#vb֭:uJinn2=ʧ~;O뮻 B4~99*f>w"  m-Wvfؽ{7nyQ__Ϲs;v@4v;:tZ4b'11NvL&Ξ={ć넇ɑ#Gf!IGfQVV$IDFForaZ\UU"==*8pN%&&ryJKKe4fرdggNRR"5GFFѣG+:111"I}'O5>'J4," O@AA`_zjkk#55)>Ç:ӦMUU"iQǏ'++ z^$ƍǁ9s*E!))dfq~Y$lBJJ #GF  !!Ç#2N(z;_'vӧ}ٲeXQvsQHHHRRR;wn!0QTTDuu5mmm$%%Q__OEEfcĉ),,D4֯_O^^^dq•E1fV DCAAZ[[oXNx1bǏ7JDKK KMrֆd"66vƎ{K K4{6ӧœAAACmm-9sCUU@vfM0ZZZLٹs'DEE] j 55˗#˲qޞGuL&YYY3͞={hoo'!!CNxx81㧼M6o~ޫsz;,˴ vIAAU=;Q`0^^^n,$C( S__ϖ-[lDD6<x<RSSf5&qrz($ITWWSYY$I$$$`Z455QYYIqq1-a8z(g:oiiZ R{CeۇbtXp94M#$$ŋq:~9殮۷JII IIIDGG#2єi'N`ʔ)7<(|>BCCo)ƿu,K1]aIAAr\mz'X,Ƭ t'BePn7~<eχlfc,tFC̜=f i~񐗗ہ,TTTZ644/-5Mva $4M#==݈UUz=ciC.1 +,,ŋs<eeeȲLdd$躎ɓL2W/**bbuHDWW`! AAn+# ^Chh('OD4)t$ ʩS={6eeeL4Am`vl&..8dYf5&"""p\W0͸nڰᠳWIj|DGGP[[v3sLF٧8+**(**j2iҤ^jQS)))d21NUU^7(IGsw@oH  UpHˑeK$IrQSSC^^ Dxs4M3tvvIgs~l6DDD8$I"++Çj۶6:;;¬TVVx3gMu vi&S߾cNOOgܸq(ӧZ=0\i>|3gw*   m%fZba>,,̨x:Å$I9UUiooGUUnťtvv뤤PZZګ {H,?]%66bgsMBB,s97Jxz2Ax7  p4UUILL4j[@;P4Йeuuٌ|>4$cI8Nn7Off&wavݘMQWWg,ͽL[j;i$4Mx-lA$}1~x%w՝AAAj5Nkk+6Zc;i$|>ttt `$kTU5L8xP~?7o=픛KQQQ4WOdd$fR^uHo6{sUII zA %L[B_lIA%` 3!!!r>Pƍǎ;. j҂(KwiooGQBBB1nsX,68eYfzj}k& BCCj&L@\\ܠ' t]'""\ۇl&33GTUe˖-cKh&!{KK8  ,e` C455 vCVDD 4773|f3'sNdYYV$TUFdd}$)#)) 6ӯצ:q1&LpNVV[l!&&!sE!<<`|>Ǐ涛6mbԨQ:M 0o-k- 0LtK5 ΢E~F{{;L&.85J^p8>}:aaaF#GOjժ~)bzfϞOPPUW^!99~^lBjj*QQQW/Iŋ[~BBB; a  m裏RUU5,g HF[oe$NJdd$nǶmp݃IdH9qd2a27o1!<<Vbҥl߾_5Ɍ3mf(jbŊ+$={p ~#MӆK=DCAx3<͔)S;o@qq`0YV> illDuXd V˨Q8pmmm~4MM$I=~C`ɊvillC}vvÇ)))̼y"YYY0v`XX`~!W0@.* VP0BA 7\GG>Otq]INN&;;M6裏ig֭ɓ)++n E!,,#F}[[ٳginn&""׋d2Bjj*aaa(i޽Y fٲeF,nvJJJ7f `/_ΛoԩS6mZ3V.OlIDyy9,qFXl_koo'%%eHz0XHNzz&qg6)IJO'}H"zU͋.w+ Mkk( $qwƑ#G$ ̷mfΜɱcضm[NJJgȲ%<<1wuuS__Orr2?яp:H&((Ș2躎ngɒ%,Xwy***5K3])--%33+V0o޼I 0"jz0"3? s<2#/K1HA&| TX99[+8j'1.:\?[f$2J%?~~MƅtP|MBF:‰H QĆJ4ǩ/&ߖ.]ҥKQEtIYyGxw?~<o}[8N֮]c̙Xl6#InfW444`Zq8W-:*I |'2c }Ycfw> 4daNXX+V ""͛73v ǡCxC7b̝C$=A$ c?j-cP""Es餏9i_)Zu8RG4&+?-IoRs3Z2ƐzM^$;IS333KTIAfPUUEll`2麎(Z Ƙ1cgEu֯_Occ#?AAA˲̈#},y~$iUUU|G4773o}:1gϞ%33sP$"FIbb␿I`&׾E b~ CF~v!yv^ޖM桽 -T;.m-ur0$ a:n]23yJ=ih5XV6rUu@N&+f\:Hfz&FzU95OѤGh2#cqHC}G;i>AnҥK]l6cQVVƺuphƜ9sx饗(((`ڵOvzσw]4jp/,,w{졠_|sCQ$IvX$IBg'OG$Gunrrrزeˠ%>~?֭cܹP'IgϞP$0i4A#$ ؘ8.Ș}ae"-ǐfh~4n`PMlsTGt/BQP ]1w} /iƶmp:wR&[($f&"{k94 D6)4wHF[scDoNtlȖFB*p;w.۷o'::Z HeLBjj*k֬!>>E!2sI6mğg9r$BKKu\&֭[GEE,]ロS ]ש7 )) &… Ytiݒ~{rJxQ &[QQ}Xp ^JUUvng;Hz0>zA9} =5Z:ѰXȟcaI7UӍh\֯7NsTgFh "!& 7uAK_gf̘1Lg_Ntt4O<ˌ?ɓ'c%;;z'O}vx<477s}aX9$2:::X~=~fΜIpp1Be8p̙3F/^7M^~7#<m֯_ɓ~/KYpua@?3w^?EQOzS]w+++cɼ{0yAn*1=4^t%E`ӻh2~oGt^H]Mػx6} ;8aQp7ZYjiݛVf{Y~Vˬ,J+5r7PàrARap|?3|]fS&DZ1mSK_qu(i͛7~l۶/7nL͚5V۷M6瓟ٺu+III[L-1ͥI(Iqq1EEEV+VРA<<ա (!"""""66ݻws`IIIlݺMr}q{اz<{AXX맧3{29p?ŋIΝ 9JOO{qu"Jz9uu""RN;vi_/ҧOԩù(LHHHСCoߞ pB{=W'!gaDDDPn]%?d2uVzK0T xϯzyڼ#Y#;"*-44%5 (( gu.}cX:v>b9˻/_NXmX S+p dggP4ɄfcΝlذf͚GiKNbb"Ν;ILLj뫩bgQXXȚ5k裏\Tcǎ=z3bѩS7ǿ-9ޫ9_bWnPDD ^jQO>B`Zs+*Ñ*@I9g2-"RiDTeÇ,WRf3̟?Krm_3ϸ:4qcǎeѢE2gVZu%?N'gwu(RE(!L_EDD| 2D\Jؽ{7Vb :ӧ3x`W%ncܹt֍ٳgn:rrr.Gbb"ZbE%=DDDܔFIU7`NJ+l3LƜ9sp8׏/n%`ذa̛7f͚ҥK9vaUd 6`63fC*DI9g2-"RiD\ N ƯJ^^<<8Nf͚4hCK?Η_~ɀHJJbڴi9rĭ~ޖ.]JddvkShZ9gCoSCDDD[0t___hРEKz{%553i$-ZDKիǖ-[ I&xxx0swq/_N.]xꩧ\TA0E}435_~Ǫ?49 :I0?~W}G /=۝6ۖpwMW`jVsrx&}v7&C̙C5ؼy3͚5su8b2p8ddd'ݻwg̟?ቜѤI1c,ZpիGj\Zfz#ە< fYΗ hK#i9'oaoHvXI; j5ڳH0 k;b[vky@~1?I`T^w+z3?sWG8X) 6DYĤl.|9:g;#Gfyp:ìʼ{"""r&cǎe̘1̝;;Jfضmtԉ7qFW&r^yf̘O^^4nj-qF9Y|Ñ*>ޭ޺iK(-}8gj*.o'-caտs3x3~2'Ežw_ki3Cab/ȢVyILV=q1$'x[o׳sNp8غu+Vb˖-ۗ3gϺ4. L2&Mł ذa.d2… vieRYh`aɮ'){U#b>5FZF &\BZ_T[Ӵè^!YNTMCoc&WG!rn6~aϟONl6Wxd2Q\\ngдiSz͍7ȷ~[틸+Rzor-[F ۻt؊R2nw^K5LJJz˛o 3ѵhBT4j;:`?|f [4͇\yޣL R QHR iA b0O?#&DrEDD,ƍ믿f٤ѲeKj׮bt^vJ(((`˖-!FrQOۍ+X8u+BA,~p#q/"dŋNvv6֭#?????BBB ϯ/..&--All,ڵG%R/"_}v*BTTAAA@v;YYYdggCqq1QQQԬY6mP^= TTIzL[}ĦbҌ>̄]v9<X[TtuOg#9lYQ_/|ʘZ3bscLfm5g3qf6Kglw5㡇Pu%e2;*Of==͘; y:O9B$P#Fpu"wD OzX]p%9|S:j܂.mYÑbMw|^fMryiKM5#66j8nڑãL>-3L-"""rGOy'{ďdGTm("R-v///v{pu#EehmADD.W+\QI[֊He[֬YÚ5k*0"ʥr4EDjӈ<)!L_EDDDDD*SCDDMiD\s/""UF䉈ȥNI9/B-"R5 Mi)!ݍKCoӱucWc%6af`ٷxם.P""""""R5TJP4$q%`,ݙQ)Hrr`LX5]o]O?DXp AXYΟGd mfW3H?n%snz0 Zr liyguhBUrVn$R l[Ylۊ$&̌eOՋY=.ތ/[Ý' aMW6,4ם\v/,ۏD!XqDޞOv{㾐xkΞ8:<Ҵ׫oiIgCk8%}EDDDDD܎LvS̅]A\ogtُ!&]=x%PI>?RTl`2{zb$-˘ m` 5t ?UHFq3F- IDAT+H$>]O/{-w?y%Gj7+banJ ;p} 18v [y>Zu?DDDDDDW\?DGG*Of6؊k dVvl_#&..;\fj=b!0g-8*󓞞~(%%%l*e_&oDDDDDDDD""""""""R1%%=DDDDDDD-)!"""R ,͆ɼx]D󦤇\ܬW3z/|<.,M:ڴm,y̙ #[}C<#'K(O֫=msso9O"""&"""7^ 4ZNifV\vW\WB<2;X\!~3QfW?L"""%=DDDmy5w_Mz5H߾~ʲ ,u=^n<ЦYNs{Ư6)eP7-&ʄ;U%kt]Bؽd2o7sӽpyQrrt"""U]%=b+REl6W ""R&SZ-Kge#fTp?g'oa au9r0>)}''<z=[< epEY\6mgm-X#OMӶ80a mD5a`a펵Iio]b]Q-y.3{wSo|}!{ǯ&B<~I?WC}{6]^Q)9"""UL%=vHKKjuu""rzxwVj9MtԳ,気>c[UTGv}$nI:WvO0o ymS Iy&ʇ?`>Sۧ0A^Y#k8ԫ ;XYXw[n][o~ p&|Xri|K9֯xoADDu4EDDDܗ%>]#V/H` |Ts(;H0/5gGv?{<~ɶ8kVtxeǖ2:y<=OOu_I.4uu'?ABb2=A ;bYkۋ{RCDDDܔ1=1c˼9{l?ICxⱛ-l,RW1'.5G]}w4S6]5 lĒϷ=iqǭ/s1Կqdފd]ݍ<[㙓x7ߏxϒ*1EZ'Q DDD܅"""Lh]k}o36_+3X}Ӻ%`Hw<%isntt!;괤uKzdl7lOx2>l1+KȦi7KO"-<|k,?by8/\7;<Ƥ?=cۧvAa29nYb00KI6G,]-y㧇kI\O`'㘼6s=3Q42G'&Pt $yPo|/ϧ)n("""""" OzyiG(LF>,MNhɑkp N,x rԣ덃H u7a5 >Ky^Ɛ涡:uS@q/guDtڭ;pY&"2WHv`)Hbx]$_؜գ"?܉}t{k#,: bKqeB>xAtj%gNd׹> ։!3]?s)aOЎLKca.[""""""R*eMVKL>Ql hrKӚ8n&`Y?Gdc?ˤӔ 7O2qLYUH!فQ'>&B,XޙBg䀿$6X$fmQ׫ؒW:2 c !6,O$[7Appk'WSU9Y{*tRLB¶wZ:/o7>tD}ʝ={p'2uVxiWi߸!^k%wo)VQ˱zЭg?{2swz$VYyCa:~!E&y,""""""JKzX[ӹq0%&k4%H'G>)˦dz0 X>%;7{D\~D|h\ Ǒ4(&""""""'-܈` r:U%].KgZc-} vtk(=IQՀ[cI%}WxNG&_ۘM_˦S,f\7j$y\f7tT10› ƁYz۳`ڴ3m#<+> fM? SHv'dXO?6N//tiEDDDDDj*{Skn[rQ3mO̿k ~&`xh5}lg.\N"(..;\fj=b!0g-8*󓞞~(%%%l*xzAޥw)821uۼ\%%=DDDDDDD-)!"""""""nIIqKJz[RCDDDDDDDܒ"""""""▔d VԥlADDo=JAANաYf|||6*,cGRE]ZXVGˋL&0 Nff&҆Eѣxyy驄Ed2퍧'G6^AAK ` IAAA\[I9NH [KIqKJz[RCDDDDDDDܒ"""""""▔ OzXj4Ctҙq6h#U'tLTt$R|,Y%ciLxDҥiM74YR?Gdc?ˤӔ 7O2qLYUH!فQ'>&B,XޙBg䀰S^1-&(Ĩ[ """"""UI+iZN{wCY8䵓ë)*d:)N&!aEK9-zrgDcLUGiU7n״K ף?. )*60=Rfǹaf4:YRDDDDDDJܲ ?i+)Od9ӓH,kڃ\,ʒ=N5&0pb˻{D\~D|l\ Ǒ4'yٚ[#$%w66%Ǽk;:)""""""UY%oGp:Qݘ} vtk(=IQՀ[cI%}WxNG&_ۘM_˦S,f\7j$y\f7tg(1b_Bno'fDDDDDDbSIqof~vqs₳$gDDDDDDR[ liyguhBUrnd3ٿ;L_!'ԮA#س7ЛЦQ LMfCb*6eU*-s++R}[?ĄIz9GśEx !*FX u\—㺓nㅅ6|b K6Μۓɮs}bCg.c,LiXǘ>gn0g~ ©9螈\T*=鑟;vaEE ]-4YyzmG BWУeM|JG4&gs҄&mՁ&A#lYF WKӚ8.#"Ty'{i#^f3{9v2WFdt>{k/ux`OLX8ZCoĴ%AQ gg‘JZVq44[$0Z,ymyAqF66?G9VE@h >4oQchE51&ouc\ϓ`FY~kHyy`,\yuAd f'K9-zrgDcLUGiU7n״(bd- XW+ 1"""""".޽ńl:`IzKQ  D`<`6cvP0Y` GVHr6a?;SOs{mO"k`99|(S jrO_HQL}FhAd7+}A"sTߊJNz8X#6֊>W5'Ç:؂٣)!^b6c„ĂNa 'p^^\,ʒ=3^c"8m*ӽ{AFV.Np̰ T'<#isYc/͑:# vndJ xX EQQ1be°t;6]iTpr48V̞aoVci=ҫ;Xݚ΍ҙM;Tqaюnu Rų')^p },J $;붢}kٔzjYl8F$ozج5\kfhp2wG :)xj6YzoDDDDDDU!M{qM?K SNxx^5O: 'im!D8dThI /+ZuY<6gkKa&Yl#73c3a  H>V4ZF_A”'~|yk+)>U˸YSjԤAk|cZ>_oW]({Skn[rQ3? lŵ[R2ppPd;N^A_Oґ"0۹-9n!$HHa&Zձ8MkH57\рjgO$Tmjm2(YTりeǎ$W!""gaٰZtnZ#%07G%"""r~D^0r6 eWrfle=Fβ9Orb_^ej9*"""""""ntk\%%=DDDDDDD-)!"""""""nIIqKJz\d,͆ɼx]&Ws.xu/gɈX\}7`"sp/4E9IIcaEaY0Giml gך?yjb^k`䤒|aSGFnf [ I.@8\lἠF~8ͻŻ tVDDΦ’qqui"l6CLԺ)^5E OdQ3:g>YNWX Bˬeԛavl5iwex%c/\~z?E2l@"wwGy#> Ief2׏;:֗9/)3?2ڃ=.1JxT KzؑTQ* ..0DD,.u{w7r?ʔ皲ywc1ě_NGƛA/lk(+y }e/?-u1r t@qVeB*ؒ5.^y^2[MW_o- zWf蕻yT[TK6=hr3|܋5~?ekQGeXz|-c;Cx~a8͗[Lvj >|)1{q6ٛG1~ԍw>85t},331 9. ->X`)y}`O/!2Q IDATlX]}D!xdO?u#9Qg 9xJ\g~pJ£\L!ԫ}?|S4e=yi9Ƽˏ{C\*&B`pm}">%gSc'_Wy|yrcm[c 5jy=7V~ʼq=i?P!qRB! ME㋁1:t; E=)k{囮C.ccxig tƽMʃ=‰iP}QqU:5UĆG[R]"{x MU}CJ^2B|4vA'kS84Њq\OOB@QaZCmi{冴k[=sD"Qr #b"'Ft~ B>GC9ʫ#d\9.G"I}Y5S?!Tb=y_B+gķ *@A!tA.J#It2"1Ť5?j^scS!D+ˉ>v|˔~HID!IC!/ ~)l:G̟_o`̄dBDϟPB2s iO|7r{=]6,@w;>\c&&DѽS[)SS 0ab[f-і>ͽw٠ΔӬ5#q ?睑Yc'kGW.oǴی60sF k1-MtBիmR*Ӂ1S;dGn'ꧩyoa +e!x̬DOO@777wsGcB! ѧp=B!"$$$( D^ʝѧ Y!B!BxC> B!B!Ic.B!B\B!B!^JRB!B!KIB!B!x)IC!B!/%)z!B!$E!B!B!B!B=B!BRB!B!^JRB!B!KIB!B!x)IC!B!/%)z!B!$E!B!B!B!B=B!BRB!B!^JRB!B!KIB!B!x)IC!B!/%@nϰհ'+k/=W>ij QuD{cB˃0 :!BAVccc}4etёߩ)7M !1!')S+G :ccB//gB!HDD...~=T%i;SFxaV=zY0 F 4jݚ2lǽ֟AWwy LU;<7kx,G>wz֧3+مMOaޱhiK8Ni 70gW{D2tz[^)sFp8E|6osDO㹣\:Ú< }9KTiW \OÜRW8| *Q&{-j4ֈ x;ɀm PS_ÿ.cEnp4Dz-kO>o䞗h,Ӟ61ys8 ۟e,QeϜ1+H?W0{^>U3K<e-lcTjIw̚'ZyIrE]گ 8iAuq_ 2sQ޺Щ2/}T؞_+iyI r_0},wm$sB#VˡڧB`@R(rBQT<A$+ҖYYd&CrgNqf**UBN:.J[Bȝ4E) sxvU8qc[_bRuK Zڼַ1YTH & 8@IhRVݹ8*FvV '8{'ŲeX*4*s߿OZy*8Bnq+$:EِkPiБ-A[Df7CMNll(i< %UyMO^2pzTh`ke)ե>bkr+(=.s6}eLFo2}ilU KL'M 2v!B!(^{~ti©TEؙsJ*II/}8d|:dG>\hxѡRur|.BT#*DΫ6ZMP)~É߰1$/QYi;0[[$T(:j4&6E=q/g'f]~w'b RݺY/ޕd.o}z@eMђPu!{#23ߢw 9IK 6 FbPYS$>][$s16rr(~g>b |Yh>6&J\* ,.fg.|7s۩ 1X6QLMRyŠSx'VvW 0ɲ +j;k١˵+Xj,_ی]z}QWت|ZhZI%9I~ 0ϸSՀ kˌ{YTV8?jAQRH|=T#HS\i<٬m ' N6> Fd*4:K4B?dRgRQy^*IDGz<)KLŪvtzQH)<CI6gkΏX~85Yb(BkGs1&1QQ:c%Bɶs-;G rl]!B! @=l[׊r!Z' $gR>jl+ӼCS\ 3ؕ^GcڷO]I%>erMez47BtmǒԲ.Ws18zvj2Tqߠ:x4oE V Y5k3&܍`R;apa,wm*O62 s{)B!ә浇S7#ū\n++XVƷ[ uYT [WI̋ZQQaNi]L}Ӹ9yn{3/Ou%l#+`R ؽC hKXD&mhU5A1|Ǐd2'_ Ǡ8D~9=^J>I=YB!BQ ѼU#ʖ+Br$oAڑ:&PnyKsJƘw}r.(SBt#Y*tyc|&r6fA_~PEJj4I 'MGg[S>yr25pZ_wj_OnljVQ7J|nsJX^{1cǦM}F.N3ZJ ;k̢AU'JU\fNvLy%(4W G|%\&呗%:Nۜ}(Wwɼ=-c(&N7\!wBO~߶kLcxr}8}kAr|z؅B!`x▕OiB%)h:1лٷz +O&.yoEʃn_<矔[yPaii*?ODOiӍ7nRX)Gt;V,g۵xa~{%:x:ݼ)1󱊘ѤB)\I4 3Hv`lۖKd I1ܻd=+ʺa&$k.fWx>03bcӬ d5#fWO*M״y )ɮG.ecubc`ܚO>S-= u<ѧ}+T0>Rrk7O/v!B!(f<==SD~+r(s1T{m$8;fٶ4:Cƿ˼+Ͼȱ !^˟*B!ċ*((%JHHHP@@@LOM#t+݉_SDyE]!BB/W/rǮZ"yz.F>^؅/#˲ ԙzKQVO㬙 e|֦;uઉ6 p9?AR =UB!H.ݻF 6m!::ڬv-B!YghZʣgVb*:ӽ5ŏ#\Жb~Nt2Unz!xEGGsMZjEٲero޽f< Y BTe*xW';)1G)֬:g"3+Bڃ- }B"8v8-FQrEaѢ;vD!B?P_`O4ۢU6𰹴8`5Et EI,L!c 6*xG۞rB!_R4aH<…G!>! {Ǐ=8`I  y<BX=Ky+x!BTŚ3˱wfDm s_LP¥Vw8x!.Bh29Ɯ)`B!D\\vvvf-݉)3S>"E/;$$$k?Z!B)^{ZS깳n<#~޾ ] O:?ÊDaoB! .B!^x=B<*B!^4.!gmmMjjC!O 55Bi[B!x988Hbb"Y#B3 HLL޾P!_oB!KŅu(B!0-...־=Bpqq)?Bb)Dž  Y!BճVt[(nʂVp.jtcp4Pjqx<~GRs]N!ooM]LJp_̙'[jzjdnMx>P3~W+wX`xXUȈ!]_biD8_?暃' OSk2uornqi0;Qdza8qGǙcu1zxWz;K 5̛+uW]; oּ䵤ac[>噌[ph$|v ب@Q0%vKےHʻ !B!svrpܤ IDATpoggWFCBBpqq+'dT^WTTnۃ#ٻjwkb E^-qw3M@1@Ig]KrQy 5㡬0 &uRȉջw l7LҜj†- 4S_c=ctmՍǸox\IsbӶNkB&ֽ֔7,_{{hsoSmӵ-/XQyk[t:%}Ju$xzWEdݑ>(S]tȃck㗖t;ObЋu@av ۳C!"YyPFF6\X8Y8`.tƒms-uh4r6#M޾TՓ[rj|=h~b{=_!1\v;êp&r4kh~ _pA-[PQ\2yDW@ӊnئsc<>&RS}}D[*SCiþKL=cj&vܷq:Vے3f);];P|JJc*}غ?)֤9-01Ge] ߇F\ܖi" `Ww#9  eq¾ӹJ`wH~9{܃{X8C1`||=gl7tؿ GC!1"dܹ}=.Laǽu;/s|w:ӚAɤk0uʺM$.Ϙ'-!Bd3=jWKȕ AjO*մ̈ƉѼmO+eeO\>ۋԯ&1,Z;ǜiqkG>r5,IYyk{ڡlżkY>e~}L1&t[s$e*xNv 4<}5嚃'݋O ׵\[+* _gcs䖖C`d:Kl[D̘reR/0͚òT8O{yv_ Fր*[iG#D1$pnGӆS%l?M͟ }dhtmuQq*Ԛceb?Ee*$kf֢=D~.B!?{JwzwE$>}D,H :Fv*P :L:cm|;آіIuh׿>~vCjr(glh3=`¢s$|s1F惣霄v V x[<:]k_scq[?3]yms11Sv"]Zo|_ʵWMT*;5yϱ)Xd߄z$i6%bY<\};ҰU~v>B=ЕY _jjR Ks"ol 9ʟ篐 i+XFNDӸq4dQ{u+&E ULAօWgD)XYۙnd|uT%+T.Λ6!B! S*zODE 1SG[H!4An[i vTh؝Gcp;c⬟D ;l5eW>VczⴂKnh $aRI+Bɼ%RdީƖY~8TE KTZ ܫ֤Z?wM_}|3%evxksMB|b1z.3D{!7-brn_:>ix>hwCSZ<1)9o&~Dz.`FJ0?t܂.wA:S ѵoNX<t$rJ1<:E2i *whh1RDx9+Ȗ":>'g !B:TmqR5EkW]ϕsY[K~%޸^6}l^m?1T\Y @Z2I)zB0عQpQ?N0Ū[ǚl~a6_,V[3g͈qsWN7ST]f~HGŷxz^~f}m{X䶭&}$py4FB۶];D98wcTiowS㹾oEZiXOhdl]7g[AxFnXd,1 -ZJeG&3~ W43NbP0Eg=^ ‡]]s߇v<]!B}𦿶MgnOE}%:LiwBcӰl@>8ր^ma&]h_0z;Kӵ"qg~@=k8?EKH-gy)"af<>zK<Ӿ:5C'՟.+RA}?UaQ4q \M \9dkD^~ZPg\1;۶2LR.Юn "AD\6 `rr]'ñ8Gy14uk?E$yWDN )\ѵuÉҵiPWEl).ٞr(cjyÿgUO6F™|;k#)^m *6nC )oCڀl8v˦Ʀf'zHß}}Ϡ-Cƶ\{y$"P/]vEXEx$ۢY[кuK(x>}5OtL6ObbgGmY =v}RפK=k:K'd瘞cɷNr1څJķ/k{y3r,*9lkshӈТEQQ q6lCǎ]<ӿOg榻^- *6nM(oٞxpnEQezv[Iv;kxnAۮش nQ\;t @c >jhح`ZTķO#TlDkVhTҶlZtHxpQŨݪ[צ* qW ڄv]:Т *{QDžjHAOO !yeO֚ug'p*T0ww!xXNe$oʜ t}W]2jEX)pujԨB!!$$$( D^s"4m_ 3zk\ R^Z?,B!B !!B! = $E'?c?B!B~V!B!iB!B!^J/dâ[͌^ j,޳靬 ]|/ʚY(oCs<{|AgA󼜫5RP}o;OR9ϳM]S>k'Ģ0~ƻ@,qB!x<]|j.gB]3[?.g6fvoXuWݶ%o#5s\8T?;=Y8֪BGF3k7szV<U ܶ*?ek}r}ޟZv=}n\?Usۏdl߰?F _ 5. ŢUlޱui*=eC0g~L};fּC B!(pOAJҊS߷.318-FQGl ;'3V4(UԂ'8x- lj11JBdZ!Ț}Wo%Pf=_OS7{NxF(V:]ɔb1y aXҔ="H+<w1Qe6؁ߤ̟ܵ~ <ѻ|v7?k:2ДSp/~z u!eOķk?_*>7;J6y?,&B! S.z8ڷv{] s )}t;3ݰM %+Kh vwd@.B}hK"}hTm=mY&k8 uKE,7/e;ta}J{㪉|.e끮kLމ:eq&regg }gMW3{s ]5}6빱j$T\mK҉*W=a}ǰyQ]WMWl(uiۨ2:^?`Q{8?~/"P{O}=<7_Tćt*85HY8ٰoBZ)z~o{w;"|:n/-QX%rqb6A2oZxg儢&旑%Y|Pjʣ #ʬVjNʘ0V5o~;7W}Ȇ 20`,Ѕ^Xr;\-|2u.Ϡߔ]$m>cŇ}C}Yf¨>7jƱk e(_䝏R6 [ę?14nCyJU.L[գ03VK1+n/Ň6#1Kj|Ql9Nq^|x:|̈s5RJ >T,=+PM ܖ J6~>?oxz |3kQSrdtmKڑF,n6OG0Mm$bk{ڡlżkɏiGw/R#@zg 8ګ36F <B!/x-\f`br&ԗ>-qصo:`_;O?̢9 qiX*; !K,a/%O$puVnMNѭ D<SH^\WIU[2BU[9bE¹8Gznlҳ0;z["X)JӫYz‡7W†s\}KϺ\>'<~D?qcmfHOp֋iڻ ٴ'G]z)o̊{X^vD_ήlDȭߩןl*G?.#by6v6>3;NیM})ͫ[sc5O :Fv*P :Lkeݪ[5~ ?`fʬX%ۨ='&%Mp.1Gjkm}$?,t90k"]Zo|_ʵWMT*;xo{^Ū_7r" UƍРwd}OI&KjJ7@"WcE2fVԷ-lX6Pǔs%.?͜/kV0a9ٌۦǿHϷsޔs !BȞ^CS.-+bea}xYoAk(.)Шܟ 7yx! XTU(Ͷ2i *+GNnh,uU7нqe9RZZ3iaF$ěȁ!4ZГ':JG[H!4AR/X@Z7m)-F1ѧ-L ;w*4ۣ1i|8o~psڰucchukW2v#'Cr9ɇSZf"=]g0F~O%\z4yk6{)G{̘y|\ͷ>B1OjĘtwBe%Ss>='2+>-p7T4BK9gk'T)gʿ\6u2(bJk{՚T ҝ!h)Q 2?OyqA!Ԋ5;3+`'4y4o̙DvI X vnxU]P7g[Sl5v೤JThzh(?>>sA}gWM 2ާĠ`@X4y;ըUuѿ*{^s Gc`PRs}?uV>Nonl.o}>J6tC}+j֮ޟ=}QmGnӭcKYV40Kަ#cKyaya@nc'亍=8v0q%s$9-Zu~XyT KTei'2Wkv8bg!|A?F ĩُQe[cV[f#dlR$㟤>Fdl_yc.99WnG*xo/e} kQqQVpJ!/r^8jxټi3gLz}-¤sa{A!eV4ؐpl:5E{^2~(!!ڱ"ԧcG8Q`_6 ꪈ 9ťG*υ^#(֟'ɻ=%rrB `/z \8LX`PaVV=3m iNc)~HlCnh ĩAs4XTȄ sSU ; ˲W gc|݂ϓR-}khGc3x \uߛq]r(svOӦ.p!ףs:h+ϝ ζݾ2^Jt[߱1_#az [8CٹۍЯȥ IDATƦaـN5,}\9ŃrC_+Q%|٣阻^{;gKݥ!}2~DiKѸ۹u'wJ\|p%%z<֯1Ff F 4Nkؑe8i֔L3繹sg{D.m˦p\3#ƀi,'tPM7}l9^(_"\Gj9HD!DDe<_Wkfe\^Ic"ksu瞇-#%kRB!K=ZЮGvq<'+>ynݚ>Ӿe=5Pn߆}5Fueʴ֜_{܄!p-_Ma i8>l Vq۽B-id|r#*a09bpM>ifeCԔl.[=J:w͐Mf~.LJob¤dB#x0l|oo%pXw:G\uFn#8DrĚL}C b8sf1Utcu9OM?LZT4͔a{2ΐ@ov~5"~ùyzE$ޯ;9|?UαwoL>rDvWNwZ!!>n/ OV3@sc?v-`;:7t E)A@AAT@@QW Q A v E. "%H!}9i}I;3n3Q1UujN]0&sZ&=7(O7O|}pJd>-[cd <#6N-II;')%TkF&9T/É65}6%i""ەV#[gB>Wd~dOJ#1Vk&[I?M}?HfӜ *)S;Zjُ*<=e#v_>u+p%gn'o(j)c9d4=3co{I.)ʱ_cm(*rkL]z2pqHX;vڵkt""""]:wof[ G^_2Uؓr[S2iIQ{u """"=2ڂksvd|3ӱ2/Տz [6n2sVԌE|>Lmk˟ݺ%"gNL`,G)myٱkVkug,\,byö}Ji$+tkvdleE<]{vF.Z3hLXMX϶ &4i&[~bҶ*986llK~/P3kj6ŏU bD{Pɳ1DDDD((5dĚߓpgDUwsw)Q$1ҔracgJݺ:&Yx2 =ǼEz>ąܶЇr`6,Z֛ߍb{?_ι{de_yͦ-[ ,;ǩ-\iح \ٺl=Ahl'^ą>fo&oH-mǻ(w߭!  ]ƖmmExxF=v\,9l|?NDDDD|+z3{NsãFumc1ns3x;;ջŊp L!.n8qv]k<ÐA]x sa6͞ά=wy:`kG3Vw [[՗ߠ{{)LclC^Dt[^{ToՃF=%g2cxéZ<:Jþ27tf.\ CX2ԍV3 =?8h,h_qN߸Nƌ7bՕo<=Htpy(}V]9|SH/)(ݼp2Ϗe ^<; ^-+{eP6Խ^xla9В>'}ug Ba|l{n1{r""""-gz8xSY6T$)x-`\js#&ordkDa|0dsޝП*.ዥ~^>~X2[uT?:Kt:Ͼ:k 3M+IXbL~uz6aؔ>hTJ &q\+ǰrgِA Tu!{îmŽGԳ5pJ|0r|_ZżiǠFGz?@MNbJ"51&Iɟ[|i5C9[G ]GW&b2SvDwն\pˊm7U qCVNw?gXR{q#c$eJ ?&ck6nǛ=ǹaK8opmǸhmGe0K9vLLiţ K0`0neFZ.TԑK08<3dnMjQ o̪ic|6#} ai:~"6OǞs-i9& w4oّ~_O0oMo/޶}cHH"ꄧoMs$hv :7CwWܛaP"bRyQjmS/3n~6ebKbX V.)h7/-KyUN>5\%Fp>(լݟHn\KZv~j*֜`9G;9XҹStӁK'r_z y8L5z2ǽ}?!?PAtgnM>\\br`̦]woDsa`s6;ÞqӾ0Unmh~_%Q2QL{ zumO떭p:67ñ!ydYVbWgYxxwkMy7γ[P\psuj $x֧ު4'eK M^o2^3:IJVD٥p<2ץL"Q=X,gXJNx C٤%<}Y^d>S[D SWstKM^ҸXs>dʪ n5w=<\LV!u{ɠuaNB8ܒ̮-~d℥ј>C!o ՚ɖE9ȳҕ{kqP?j^Lgl~8c+OQ,6F }+}e]%` wȳ=S뢞 \7REyly58oML<6v8N MyGP>6Ώ;FڵX""""YtܹsWȞUS"Bwꙏr4nډ0k[Xڕ<>vS4(ŁŴ=ӂmSEFy+lǹHVċfN.E$Y͑^LX8SViO/c+cw~G(~~Oȥ}8-6EA\d7B6NqnEEDDD +[oosDDDDDDD.!"""""""v)ߊeLrwTZ ~m ڸN1,zL4IYѩ36gTu̽}w>a9#',9f+.\9gjqR5j)B؉?OY6DDDDD |+zϮcuu8%gՌ~Gεcp~h<1\; K⸱wO\btycޢk=S 4bR&vI6cث)圍~^o]דNAt}uF~Q\de!g9Ra~ya3*ʕz՟dvI\xc9JDDDDɷ?#xx}kU}(͉0M\ԁg?{6pX=Ѿ松zuĥ0s vV’BqM[)G8X)k)lmzaDm?`򻗊.s|Rc~ K9sVkǛo>G*c.pYX̀hxXG/|6q|W\Y:ҟ&[qG)Ӎ\\z M\ϰ.%ط;t7v*C3?gY^;wp$gt}6`Y)o`B5MDDDDR02i}yfh/+ٜw'羐 |1iߟ*KCTj3\>?wR II$O3h>71=*s-:]hY=WqkּA?jr%}Xo^Isl _;K閃y_ 2xTEۙSoJ8ņsn;£}T4pdoصVrq.*P\boXo$ '{L5믒X2[13s-Lo3hٗ~ }#}J'imZ;͆;Hu#Bv;J>͈_^.O$RCV.@ԫ>7ܩPULk<69"/rGOәy4<عd Ӎ_ʗqMpT  !""""RmJ5oN=#,:UA. 6I'e%nɣXDҰs<3+0s⧩|ڃ3| ~ ܹa! OSy,JвsJlcꎘq?}%oӈx]9b)YFޮ/n?#gx}:GC*ntko~ `8UKO6勥lZj9qzT|?/ pߞH{]9[qaKnEUVA7hsbC[?I2:g\ovV!vc\P/@nDDDDD$L#Kx9?$le̷&`%Wd>r2xfͪo- :ñ곴{?pM)1خ`~8G_#fO)"HrxnxzNDlk1ܺ2yMa<۬'m$;|1+owvPJe΀o9ۖpR4%(nG#j$o~?[͆k4Y S`T{)g>΃Y}dyr~B2/ҏ mlo6ď(rIDATc|/B!tWLX9<q<\w1ʔtȅ}8vi)+ѣ9ӹm^'h?7YLPNrfKn]ܑ?7G3h#puCnetΰ]ލ+ e2xPZ8w5T(zX ھ]_Į*y-ۼA/iCEjݓ߮xG2z)#a8k҇H9?g-`(ۖg+Ιup|{M;9ܥ]Hx>l!e{]/cq.u:t14#7Ŝv5_[OjoF3ļVߦ< __ȍv$V'<}kR!Nf_GS5"XTGr :Oy[>Adt/lj0M1Ƀ(wNk;+A[ƿ:H̪C$dxb~፩;waƟg|\Zf&cc{3>i[>gYZo/ر̠U2Ojj7i y5.0Y=Jcy +EDDDD\C`L Lz.17t`87Җ> %'L1ïgغ4]o$=i|sj8:g"W>#蜑1ib/5@Y{F9 m>^yM`//<;"""""R$NŊ :B- 0mZ_yMV UTȊ@BCCɓ!"""""^TTnnn8;;QjLP^mռDddd~WdWr3>L)qrr*0 ggg._zkd%Fɉ<ٷzADDDDD =łVC)lz5Yɫ92 y%=DDDDDDD.!"""""""vIEKzH.a 5˄7X21ƙ r@4#B"""""rg&u"/^pp/'qa|5']!szbZvkJa^" D$b8%ezȲ$]&:"А`CB &> v=}DDDDDDҞOE}7Z$r;ggCrΒSnӆGR \Ǭ :͚lBw\Crc zQ*=DDDDDb¶fW$%F}uW1d؏?Q/-S/'+IqDƓlq䊇FD\t4IXL+Nq 11'$b5Z /O7L KB F܋yj,ڹTCDDDDD Vg0l]b hч_dxxj$^lZnD\<DZ`gHt,N_\\c>N1Sw2]pcL[8cr`Nʼn#I&~?O`1cf|Gƽs5df(=T;ZՄ&:P iY1;܉2K`Ҁ ,Q19J8cD8Ue. xޓ~%*cDDo5U;3CvP<9st3qo1p>z}W/y^=cM,@I1O4ppu ar)MUiգ C<ɋ}!89UwmWx49s{rcg1v,'cLd%8G Rpzq!1* IշfB#c+{h&Os͗2lZ7ȺsY^iNeNFDa0\~odbտ%|ȳl(߫,G14EzwjDWnH"6"\3tmOaX^j5'1 x5)a3k _lt"9S?p㍾5|r;ntlA?/9b &ôy5%̟9JzMcp}֑VvNMCy~"kZ&w~}-'s~VN\KsʦS*T(SLFDDDDD$--k?o6fu'"fAAAΝ;RB"""""""bT%=DDDDDDD.!"""""""vIEKƂ@DDDDD$3ٌmmaXlʕ5Yɫyz$''tEFrr2nnnfMV򚒒[*zHE|| AntiMicroX profile AntiMicroX-antimicrox-2888bf6/other/io.github.antimicrox.antimicrox.yml000066400000000000000000000011561377703515000263520ustar00rootroot00000000000000# Maintained on Flathub at https://github.com/flathub/io.github.antimicrox.antimicrox app-id: io.github.antimicrox.antimicrox runtime: org.kde.Platform runtime-version: '5.11' sdk: org.kde.Sdk command: antimicrox finish-args: # X11 + XShm access - --share=ipc - --socket=x11 # Gamepads - --device=all modules: - name: antimicrox buildsystem: cmake sources: - type: git url: https://github.com/AntiMicroX/antimicrox.git # Build top commit of master branch branch: master # You can also set a tag and/or commit to build # tag: 3.xx # commit: xxx AntiMicroX-antimicrox-2888bf6/share/000077500000000000000000000000001377703515000173655ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/share/antimicrox/000077500000000000000000000000001377703515000215425ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/000077500000000000000000000000001377703515000242635ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/CMakeLists.txt000066400000000000000000000022771377703515000270330ustar00rootroot00000000000000# This will ensure that the *.qm files will be stored # in the right place within the build directory. file(GLOB antimicrox_TRANSLATIONS antimicrox_*.ts) list(APPEND antimicrox_TRANSLATIONS antimicrox.ts) file(GLOB_RECURSE antimicrox_BASE_SOURCES ${PROJECT_SOURCE_DIR}/src/*.cpp) file(GLOB_RECURSE antimicrox_BASE_FORMS ${PROJECT_SOURCE_DIR}/src/*.ui) if(UPDATE_TRANSLATIONS) message("Update translations - lupdate ON") if(TRANS_KEEP_OBSOLETE) message("getting rid of old text entries: \"lupdate -noobsolete\" ON") QT5_CREATE_TRANSLATION(antimicrox_QMFILES ${antimicrox_BASE_SOURCES} ${antimicrox_BASE_FORMS} ${antimicrox_TRANSLATIONS} OPTIONS -Inobsolete) else() QT5_CREATE_TRANSLATION(antimicrox_QMFILES ${antimicrox_BASE_SOURCES} ${antimicrox_BASE_FORMS} ${antimicrox_TRANSLATIONS}) endif(TRANS_KEEP_OBSOLETE) else() QT5_ADD_TRANSLATION(antimicrox_QMFILES ${antimicrox_TRANSLATIONS}) endif(UPDATE_TRANSLATIONS) add_custom_target(updateqm DEPENDS ${antimicrox_QMFILES}) install(FILES ${antimicrox_QMFILES} DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/antimicrox/translations") set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM true) AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox.ts000066400000000000000000021572511377703515000270250ustar00rootroot00000000000000 AboutDialog About About Version Version <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Copyright: 2013 - 2020 Copyright: 2013 - 2018 Copyright: 2013 - 2018 Info Info <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicroX group at https://github.com/AntiMicroX, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicroX group at https://github.com/AntiMicroX, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> Changelog Changelog Credits Credits AntiMicroX AntiMicroX About Development About Development License License Program Version %1 Program Version %1 Program Compiled on %1 at %2 Program Compiled on %1 at %2 Built Against SDL %1 Built Against SDL %1 Running With SDL %1 Running With SDL %1 Using Qt %1 Using Qt %1 Using Event Handler: %1 Using Event Handler: %1 AddEditAutoProfileDialog Auto Profile Dialog Auto Profile Dialog Profile: Profile: Pro&file: Pro&file: Browse Browse Window: Window: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties Detect Window Properties &Class: &Class: T&itle: T&itle: Class: Class: Title: Title: set partial title set partial title Application: Application: Select Select De&vices: De&vices: Devices: Devices: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller Set as Default for Controller A different profile is already selected as the default for this device. A different profile is already selected as the default for this device. Current (%1) Current (%1) Open Config Open Config Select Program Select Program Programs (*.exe) Programs (*.exe) Please use the main default profile selection. Please use the main default profile selection. Main Profile Main Profile Already selected Already selected Chosen Profile Chosen Profile The selection will be used instead of the all default profile option. The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Please select a window by using the mouse. Press Escape if you want to cancel. Capture Application Window Capture Application Window Could not obtain information for the selected window. Could not obtain information for the selected window. Application Capture Failed Application Capture Failed Profile file path is invalid. Profile file path is invalid. No window matching property was specified. No window matching property was specified. Program path is invalid or not executable. Program path is invalid or not executable. File is not an .exe file. File is not an .exe file. No window matching property was selected. No window matching property was selected. AdvanceButtonDialog Advanced Advanced Assignments Assignments Toggle Toggle Turbo Turbo Set Selector Set Selector Blank or KB/M Blank or KB/M Hold Hold Pause Pause Cycle Cycle Distance Distance Insert Insert Delete Delete Clear All Clear All Time: Time: 0.01s 0.01s 0s 0s Insert a pause that occurs in between key presses. Insert a pause that occurs in between key presses. Release Release Insert a new blank slot. Insert a new blank slot. Delete a slot. Delete a slot. Clear all currently assigned slots. Clear all currently assigned slots. Specify the duration of an inserted Pause or Hold slot. Specify the duration of an inserted Pause or Hold slot. 0m 0m &Mouse Speed Mod: &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Specify the range past an axis dead zone in which a sequence of actions will execute. Distance: Distance: % % Mouse Mod Mouse Mod Press Time Press Time Delay Delay Execute Execute Load Load Set Change Set Change Text Entry Text Entry Join Join Split Split Placeholder Placeholder 0 0 Set the percentage that mouse speeds will be modified by. Set the percentage that mouse speeds will be modified by. Auto Reset Cycle After Auto Reset Cycle After seconds seconds Executable: Executable: ... ... Arguments: Arguments: Enabled Enabled Mode: Mode: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Normal Gradient Gradient Pulse Pulse Delay: Delay: 0.10s 0.10s Rate: Rate: 10.0/s 10.0/s Disabled Disabled Select Set 1 One Way Select Set 1 One Way Select Set 1 Two Way Select Set 1 Two Way Select Set 1 While Held Select Set 1 While Held Select Set 2 One Way Select Set 2 One Way Select Set 2 Two Way Select Set 2 Two Way Select Set 2 While Held Select Set 2 While Held Select Set 3 One Way Select Set 3 One Way Select Set 3 Two Way Select Set 3 Two Way Select Set 3 While Held Select Set 3 While Held Select Set 4 One Way Select Set 4 One Way Select Set 4 Two Way Select Set 4 Two Way Select Set 4 While Held Select Set 4 While Held Select Set 5 One Way Select Set 5 One Way Select Set 5 Two Way Select Set 5 Two Way Select Set 5 While Held Select Set 5 While Held Select Set 6 One Way Select Set 6 One Way Select Set 6 Two Way Select Set 6 Two Way Select Set 6 While Held Select Set 6 While Held Select Set 7 One Way Select Set 7 One Way Select Set 7 Two Way Select Set 7 Two Way Select Set 7 While Held Select Set 7 While Held Select Set 8 One Way Select Set 8 One Way Select Set 8 Two Way Select Set 8 Two Way Select Set 8 While Held Select Set 8 While Held [NO KEY] [NO KEY] sec. sec. /sec. /sec. Not checked slots Not checked slots To delete slots, you need to select at least one To delete slots, you need to select at least one To insert slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Unknown current slot Click on chosen slots before joining them Click on chosen slots before joining them Not enough slots Not enough slots It's impossible to join slots. Add at least one other slot. It's impossible to join slots. Add at least one other slot. Not selected slots Not selected slots It's impossible to join slots. Select at least two slots before joining them It's impossible to join slots. Select at least two slots before joining them Only keyboard slots Only keyboard slots It's only possible to join simple and mix keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. It's impossible to split slots. Add at least one other slot. Not selected slot Not selected slot Select your slot before splitting. Select your slot before splitting. Too many mix slots Too many mix slots Select one mix slot. Select one mix slot. Only mix slots Only mix slots It's only possible to split mix slot. It's only possible to split mix slot. Empty execution path Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist File doesn't exist There is no such file locally, that could be executed. Check the file on your system There is no such file locally, that could be executed. Check the file on your system Set %1 Set %1 Select Set %1 Select Set %1 One Way One Way Two Way Two Way While Held While Held Choose Executable Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Choose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Execute program when slot is activated. Choose Profile Choose Profile Config Files (*.amgp *.xml) Config Files (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Stick/Pad Assignment Sticks Sticks DPads DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Joystick %2) Stick 1 Stick 1 Enabled Enabled Assign Assign X Axis: X Axis: Y Axis: Y Axis: Stick 2 Stick 2 Number of Physical DPads: %1 Number of Physical DPads: %1 Virtual DPad 1 Virtual DPad 1 Up: Up: Down: Down: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Left: Left: Right: Right: Axis %1 Axis %1 Axis %1 - Axis %1 - Axis %1 + Axis %1 + Button %1 Button %1 Move stick 1 along the X axis Move stick 1 along the X axis Move stick 1 along the Y axis Move stick 1 along the Y axis Move stick 2 along the X axis Move stick 2 along the X axis Move stick 2 along the Y axis Move stick 2 along the Y axis Press a button or move an axis Press a button or move an axis AxisEditDialog Axis Axis Mouse (Horizontal) Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Vertical) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Up | Down Arrows: Left | Right Arrows: Left | Right Keys: W | S Keys: W | S Keys: A | D Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 NumPad: KP_4 | KP_6 None None Set the value to use as the limit for an axis. Useful for a worn out analog stick. Set the value to use as the limit for an axis. Useful for a worn out analog stick. Negative Half Throttle Negative Half Throttle Positive Half Throttle Positive Half Throttle Name: Name: Specify the name of an axis. Specify the name of an axis. Mouse Settings Mouse Settings Set the value of the dead zone for an axis. Set the value of the dead zone for an axis. Presets: Presets: Dead Zone: Dead Zone: Max Zone: Max Zone: [NO KEY] [NO KEY] Throttle setting that determines the behavior of how to interpret an axis hold or release. Throttle setting that determines the behavior of how to interpret an axis hold or release. Negative Throttle Negative Throttle Normal Normal Positive Throttle Positive Throttle Current Value: Current Value: Set Set Set %1 Set %1 Left Mouse Button Left Mouse Button Right Mouse Button Right Mouse Button ButtonEditDialog Dialog Dialog To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Placeholder Placeholder Toggle Toggle Enables a key press or release to only occur when a controller button is pressed. Enables a key press or release to only occur when a controller button is pressed. Enables rapid key presses and releases. Turbo controller. Enables rapid key presses and releases. Turbo controller. Turbo Turbo Last keyboard/mouse button: Last keyboard/mouse button: Slots Slots Na&me: Na&me: Specify the name of a button. Specify the name of a button. Action: Action: Specify the action that will be performed in game while this button is being used. Specify the action that will be performed in game while this button is being used. Advanced Advanced Choose your keyboard key Choose your keyboard key No button No button Last button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice No choice Before you open window with advanced settins, you have to choice a key Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set As last gamepad button has been set Index %1 Index %1 [NO KEY] [NO KEY] Calibration Form Form Start calibration Start calibration Controller: Controller: Sticks: Sticks: Use settings from jstest-gtk Use settings from jstest-gtk Reset settings Reset settings Cancel Cancel Save Save Calibration Calibration Do you really want to reset settings of current axes? Do you really want to reset settings of current axes? Do you really want to reset settings of current axis? Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Calibrating center Start second step Start second step Center X: %1 Center X: %1 Center Y: %1 Center Y: %1 Place the joystick in the top-left corner many times Place the joystick in the top-left corner many times Calibrating position Calibrating position X: %1 X: %1 Y: %1 Y: %1 Place the joystick in the bottom-right corner Place the joystick in the bottom-right corner Start final step Start final step range X: %1 - %2 range X: %1 - %2 range Y: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone X: %1 deadzone Y: %1 deadzone Y: %1 ---Calibration done!--- ---Calibration done!--- Calibration values have been saved Calibration values have been saved Dead zone calibration Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Do you want to save calibration of current axis? You must move X axis to the right at least five times! Keep moving! You must move X axis to the right at least five times! Keep moving! You must move X axis to the left at least five times! Keep moving! You must move X axis to the left at least five times! Keep moving! Axis %1 Axis %1 CapturedWindowInfoDialog Captured Window Properties Captured Window Properties Information About Window Information About Window Class: Class: TextLabel TextLabel Title: Title: Path: Path: Match By Properties Match By Properties Class Class Title Title Path Path Full Path Full Path File Name File Name DPadContextMenu Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Standard Standard Eight Way Eight Way 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal Mouse Settings Mouse Settings DPadEditDialog Dialog Dialog Presets: Presets: Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Dpad Mode: Dpad Mode: &Name: &Name: 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal DPad Delay: DPad Delay: Time lapsed before a direction change is taken into effect. Time lapsed before a direction change is taken into effect. s s Specify the name of a dpad. Specify the name of a dpad. Mouse Settings Mouse Settings Standard Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way Eight Way Set Set Set %1 Set %1 EditAllDefaultAutoProfileDialog Default Profile Default Profile Profile: Profile: Browse Browse Open Config Open Config Profile file path is invalid. Profile file path is invalid. ExtraProfileSettingsDialog Extra Profile Settings Extra Profile Settings Key Press Time: Key Press Time: 0.00 ms 0.00 ms Profile Name: Profile Name: s s GameController Game Controller Game Controller GameControllerDPad DPad DPad GameControllerMappingDialog Game Controller Mapping Game Controller Mapping <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A A B B X X Y Y Back Back Start Start Guide Guide Left Shoulder Left Shoulder Right Shoulder Right Shoulder Left Stick Click Left Stick Click Right Stick Click Right Stick Click Left Stick X Left Stick X Left Stick Y Left Stick Y Right Stick X Right Stick X Right Stick Y Right Stick Y Left Trigger Left Trigger Right Trigger Right Trigger DPad Up DPad Up DPad Left DPad Left DPad Down DPad Down DPad Right DPad Right Mapping Mapping SDL 2 Game Controller Mapping String SDL 2 Game Controller Mapping String Last Axis Event: Last Axis Event: Current Axis Detection Dead Zone: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Game Controller Mapping (%1) (#%2) Discard Controller Mapping? Discard Controller Mapping? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. GameControllerSet Back Back Guide Guide Start Start LS Click LS Click RS Click RS Click L Shoulder L Shoulder R Shoulder R Shoulder L Trigger L Trigger R Trigger R Trigger GameControllerTrigger Trigger Trigger JoyAxis Axis Axis JoyAxisButton Negative Negative Positive Positive Unknown Unknown Button Button JoyAxisContextMenu Mouse (Horizontal) Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Vertical) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Up | Down Arrows: Left | Right Arrows: Left | Right Keys: W | S Keys: W | S Keys: A | D Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 NumPad: KP_4 | KP_6 None None Mouse Settings Mouse Settings Left Mouse Button Left Mouse Button Right Mouse Button Right Mouse Button JoyButton Processing turbo for #%1 - %2 Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Distance change for button #%1 - %2 Button Button [NO KEY] [NO KEY] [Set %1 1W] [Set %1 1W] [Set %1 2W] [Set %1 2W] [Set %1 WH] [Set %1 WH] JoyButtonContextMenu Toggle Toggle Turbo Turbo Clear Clear Set Select Set Select Disabled Disabled Set %1 Set %1 Set %1 1W Set %1 1W Set %1 2W Set %1 2W Set %1 WH Set %1 WH JoyButtonSlot Mouse Mouse Up Up Down Down Left Left Right Right LB LB MB MB RB RB B4 B4 B5 B5 Pause Pause Hold Hold Cycle Cycle Distance Distance Release Release Mouse Mod Mouse Mod Press Time Press Time Delay Delay Load %1 Load %1 Set Change %1 Set Change %1 [Text] %1 [Text] %1 [Exec] %1 [Exec] %1 [NO KEY] [NO KEY] JoyControlStick Stick Stick JoyControlStickButton Up Up Down Down Left Left Right Right Button Button JoyControlStickContextMenu Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Standard Standard Eight Way Eight Way 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal Mouse Settings Mouse Settings JoyControlStickEditDialog Dialog Dialog X: X: 0 0 Y: Y: Distance: Distance: Presets: Presets: Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Stick Mode: Stick Mode: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal Dead zone value to use for an analog stick. Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. The area (in degrees) that each diagonal region occupies. Square Stick: Square Stick: Percentage to modify a square stick coordinates to confine values to a circle Percentage to modify a square stick coordinates to confine values to a circle % % Stick Delay: Stick Delay: Time lapsed before a direction change is taken into effect. Time lapsed before a direction change is taken into effect. s s Modifier: Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton PushButton Na&me: Name: Na&me: Specify the name of an analog stick. Specify the name of an analog stick. Mouse Settings Mouse Settings Standard Standard Bearing: Bearing: % Safe Zone: % Safe Zone: Eight Way Eight Way Dead Zone: Dead Zone: Max Zone: Max Zone: Diagonal Range: Diagonal Range: Set Set Set %1 Set %1 JoyControlStickModifierButton Modifier Modifier JoyDPad DPad DPad JoyDPadButton Up Up Down Down Left Left Right Right Button Button JoyTabWidget <New> <New> Remove Remove Remove configuration from recent list. Remove configuration from recent list. Load Load Load configuration file. Load configuration file. Save Save Save changes to configuration file. Save changes to configuration file. Save As Save As Save changes to a new configuration file. Save changes to a new configuration file. Sets Sets Copy from Set Copy from Set Settings Settings Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Stick/Pad Assign Stick/Pad Assign Controller Mapping Controller Mapping Quick Set Quick Set Names Names Toggle button name displaying. Toggle button name displaying. Pref Pref Change global profile settings. Change global profile settings. Reset Reset Revert changes to the configuration. Reload configuration file. Revert changes to the configuration. Reload configuration file. Open Config Open Config Config Files (*.amgp *.xml) Config Files (*.amgp *.xml) Config File (*.%1.amgp) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Do you really want to reset buttons settings for joystick? Save Profile Changes? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks Sticks DPads DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 Set %1: %2 Set %1 Set %1 Copy Set Assignments Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Are you sure you want to copy the assignments and device properties from %1? Save Config Save Config Set Set Joystick Joystick Joystick JoystickStatusWindow Properties Properties Details Details Name: Name: %1 %1 Number: Number: Axes: Axes: Buttons: Buttons: Hats: Hats: Battery: Battery: Unknown Unknown GUID: GUID: Game Controller: Game Controller: Axes Axes Buttons Buttons Hats Hats %1 (#%2) Properties %1 (#%2) Properties Axis %1 Axis %1 Hat %1 Hat %1 No No Yes Yes MainSettingsDialog Edit Settings Edit Settings General General Controller Mappings Controller Mappings Language Language Auto Profile Auto Profile Mouse Mouse Advanced Advanced Profile Direc&tory: Profile Direc&tory: <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> Recent Profile Count: Recent Profile Count: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> Gamepad Poll Rate: Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Hide main window when the main window close button is clicked instead of quitting the program. Close To Tray Close To Tray Have Windows start AntiMicroX at system startup. Have Windows start AntiMicroX at system startup. Launch At Windows Startup Launch At Windows Startup Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Single Profile List in Tray Single Profile List in Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimize to Taskbar Minimize to Taskbar This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Hide Empty Buttons Hide Empty Buttons When the program is launched, open the last known profile that was opened during the previous session. When the program is launched, open the last known profile that was opened during the previous session. Auto Load Last Opened Profile Auto Load Last Opened Profile Only show the system tray icon when the program first launches. Only show the system tray icon when the program first launches. Launch in Tray Launch in Tray Associate .amgp files with AntiMicroX in Windows Explorer. Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles Associate Profiles Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Attach the numeric keypad Combination of keys for quitting app Combination of keys for quitting app Choose keys combination Choose keys combination ! restart is needed after choice of combination ! restart is needed after choice of combination Key Repeat Key Repeat Active keys will be repeatedly pressed when this option is enabled. Active keys will be repeatedly pressed when this option is enabled. Enable Enable Specifies how much time should elapse before key repeating begins. Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Português do Brasil Français Français Deutsch Deutsch Italiano Italiano 日本語 日本語 Русский Русский српски / srpski српски / srpski 简体中文 简体中文 Español Español українська українська Polski Polski History Si&ze: History Si&ze: Weight Modi&fier: Weight Modi&fier: Log File: Log File: Log Level: Log Level: None None Error Error Warning Warning Info Info Debug Debug Note: To see the change of log level in console output (not in log file), application restart is required Note: To see the change of log level in console output (not in log file), application restart is required Reset Reset Class Class Pro&file Directory: Pro&file Directory: Title Title Program Program Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision Disable Enhance Pointer Precision Smoothing Smoothing Histor&y Size: Histor&y Size: Weight &Modifier: Weight &Modifier: Refresh Rate: Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Spring Screen: Screen: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: Accel Numerator: 0 0 Accel Denominator: Accel Denominator: Accel Threshold: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Reset Acceleration Delay: Delay: Profi&le Directory: Profi&le Directory: ms ms Rate: Rate: times/s times/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. GUID GUID Mapping String Mapping String Disable? Disable? Delete Delete Insert Insert Default Default English English Active Active Devices: Devices: All All Device Device Profile Profile Default? Default? Add Add Edit Edit Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Select Default Profile Directory Select Default Profile Directory Are you sure you want to delete the profile? Are you sure you want to delete the profile? Save Log File As Save Log File As Log Files (*.log) Log Files (*.log) Do you really want to reset setting? Do you really want to reset setting? Would you like to reset mappings too? Would you like to reset mappings too? [NO KEY] [NO KEY] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu If events are not seen by a game, please click here to run this application as Administrator. If events are not seen by a game, please click here to run this application as Administrator. &App &App &Options &Options &Help &Help He&lp He&lp &Quit &Quit Ctrl+Q Ctrl+Q &Update Joysticks &Update Joysticks Ctrl+U Ctrl+U &Hide &Hide Ctrl+H Ctrl+H &About &About Ctrl+A Ctrl+A About &Qt About &Qt Ctrl+T Ctrl+T &Properties &Properties Ctrl+P Ctrl+P &Key Checker &Key Checker Ctrl+K Ctrl+K &GitHub Page &GitHub Page Ctrl+G Ctrl+G &Game Controller Mapping &Game Controller Mapping Ctrl+M Ctrl+M S&ettings S&ettings Ctrl+S Ctrl+S &Stick/Pad Assign &Stick/Pad Assign Ctrl+X Ctrl+X &Wiki &Wiki Ctrl+W Ctrl+W &Issues &Issues Ctrl+I Ctrl+I &Calibration &Calibration Ctrl+C Ctrl+C Issues Issues Home Page Home Page Could not find a proper controller identifier. Exiting. Could not find a proper controller identifier. Exiting. (%1) (%1) Open File Open File %1 battery %1 battery Battery level is less than %1 Battery level is less than %1 Device number: %1 Device name: %2 Device number: %1 Device name: %2 Reading old profile Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore &Restore Calibration couldn't be opened Calibration couldn't be opened You must connect at least one controller to open the window You must connect at least one controller to open the window Run as Administrator? Run as Administrator? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Failed to elevate program Failed to elevate program Failed to restart this program as the Administrator Failed to restart this program as the Administrator Could not find controller. Exiting. Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Mouse Settings - Set %1 Set %1 MouseButtonSettingsDialog Mouse Settings - Mouse Settings - Set %1 Set %1 MouseControlStickSettingsDialog Mouse Settings Mouse Settings Set %1 Set %1 MouseDPadSettingsDialog Mouse Settings Mouse Settings Set %1 Set %1 MouseSettingsDialog Mouse Settings Mouse Settings Mouse Mode: Mouse Mode: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Cursor Spring Spring Acceleration: Acceleration: Enhanced Precision Enhanced Precision Linear Linear Quadratic Quadratic Cubic Cubic Quadratic Extreme Quadratic Extreme Power Function Power Function Easing Quadratic Easing Quadratic Easing Cubic Easing Cubic Mouse Speed Settings Mouse Speed Settings Enable to change the horizontal and vertical speed boxes at the same time. Enable to change the horizontal and vertical speed boxes at the same time. Change Together Change Together Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration Delta Acceleration &Multiplier: &Multiplier: Mi&n Threshold: Mi&n Threshold: 1 = 20 pps 1 = 20 pps Wheel Hori. Speed: Wheel Hori. Speed: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: Easing Duration: s s Highest value to accelerate mouse movement by Highest value to accelerate mouse movement by x x Start %: Start %: Acceleration begins at this percentage of the base multiplier Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Minimum amount of axis travel required for acceleration to begin Max Threshold: Max Threshold: Maximum axis travel before acceleration has reached the multiplier value Maximum axis travel before acceleration has reached the multiplier value E&xtra Duration: E&xtra Duration: Curve: Curve: Ease Out Sine Ease Out Sine Ease Out Quad Ease Out Quad Ease Out Cubic Ease Out Cubic Release Radius: Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Relative Mouse Status Mouse Status X: X: 0 (0 pps) 0 (0 pps) Y: Y: 1 = 1 notch(es)/s 1 = 1 notch(es)/s Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: Hori&zontal Speed: &Vertical Speed: &Vertical Speed: Wheel Vert. Speed: Wheel Vert. Speed: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Spring Settings Spring Width: Spring Width: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Spring Height: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. %n notch(es)/s %n notch/s %n notches/s ProfileImporter Form Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Cancel OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Key Checker <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-5.10/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-5.10/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Event Handler: Native Key Value: Native Key Value: 0x00000000 0x00000000 Qt Key Value: Qt Key Value: antimicro Key Value: AntiMicroX Key Value: AntiMicroX Key Value: AntiMicroX Key Value: QObject Super Super Menu Menu Mute Mute Vol+ Vol+ Vol- Vol- Play/Pause Play/Pause Play Play Pause Pause Prev Prev Next Next Mail Mail Home Home Media Media Search Search Launch program in system tray only. Launch program in system tray only. Launch program with the tray menu disabled Launch program with the tray menu disabled Launch program without the main window displayed Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value value Unload currently enabled profile(s) Unload currently enabled profile(s) value(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID Start joysticks on a specific set. Value can be a controller index, name, or GUID number value number value Launch program as a daemon. Use only on Linux. Launch program as a daemon. Use only on Linux. Enable logging Enable logging log-type log-type Choose a file for logs writing Choose a file for logs writing filename filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Daemon launched Failed to launch daemon Failed to launch daemon Launching daemon Launching daemon Display string "%1" is not valid. Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to set a signature id for the daemon Failed to change working directory to / Failed to change working directory to / Quitting Program Quitting Program # of joysticks found: %1 # of joysticks found: %1 List Joysticks: List Joysticks: --------------- --------------- Joystick %1: Joystick %1: Index: %1 Index: %1 GUID: %1 GUID: %1 UniqueID: %1 UniqueID: %1 VendorID: %1 VendorID: %1 ProductID: %1 ProductID: %1 Product Version: %1 Product Version: %1 Name: %1 Name: %1 Yes Yes No No Game Controller: %1 Game Controller: %1 # of Axes: %1 # of Axes: %1 # of Buttons: %1 # of Buttons: %1 # of Hats: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Failed to open event generator. Exiting. Using %1 as the event generator. Using %1 as the event generator. Could not raise process priority. Could not raise process priority. Last button Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Profile location %1 is not an XML file. Profile location %1 does not exist. Profile location %1 does not exist. Controller identifier is not a valid value. Controller identifier is not a valid value. An invalid set number '%1' was specified. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. Controller identifier '%s'' is not a valid value. No set number was specified. No set number was specified. No controller was specified. No controller was specified. No display string was specified. No display string was specified. An invalid event generator was specified. An invalid event generator was specified. No event generator string was specified. No event generator string was specified. No log file specified. No log file specified. Logging started Logging started Auto-switching to profile "%1". Auto-switching to profile "%1". Auto-switching to nullptr profile! Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set Quick Set <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> Quick Set %1 Quick Set %1 SetAxisThrottleDialog Throttle Change Throttle Change The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? SetJoystick Set %1: %2 Set %1: %2 Set %1 Set %1 SetNamesDialog Set Name Settings Set Name Settings Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Name Name SimpleKeyGrabberButton Mouse Mouse SpringModeRegionPreview Spring Mode Preview Spring Mode Preview UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Could not open uinput device file Please check that you have permission to write to the device Using uinput device file %1 Using uinput device file %1 UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z Esc Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock CapsLock ; ; ' ' Enter Enter Shift_L Shift_L , , . . / / Ctrl_L Ctrl_L Super_L Super_L Alt_L Alt_L Space Space Alt_R Alt_R Menu Menu Ctrl_R Ctrl_R Shift_R Shift_R Up Up Left Left Down Down Right Right PrtSc PrtSc Ins Ins Del Del Home Home End End PgUp PgUp PgDn PgDn NumLock NumLock * * + + KP_Enter KP_Enter KP_1 KP_1 KP_2 KP_2 KP_3 KP_3 KP_4 KP_4 KP_5 KP_5 KP_6 KP_6 KP_7 KP_7 KP_8 KP_8 KP_9 KP_9 KP_0 KP_0 SCLK SCLK Pause Pause Super_R Super_R Mute Mute VolDn VolDn VolUp VolUp Play Play Stop Stop Prev Prev Next Next [NO KEY] [NO KEY] UnixWindowInfoDialog Captured Window Properties Captured Window Properties Information About Window Information About Window Class: Class: TextLabel TextLabel Title: Title: Path: Path: Match By Properties Match By Properties Class Class Title Title Path Path VDPad VDPad VDPad VirtualKeyPushButton Space Space Tab Tab Shift (L) Shift (L) Shift (R) Shift (R) Ctrl (L) Ctrl (L) Ctrl (R) Ctrl (R) Alt (L) Alt (L) Alt (R) Alt (R) Alt Gr Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP PGUP DEL DEL PGDN PGDN 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK NUM LK * * + + Enter Enter Del Del < < : : Super (L) Super (L) Menu Menu Up Up Down Down Left Left Right Right VirtualKeyboardMouseWidget Keyboard Keyboard Mouse Mouse Mouse Settings Mouse Settings Left Mouse Left Up Mouse Up Left Button Mouse Left Button Middle Button Mouse Middle Button Right Button Mouse Right Button Wheel Up Mouse Wheel Up Wheel Left Mouse Wheel Left Wheel Right Mouse Wheel Right Wheel Down Mouse Wheel Down Down Mouse Down Right Mouse Right Button 4 Mouse Button 4 Mouse 8 Mouse Mouse 8 Button 5 Mouse Button 5 Mouse 9 Mouse Mouse 9 NONE NONE [NO KEY] [NO KEY] Last button Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Others Applications Applications Browser Back Browser Back Browser Favorites Browser Favorites Browser Forward Browser Forward Browser Home Browser Home Browser Refresh Browser Refresh Browser Search Browser Search Browser Stop Browser Stop Calc Calc Email Email F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media Media Media Next Media Next Media Play Media Play Media Previous Media Previous Media Stop Media Stop Search Search Volume Down Volume Down Volume Mute Volume Mute Volume Up Volume Up VirtualMousePushButton INVALID INVALID WinAppProfileTimerDialog Capture Application Capture Application After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Timer: Timer: Seconds Seconds Cancel Cancel WinExtras [NO KEY] [NO KEY] AntiMicroX Profile AntiMicroX Profile X11Extras ESC ESC Tab Tab Space Space DEL DEL Return Return KP_Enter KP_Enter Backspace Backspace Alt Gr Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput extension was not found. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. Virtual pointer found with id=%1. Virtual pointer found with id=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Changing mouse acceleration for device with id=%1 Changing mouse acceleration for device with id=%1 XMLConfigReader Could not write updated profile XML to file %1. Could not write updated profile XML to file %1. XMLConfigWriter Could not write to profile at %1. Could not write to profile at %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Launch program in system tray only. Launch program with the tray menu disabled Launch program with the tray menu disabled Launch program without the main window displayed Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value value Unload currently enabled profile(s) Unload currently enabled profile(s) value(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID Start joysticks on a specific set. Value can be a controller index, name, or GUID number value number value Launch program as a daemon. Use only on Linux. Launch program as a daemon. Use only on Linux. Enable logging Enable logging log-type log-type Choose a file for logs writing Choose a file for logs writing filename filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_br.ts000066400000000000000000012557471377703515000275200ustar00rootroot00000000000000 AboutDialog About Version Info Changelog Credits AntiMicroX <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> About Development "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 License Program Version %1 Program Compiled on %1 at %2 Built Against SDL %1 Running With SDL %1 Using Qt %1 Using Event Handler: %1 AddEditAutoProfileDialog Auto Profile Dialog Browse Window: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties Pro&file: &Class: T&itle: set partial title Application: Select De&vices: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller A different profile is already selected as the default for this device. Current (%1) Open Config Select Program Please use the main default profile selection. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Capture Application Window Could not obtain information for the selected window. Application Capture Failed Profile file path is invalid. No window matching property was specified. Program path is invalid or not executable. No window matching property was selected. AdvanceButtonDialog Advanced Assignments Toggle Turbo Set Selector Blank or KB/M Hold Pause Cycle Distance Insert Delete Clear All Time: 0.01s 0s Insert a pause that occurs in between key presses. Release Insert a new blank slot. Delete a slot. Clear all currently assigned slots. Specify the duration of an inserted Pause or Hold slot. 0m &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Distance: % Mouse Mod Press Time Delay Execute Load Set Change Text Entry Join Split Placeholder 0 Set the percentage that mouse speeds will be modified by. Auto Reset Cycle After seconds Executable: ... Arguments: Enabled Mode: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Gradient Pulse Delay: 0.10s Rate: 10.0/s Disabled Select Set 1 One Way Select Set 1 Two Way Select Set 1 While Held Select Set 2 One Way Select Set 2 Two Way Select Set 2 While Held Select Set 3 One Way Select Set 3 Two Way Select Set 3 While Held Select Set 4 One Way Select Set 4 Two Way Select Set 4 While Held Select Set 5 One Way Select Set 5 Two Way Select Set 5 While Held Select Set 6 One Way Select Set 6 Two Way Select Set 6 While Held Select Set 7 One Way Select Set 7 Two Way Select Set 7 While Held Select Set 8 One Way Select Set 8 Two Way Select Set 8 While Held [NO KEY] sec. /sec. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Select Set %1 One Way Two Way While Held Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Choose Profile Config Files (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Sticks DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) Stick 1 Enabled Assign X Axis: Y Axis: Stick 2 Number of Physical DPads: %1 Virtual DPad 1 Up: Down: Left: Right: Axis %1 Axis %1 - Axis %1 + Button %1 Move stick 1 along the X axis Move stick 1 along the Y axis Move stick 2 along the X axis Move stick 2 along the Y axis Press a button or move an axis AxisEditDialog Axis Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Left | Right Keys: W | S Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 None Set the value to use as the limit for an axis. Useful for a worn out analog stick. Negative Half Throttle Positive Half Throttle Name: Specify the name of an axis. Mouse Settings Set the value of the dead zone for an axis. Presets: Dead Zone: Max Zone: [NO KEY] Throttle setting that determines the behavior of how to interpret an axis hold or release. Negative Throttle Normal Positive Throttle Current Value: Set Set %1 Left Mouse Button Right Mouse Button ButtonEditDialog Dialog To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Placeholder Toggle Enables a key press or release to only occur when a controller button is pressed. Enables rapid key presses and releases. Turbo controller. Turbo Last keyboard/mouse button: Slots Na&me: Specify the name of a button. Action: Specify the action that will be performed in game while this button is being used. Advanced Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 Calibration Form Start calibration Sticks: Reset settings Cancel Save Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path Full Path File Name DPadContextMenu Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Standard Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings DPadEditDialog Dialog Presets: Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Dpad Mode: &Name: 4 Way Cardinal 4 Way Diagonal DPad Delay: Time lapsed before a direction change is taken into effect. s Specify the name of a dpad. Mouse Settings Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way Set Set %1 EditAllDefaultAutoProfileDialog Default Profile Profile: Browse Open Config Profile file path is invalid. ExtraProfileSettingsDialog Extra Profile Settings Key Press Time: 0.00 ms Profile Name: s GameController Game Controller GameControllerDPad DPad GameControllerMappingDialog Game Controller Mapping <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A B X Y Back Start Guide Left Shoulder Right Shoulder Left Stick Click Right Stick Click Left Stick X Left Stick Y Right Stick X Right Stick Y Left Trigger Right Trigger DPad Up DPad Left DPad Down DPad Right Mapping SDL 2 Game Controller Mapping String Last Axis Event: Current Axis Detection Dead Zone: 5000 10000 15000 20000 25000 30000 32000 Game Controller Mapping (%1) (#%2) Discard Controller Mapping? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. GameControllerSet Back Guide Start LS Click RS Click L Shoulder R Shoulder L Trigger R Trigger GameControllerTrigger Trigger JoyAxis Axis JoyAxisButton Negative Positive Unknown Button JoyAxisContextMenu Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Left | Right Keys: W | S Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 None Mouse Settings Left Mouse Button Right Mouse Button JoyButton Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Button [NO KEY] [Set %1 1W] [Set %1 2W] [Set %1 WH] JoyButtonContextMenu Toggle Turbo Clear Set Select Disabled Set %1 Set %1 1W Set %1 2W Set %1 WH JoyButtonSlot Mouse Up Down Left Right LB MB RB Pause Hold Cycle Distance Release Mouse Mod Press Time Delay Load %1 Set Change %1 [Text] %1 [Exec] %1 [NO KEY] JoyControlStick Stick JoyControlStickButton Up Down Left Right Button JoyControlStickContextMenu Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Standard Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings JoyControlStickEditDialog Dialog X: 0 Y: Distance: Presets: Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Stick Mode: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4 Way Diagonal Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. Square Stick: Percentage to modify a square stick coordinates to confine values to a circle % Stick Delay: Time lapsed before a direction change is taken into effect. s Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Na&me: Name: Specify the name of an analog stick. Mouse Settings Standard Bearing: % Safe Zone: Eight Way Dead Zone: Max Zone: Diagonal Range: Set Set %1 JoyControlStickModifierButton Modifier JoyDPad DPad JoyDPadButton Up Down Left Right Button JoyTabWidget <New> Remove Remove configuration from recent list. Load Load configuration file. Save Save changes to configuration file. Save As Save changes to a new configuration file. Sets Copy from Set Settings Set 1 Set 2 Set 3 Set 4 Set 5 Set 6 Set 7 Set 8 Stick/Pad Assign Controller Mapping Quick Set Names Toggle button name displaying. Pref Change global profile settings. Reset Revert changes to the configuration. Reload configuration file. Open Config Config Files (*.amgp *.xml) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 Set %1 Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Save Config Set Joystick Joystick JoystickStatusWindow Properties Details Name: %1 Number: Axes: Buttons: Hats: Battery: Unknown GUID: Game Controller: Axes Buttons Hats %1 (#%2) Properties Axis %1 Hat %1 No Yes MainSettingsDialog Edit Settings General Controller Mappings Language Auto Profile Mouse Advanced <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> Recent Profile Count: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Close To Tray Have Windows start AntiMicroX at system startup. Launch At Windows Startup Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Single Profile List in Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimize to Taskbar This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Hide Empty Buttons When the program is launched, open the last known profile that was opened during the previous session. Auto Load Last Opened Profile Only show the system tray icon when the program first launches. Launch in Tray Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Active keys will be repeatedly pressed when this option is enabled. Enable Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Error Warning Info Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset Class Title Program Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision Smoothing Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Screen: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: 0 Accel Denominator: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Delay: Pro&file Directory: ms Rate: times/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. GUID Mapping String Disable? Delete Insert Default English Active Devices: All Device Profile Default? Add Edit Select Default Profile Directory Are you sure you want to delete the profile? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] MainWindow AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu If events are not seen by a game, please click here to run this application as Administrator. &App &Options He&lp &Quit Ctrl+Q &Update Joysticks Ctrl+U &Hide Ctrl+H &About Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C Home Page Could not find a proper controller identifier. Exiting. (%1) Open File %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore Calibration couldn't be opened You must connect at least one controller to open the window Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Set %1 MouseButtonSettingsDialog Mouse Settings - Set %1 MouseControlStickSettingsDialog Mouse Settings Set %1 MouseDPadSettingsDialog Mouse Settings Set %1 MouseSettingsDialog Mouse Settings Mouse Mode: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Spring Acceleration: Enhanced Precision Linear Quadratic Cubic Quadratic Extreme Power Function Easing Quadratic Easing Cubic Mouse Speed Settings Enable to change the horizontal and vertical speed boxes at the same time. Change Together Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: 1 = 20 pps Wheel Hori. Speed: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: s Highest value to accelerate mouse movement by x Start %: Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Max Threshold: Maximum axis travel before acceleration has reached the multiplier value E&xtra Duration: Curve: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Mouse Status X: 0 (0 pps) Y: 1 = 1 notch(es)/s Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Spring Width: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. %n notch(es)/s %n notch/s %n notches/s ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Native Key Value: 0x00000000 Qt Key Value: antimicro Key Value: QObject Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Failed to launch daemon Launching daemon Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to change working directory to / Quitting Program # of joysticks found: %1 List Joysticks: --------------- Joystick %1: Index: %1 UniqueID: %1 GUID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Yes No Game Controller: %1 # of Axes: %1 # of Buttons: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Profile location %1 does not exist. Controller identifier is not a valid value. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. No controller was specified. No display string was specified. An invalid event generator was specified. No event generator string was specified. No log file specified. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> Quick Set %1 SetAxisThrottleDialog Throttle Change The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? SetJoystick Set %1: %2 Set %1 SetNamesDialog Set Name Settings Set 1 Set 2 Set 3 Set 4 Set 5 Set 6 Set 7 Set 8 Name SimpleKeyGrabberButton Mouse SpringModeRegionPreview Spring Mode Preview UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Using uinput device file %1 UInputHelper a b c d e f g h i j k l m n o p q r s t u v w x y z Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 ` 1 2 3 4 5 6 7 8 9 0 - = BackSpace Tab [ ] \ CapsLock ; ' Enter Shift_L , . / Ctrl_L Super_L Alt_L Space Alt_R Menu Ctrl_R Shift_R Up Left Down Right PrtSc Ins Del Home End PgUp PgDn NumLock * + KP_Enter KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9 KP_0 SCLK Pause Super_R Mute VolDn VolUp Play Stop Prev Next [NO KEY] UnixWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path VDPad VDPad VirtualKeyPushButton Space Tab Shift (L) Shift (R) Ctrl (L) Ctrl (R) Alt (L) Alt (R) Alt Gr ` ~ - = [ ] \ Caps ; ' , . / ESC PRTSC SCLK INS PGUP DEL PGDN 1 2 3 4 5 6 7 8 9 0 NUM LK * + Enter Del < : Super (L) Menu Up Down Left Right VirtualKeyboardMouseWidget Keyboard Mouse Mouse Settings Left Mouse Up Mouse Left Button Mouse Middle Button Mouse Right Button Mouse Wheel Up Mouse Wheel Left Mouse Wheel Right Mouse Wheel Down Mouse Down Mouse Right Mouse Mouse 8 Mouse Mouse 9 Mouse NONE [NO KEY] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Browser Back Browser Favorites Browser Forward Browser Home Browser Refresh Browser Search Browser Stop Calc Email F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 Media Media Next Media Play Media Previous Media Stop Search Volume Down Volume Mute Volume Up VirtualMousePushButton INVALID X11Extras ESC Tab Space DEL Return KP_Enter Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Changing mouse acceleration for device with id=%1 XMLConfigReader Could not write updated profile XML to file %1. XMLConfigWriter Could not write to profile at %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_br.ts.autosave000066400000000000000000012001051377703515000313200ustar00rootroot00000000000000 AboutDialog About Version "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicrox project. Additionally, project management has passed from Travis (Ryochan7) to the antimicrox organization due to Travis having other interests and priorities. Copyright: 2013 - 2018 Info <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the antimicrox group at https://github.com/antimicrox, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> Changelog Credits antimicrox About Development License Program Version %1 Program Compiled on %1 at %2 Built Against SDL %1 Running With SDL %1 Using Qt %1 Using Event Handler: %1 AddEditAutoProfileDialog Auto Profile Dialog Profile: Browse Window: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties Class: Title: set partial title Application: Select De&vices: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller A different profile is already selected as the default for this device. Current (%1) Open Config Select Program Programs (*.exe) Please use the main default profile selection. Please select a window by using the mouse. Press Escape if you want to cancel. Capture Application Window Could not obtain information for the selected window. Application Capture Failed Profile file path is invalid. No window matching property was specified. Program path is invalid or not executable. File is not an .exe file. No window matching property was selected. AdvanceButtonDialog Advanced Assignments Toggle Turbo Set Selector Blank or KB/M Hold Pause Cycle Distance Insert Delete Clear All Time: 0.01s 0s Insert a pause that occurs in between key presses. Release Insert a new blank slot. Delete a slot. Clear all currently assigned slots. Specify the duration of an inserted Pause or Hold slot. 0m &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Distance: % Mouse Mod Press Time Delay Execute Load Set Change Text Entry Placeholder 0 Set the percentage that mouse speeds will be modified by. Auto Reset Cycle After seconds Executable: ... Arguments: Enabled Mode: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Gradient Pulse Delay: 0.10s Rate: 10.0/s Disabled Select Set 1 One Way Select Set 1 Two Way Select Set 1 While Held Select Set 2 One Way Select Set 2 Two Way Select Set 2 While Held Select Set 3 One Way Select Set 3 Two Way Select Set 3 While Held Select Set 4 One Way Select Set 4 Two Way Select Set 4 While Held Select Set 5 One Way Select Set 5 Two Way Select Set 5 While Held Select Set 6 One Way Select Set 6 Two Way Select Set 6 While Held Select Set 7 One Way Select Set 7 Two Way Select Set 7 While Held Select Set 8 One Way Select Set 8 Two Way Select Set 8 While Held sec. /sec. Set %1 Select Set %1 One Way Two Way While Held Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Choose Profile Config Files (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Sticks DPads %1 (Joystick %2) Stick 1 Enabled Assign X Axis: Y Axis: Stick 2 Number of Physical DPads: %1 Virtual DPad 1 Up: Down: Note: This window is meant for backwards compatibility with profiles made before antimicrox 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Left: Right: Axis %1 Axis %1 - Axis %1 + Button %1 Move stick 1 along the X axis Move stick 1 along the Y axis Move stick 2 along the X axis Move stick 2 along the Y axis Press a button or move an axis AxisEditDialog Axis Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Left | Right Keys: W | S Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 None Set the value to use as the limit for an axis. Useful for a worn out analog stick. Negative Half Throttle Positive Half Throttle Name: Specify the name of an axis. Mouse Settings Set the value of the dead zone for an axis. Presets: Dead Zone: Max Zone: [NO KEY] Throttle setting that determines the behavior of how to interpret an axis hold or release. Negative Throttle Normal Positive Throttle Current Value: Set Set %1 Left Mouse Button Right Mouse Button ButtonEditDialog Dialog To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Placeholder Toggle Enables a key press or release to only occur when a controller button is pressed. Enables rapid key presses and releases. Turbo controller. Turbo Last keyboard/mouse button: Slots Na&me: Specify the name of a button. Action: Specify the action that will be performed in game while this button is being used. Advanced Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 Calibration Form Start calibration Controller: Sticks: Reset settings Cancel Save Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path Full Path File Name DPadContextMenu Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Standard Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings DPadEditDialog Dialog Presets: Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Dpad Mode: &Name: 4 Way Cardinal 4 Way Diagonal DPad Delay: Time lapsed before a direction change is taken into effect. s Specify the name of a dpad. Mouse Settings Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way Set Set %1 EditAllDefaultAutoProfileDialog Default Profile Profile: Browse Open Config Profile file path is invalid. ExtraProfileSettingsDialog Extra Profile Settings Key Press Time: 0.00 ms Profile Name: s GameController Game Controller GameControllerDPad DPad GameControllerMappingDialog Game Controller Mapping <html><head/><body><p>antimicrox makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>antimicrox will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A B X Y Back Start Guide Left Shoulder Right Shoulder Left Stick Click Right Stick Click Left Stick X Left Stick Y Right Stick X Right Stick Y Left Trigger Right Trigger DPad Up DPad Left DPad Down DPad Right Mapping SDL 2 Game Controller Mapping String Last Axis Event: Current Axis Detection Dead Zone: 5000 10000 15000 20000 25000 30000 32000 Game Controller Mapping (%1) (#%2) Discard Controller Mapping? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. GameControllerSet Back Guide Start LS Click RS Click L Shoulder R Shoulder L Trigger R Trigger GameControllerTrigger Trigger JoyAxis Axis JoyAxisButton Negative Positive Unknown Button JoyAxisContextMenu Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Left | Right Keys: W | S Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 None Mouse Settings Left Mouse Button Right Mouse Button JoyButton Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Button [NO KEY] [Set %1 1W] [Set %1 2W] [Set %1 WH] JoyButtonContextMenu Toggle Turbo Clear Set Select Disabled Set %1 Set %1 1W Set %1 2W Set %1 WH JoyButtonSlot Mouse Up Down Left Right LB MB RB B4 B5 Pause Hold Cycle Distance Release Mouse Mod Press Time Delay Load %1 Set Change %1 [Text] %1 [Exec] %1 [NO KEY] JoyControlStick Stick JoyControlStickButton Up Down Left Right Button JoyControlStickContextMenu Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Standard Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings JoyControlStickEditDialog Dialog X: 0 Y: Distance: Presets: Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Stick Mode: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4 Way Diagonal Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. Square Stick: Percentage to modify a square stick coordinates to confine values to a circle % Stick Delay: Time lapsed before a direction change is taken into effect. s Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Na&me: Name: Specify the name of an analog stick. Mouse Settings Standard Bearing: % Safe Zone: Eight Way Dead Zone: Max Zone: Diagonal Range: Set Set %1 JoyControlStickModifierButton Modifier JoyDPad DPad JoyDPadButton Up Down Left Right Button JoyTabWidget <New> Remove Remove configuration from recent list. Load Load configuration file. Save Save changes to configuration file. Save As Save changes to a new configuration file. Sets Copy from Set Settings Set 1 Set 2 Set 3 Set 4 Set 5 Set 6 Set 7 Set 8 Stick/Pad Assign Controller Mapping Quick Set Names Toggle button name displaying. Pref Change global profile settings. Reset Revert changes to the configuration. Reload configuration file. Open Config Config Files (*.amgp *.xml) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 Set %1 Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Save Config Set Joystick Joystick JoystickStatusWindow Properties Details Name: %1 Number: Axes: Buttons: Hats: GUID: Game Controller: Axes Buttons Hats %1 (#%2) Properties Axis %1 Hat %1 No Yes MainSettingsDialog Edit Settings General Controller Mappings Language Auto Profile Mouse Advanced Profile Direc&tory: <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> Recent Profile Count: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using antimicrox unattended. Hide main window when the main window close button is clicked instead of quitting the program. Close To Tray Have Windows start antimicrox at system startup. Launch At Windows Startup Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Single Profile List in Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimize to Taskbar This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Hide Empty Buttons When the program is launched, open the last known profile that was opened during the previous session. Auto Load Last Opened Profile Only show the system tray icon when the program first launches. Launch in Tray Associate .amgp files with antimicrox in Windows Explorer. Associate Profiles Key Repeat Active keys will be repeatedly pressed when this option is enabled. Enable Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>antimicrox has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make antimicrox load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Log File: Log Level: None Error Warning Info Debug Reset Class Title Program Disable the "Enhanced Pointer Precision" Windows setting while antimicrox is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within antimicrox to be more precise. Disable Enhance Pointer Precision Smoothing Weight &Modifier: Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Screen: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: 0 Accel Denominator: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Delay: ms Rate: times/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. GUID Mapping String Disable? Delete Insert Default English Active Devices: All Device Profile Default? Add Edit Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Select Default Profile Directory Are you sure you want to delete the profile? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? MainWindow antimicrox No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu If events are not seen by a game, please click here to run this application as Administrator. &App &Options &Help &Quit Ctrl+Q &Update Joysticks Ctrl+U &Hide Ctrl+H &About Ctrl+A About &Qt &Properties &Key Checker &GitHub Page &Game Controller Mapping S&ettings &Stick/Pad Assign &Wiki &Issues &Calibration Home Page Could not find a proper controller identifier. Exiting. (%1) Open File &Restore Calibration couldn't be opened You must connect at least one controller to open the window Run as Administrator? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by antimicrox to not be used by those games unless antimicrox is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Failed to elevate program Failed to restart this program as the Administrator Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Set %1 MouseButtonSettingsDialog Mouse Settings - Set %1 MouseControlStickSettingsDialog Mouse Settings Set %1 MouseDPadSettingsDialog Mouse Settings Set %1 MouseSettingsDialog Mouse Settings Mouse Mode: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Spring Acceleration: Enhanced Precision Linear Quadratic Cubic Quadratic Extreme Power Function Easing Quadratic Easing Cubic Mouse Speed Settings Enable to change the horizontal and vertical speed boxes at the same time. Change Together Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: 1 = 20 pps Wheel Hori. Speed: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: s Highest value to accelerate mouse movement by x Start %: Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Max Threshold: Maximum axis travel before acceleration has reached the multiplier value E&xtra Duration: Curve: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Mouse Status X: 0 (0 pps) Y: 1 = 1 notch(es)/s Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Spring Width: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. %n notch(es)/s %n notch/s %n notches/s QKeyDisplayDialog Key Checker <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by antimicrox.</p><p>The antimicrox key value and the Qt key value will usually be the same. antimicrox tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to antimicrox's <a href="https://github.com/AntiMicroX/antimicrox/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Native Key Value: 0x00000000 Qt Key Value: antimicrox Key Value: QObject Super Menu Mute Vol+ Vol- Play/Pause Play Pause Prev Next Mail Home Media Search Daemon launched Failed to launch daemon Launching daemon Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to change working directory to / Quitting Program # of joysticks found: %1 List Joysticks: --------------- Joystick %1: Index: %1 GUID: %1 Name: %1 Yes No Game Controller: %1 # of Axes: %1 # of Buttons: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Could not raise process priority. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Profile location %1 does not exist. Controller identifier is not a valid value. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. No controller was specified. No display string was specified. An invalid event generator was specified. No event generator string was specified. No log file specified. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> Quick Set %1 SetAxisThrottleDialog Throttle Change The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? SetJoystick Set %1: %2 Set %1 SetNamesDialog Set Name Settings Set 1 Set 2 Set 3 Set 4 Set 5 Set 6 Set 7 Set 8 Name SimpleKeyGrabberButton Mouse SpringModeRegionPreview Spring Mode Preview UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Using uinput device file %1 UInputHelper a b c d e f g h i j k l m n o p q r s t u v w x y z Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 ` 1 2 3 4 5 6 7 8 9 0 - = BackSpace Tab [ ] \ CapsLock ; ' Enter Shift_L , . / Ctrl_L Super_L Alt_L Space Alt_R Menu Ctrl_R Shift_R Up Left Down Right PrtSc Ins Del Home End PgUp PgDn NumLock * + KP_Enter KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9 KP_0 SCLK Pause Super_R Mute VolDn VolUp Play Stop Prev Next [NO KEY] UnixWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path VDPad VDPad VirtualKeyPushButton Space Tab Shift (L) Shift (R) Ctrl (L) Ctrl (R) Alt (L) Alt (R) Alt Gr ` ~ - = [ ] \ Caps ; ' , . / ESC PRTSC SCLK INS PGUP DEL PGDN 1 2 3 4 5 6 7 8 9 0 NUM LK * + Enter < : Super (L) Menu Up Down Left Right VirtualKeyboardMouseWidget Keyboard Mouse Mouse Settings Left Mouse Up Mouse Left Button Mouse Middle Button Mouse Right Button Mouse Wheel Up Mouse Wheel Left Mouse Wheel Right Mouse Wheel Down Mouse Down Mouse Right Mouse Button 4 Mouse Mouse 8 Mouse Button 5 Mouse Mouse 9 Mouse NONE Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Applications Browser Back Browser Favorites Browser Forward Browser Home Browser Refresh Browser Search Browser Stop Calc Email Media Media Next Media Play Media Previous Media Stop Search Volume Down Volume Mute Volume Up VirtualMousePushButton INVALID WinAppProfileTimerDialog Capture Application After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Timer: Seconds Cancel WinExtras [NO KEY] antimicrox Profile X11Extras ESC Tab Space DEL Return KP_Enter Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Changing mouse acceleration for device with id=%1 XMLConfigReader Could not write updated profile XML to file %1. XMLConfigWriter Could not write to profile at %1. antimicrox Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_de.ts000066400000000000000000014064331377703515000274730ustar00rootroot00000000000000 AboutDialog About Über Version Version Info Info Changelog Changelog Credits Mitwirkende AntiMicroX <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Es wurde ursprünglich von Travis Nickles &lt;nickles.travis@gmail.com&gt; entwickelt, dann von der AntiMicro-Gruppe unter https://github.com/AntiMicro und jetzt von juliagoda unter https://github.com/juliagoda weiterentwickelt.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Mitwirkende:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">frühere Mitwirkende</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Übersetzer:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brasilianisches Portugiesisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinesisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - Französisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - Deutsch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - Deutsch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italienisch</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polnish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> About Development Über die Entwicklung "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Copyright: 2013 - 2020 License Lizenz Program Version %1 Programmversion %1 Program Compiled on %1 at %2 Programm kompiliert am %1 um %2 Built Against SDL %1 Nutzt SDL %1 Running With SDL %1 Läuft mit SDL %1 Using Qt %1 Benutzt Qt %1 Using Event Handler: %1 Verwendung des Ereignisbehandlers: %1 AddEditAutoProfileDialog Auto Profile Dialog Auto-Profil-Dialog Profile: Profil: Pro&file: Pro&fil: Browse Durchsuchen Window: Fenster: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Wählen Sie das Fenster. Klicken Sie auf das entsprechende Anwendungs-Fenster und der Anwendungs-Dateipfad wird in das Formular eingetragen. Detect Window Properties Erkenne Fenstereigenschaften &Class: &Klasse: T&itle: T&itel: Class: Klasse: Title: Titel: set partial title Teiltitel setzen Application: Anwendung: Select Wähle De&vices: Ge&räte: Devices: Geräte: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Wählen Sie dieses Profil als Standard für das jeweilige Gerät. Diese Auswahl wird anstatt jeder anderen Standardeinstellung genutzt. Set as Default for Controller Setze als Standardcontroller A different profile is already selected as the default for this device. Ein anderes Profil ist bereits als Standard für dieses Gerät ausgewählt. Current (%1) Aktuell (%1) Open Config Konfiguration öffnen Select Program Wähle Anwendung Programs (*.exe) Programme (*.exe) Please use the main default profile selection. Bitte benutzen Sie die Standard-Profilauswahl. Main Profile Hauptprofil Already selected Bereits ausgewählt Chosen Profile Ausgewähltes Profil The selection will be used instead of the all default profile option. Die Auswahl wird statt der Option des Standardprofiles verwendet. Please select a window by using the mouse. Press Escape if you want to cancel. Bitte wählen Sie mit der Maus ein Fenster aus. Escape drücken um abzubrechen. Capture Application Window Anwendungsfenster auswählen Could not obtain information for the selected window. Konnte nicht Information für das ausgewählte Fenster gewinnen. Application Capture Failed Anwendungsauswahl fehlgeschlagen Profile file path is invalid. Profil-Dateipfad ist ungültig. No window matching property was specified. Kein zugehöriges Fenster wurde spezifiziert. Program path is invalid or not executable. Programmpfad ist ungültig oder nicht ausführbar. File is not an .exe file. Datei ist keine .exe-Datei. No window matching property was selected. Kein zugehöriges Fenster wurde ausgewählt. AdvanceButtonDialog Advanced Erweitert Assignments Zuweisungen Toggle Umschalten Turbo Turbo Set Selector Wähle Set Blank or KB/M Leer oder KB/M Hold Halten Pause Pause Cycle Kreislauf Distance Distanz Insert Einfügen Delete Entfernen Clear All Leeren Time: Zeit: 0.01s 0.01s 0s 0s Insert a pause that occurs in between key presses. Füg eine Pause zwischen den Tasten ein. Release Freigeben Insert a new blank slot. Füg eine neue leere Aktion hinzu. Join Verbinde Split Teile Delete a slot. Lösche eine Aktion. Clear all currently assigned slots. Lösche alle zugewiesenen Aktionen. Specify the duration of an inserted Pause or Hold slot. Gib die Dauer der hinzugefügten Pause- oder Haltenaktion an. 0m 0m &Mouse Speed Mod: &Mausgeschwindigkeitsmodus: Specify the range past an axis dead zone in which a sequence of actions will execute. Gib die Distanz der Achse zur "Dead Zone" an, in der die Sequenz an Aktionen ausgeführt wird. Distance: Distanz: % % Mouse Mod Maus Mod Press Time Druckzeit Delay Verzögerung Execute Ausführung Load Laden Set Change Gruppewahl Text Entry Texteintrag Placeholder Platzhalter 0 0 Mouse Speed Mod: Maus Mod Geschwindigkeit: Set the percentage that mouse speeds will be modified by. Stelle den Prozentsatz ein um der die Mausgeschwindigkeit modifiziert werden soll. Auto Reset Cycle After Zyklus automatisch neustarten nach seconds Sekunden Executable: ausführbare Datei: ... ... Arguments: Argumente: Enabled Aktiviert Mode: Modus: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Normal: Wiederholt mit der eingestellten Rate Taste drücken und loslassen.</p><p>Verlaufend: Ändere die Auslösen-/Loslassen-Verzögerung aufgrund wie weit die eine Achse bewegt wurde.</p><p>Pulsierend: Ändere wie häufig eine Taste pro Sekunde ausgelöst wurde. Die Verögerung bleibt gleich.</p></body></html> Normal Normal Gradient Verlaufend Pulse Pulsierend Delay: Verzögerung: 0.10s 0.10s Rate: Rate: 10.0/s 10.0/s Disabled Deaktiviert Select Set 1 One Way Wähle Gruppe 1: einseitig Select Set 1 Two Way Wähle Gruppe 1: wechselseitig Select Set 1 While Held Wähle Gruppe 1: festgehalten Select Set 2 One Way Wähle Gruppe 2: einseitig Select Set 2 Two Way Wähle Gruppe 2: wechselseitig Select Set 2 While Held Wähle Gruppe 2: festgehalten Select Set 3 One Way Wähle Gruppe 3: einseitig Select Set 3 Two Way Wähle Gruppe 3: wechselseitig Select Set 3 While Held Wähle Gruppe 3: festgehalten Select Set 4 One Way Wähle Gruppe 4: einseitig Select Set 4 Two Way Wähle Gruppe 4: wechselseitig Select Set 4 While Held Wähle Gruppe 4: festgehalten Select Set 5 One Way Wähle Gruppe 5: einseitig Select Set 5 Two Way Wähle Gruppe 5: wechselseitig Select Set 5 While Held Wähle Gruppe 5: festgehalten Select Set 6 One Way Wähle Gruppe 6: einseitig Select Set 6 Two Way Wähle Gruppe 6: wechselseitig Select Set 6 While Held Wähle Gruppe 6: festgehalten Select Set 7 One Way Wähle Gruppe 7: einseitig Select Set 7 Two Way Wähle Gruppe 7: wechselseitig Select Set 7 While Held Wähle Gruppe 7: festgehalten Select Set 8 One Way Wähle Gruppe 8: einseitig Select Set 8 Two Way Wähle Gruppe 8: wechselseitig Select Set 8 While Held Wähle Gruppe 8: festgehalten [NO KEY] [KEINE TASTE] sec. Sek. /sec. /Sek. Not checked slots Nicht überprüfte Slots To delete slots, you need to select at least one Um Slots zu löschen, musst du mindestens einen Slot auswählen To insert slots, you need to select at least one Um Slots einzufügen, musst du mindestens einen Slot auswählen Unknown current slot Unbekannter aktueller Slot Click on chosen slots before joining them Klicke auf die ausgewählten Slots, bevor du die schließst an Not enough slots Nicht genügend Slots It's impossible to join slots. Add at least one other slot. Es ist unmöglich, um Slots zu verbinden. Füge mindestens einen weiteren Slot hinzu. Not selected slots Nicht ausgewählte Slots It's impossible to join slots. Select at least two slots before joining them Es ist unmöglich, um Slots zu verbinden. Wähle mindestens zwei Slots bevor aus Only keyboard slots Nur Tastatur-Slots It's only possible to join simple and mix keyboard slots Es ist nur möglich, einfache und gemischte Tastatur-Slots zu verbinden It's impossible to split slots. Add at least one other slot. Es ist unmöglich, um Slots zu teilen. Füge mindestens einen weiteren Slot hinzu. Not selected slot Nicht ausgewählte Slots Select your slot before splitting. Wähle deinen Slot bevor aus. Too many mix slots Zu viele Mix-Slots Select one mix slot. Wähle einen Mix-slot aus. Only mix slots Nur Mix-Slots It's only possible to split mix slot. Es ist nur möglich, den Mix-Slot zu teilen. Empty execution path Leerer Ausführungspfad Line for execution file path is empty. Fill the first line before you are going to add a slot. Die Zeile für den Pfad der Ausführungsdatei ist leer. Fülle die erste Zeile, bevor Sie einen Slot hinzufügen. File doesn't exist Datei existiert nicht There is no such file locally, that could be executed. Check the file on your system Es gibt keine solche Datei lokal, die ausgeführt werden könnte. Überprüfe die Datei auf Ihrem System Set %1 Gruppe %1 Select Set %1 Wähle Gruppe %1 One Way Einweg Two Way Zweiwege While Held Solang wie gehalten Choose Executable Wähle ausführbare Datei Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Slots nach einer Zyklus-Aktion werden beim nächsten Tastendruck ausgeführt. Es können mehrere Zyklen hinzugefügt werden, um Partitionen in einer Sequenz zu erstellen. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Verzögert den Zeitpunkt der Aktivierung des nächsten Slots um die angegebene Zeit. Slots, die vor der Verzögerung aktiviert wurden, bleiben auch nach Ablauf der Verzögerungszeit aktiv. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Die Abstandsaktion legt fest, dass Slots anschließend nur dann ausgeführt werden, wenn eine Achse um einen bestimmten Bereich über die festgelegte Totzone hinaus bewegt wird. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Füge eine Halteaktion ein. Slots nach der Aktion werden nur ausgeführt, wenn die Taste über das angegebene Intervall hinaus gehalten wird. Chose a profile to load when this slot is activated. Wähle ein Profil zum Laden wenn dieser Slot aktiviert ist. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Die Maus-Mod-Aktion ändert alle Einstellungen der Mausgeschwindigkeit um einen bestimmten Prozentsatz, während die Aktion ausgeführt wird. Dies kann nützlich sein, um die Maus während des Scharfschneidens zu verlangsamen. Specify the time that keys past this slot should be held down. Gib die Zeit an, die die Tasten nach diesem Schlitz gedrückt gehalten werden sollen. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Füg eine Freigabe-Aktion ein. Slots nach der Aktion werden nach dem Loslassen einer Taste nur dann ausgeführt, wenn die Taste über das angegebene Intervall hinaus gehalten wurde. Change to selected set once slot is activated. Wechsle zu ausgewählter Gruppe wenn Slot aktiviert ist. Full string will be typed when a slot is activated. Die vollständige Zeichenfolge wird eingegeben, wenn ein Slot aktiviert wird. Execute program when slot is activated. Führe das Programm aus, wenn der Slot aktiviert ist. Choose Profile Wähle Profil Config Files (*.amgp *.xml) Konfigurationsdateien (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Stick/Pad Zuweisung Sticks Sticks DPads DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Hinweis: Dieses Fenster dient der Rückwärtskompatibilität mit Profilen, die vor Antimicro 2.0 hergestellt wurden. Seit Version 2.0 wird die Verwendung des Game Controller Mapping-Fensters bevorzugt. %1 (Joystick %2) %1 (Joystick %2) Stick 1 Stick 1 Enabled Aktiviert Assign Zuweisen X Axis: X Achse: Y Axis: Y Achse: Stick 2 Stick 2 Number of Physical DPads: %1 Nummer der physischen DPads: %1 Virtual DPad 1 Virtueller DPad 1 Up: Hoch: Down: Runter: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Hinweis: Dieses Fenster ist nur zur Rückwärtskompatibilität zu Profilen für AntiMicroX vor 2.0 gedacht. Seit Version 2.0 wird das Spielecontroller-Zuweisungsfenster bevorzugt. Left: Links: Right: Rechts: Axis %1 Achse %1 Axis %1 - Achse %1 - Axis %1 + Achse %1 + Button %1 Button %1 Move stick 1 along the X axis Bewege Stick 1 entlang der X Achse Move stick 1 along the Y axis Bewege Stick 1 entlang der Y Achse Move stick 2 along the X axis Bewege Stick 2 entlang der X Achse Move stick 2 along the Y axis Bewege Stick 2 entlang der Y Achse Press a button or move an axis Drücke einen Button oder bewege eine Achse AxisEditDialog Axis Achse Mouse (Horizontal) Maus (Horizontal) Mouse (Inverted Horizontal) Maus (Invertiert Horizontal) Mouse (Vertical) Maus (Vertikal) Mouse (Inverted Vertical) Maus (Invertiert Vertikal) Arrows: Up | Down Pfeiltasten: Hoch | Runter Arrows: Left | Right Pfeiltasten: Links | Rechts Keys: W | S Tasten: W | S Keys: A | D Tasten: A | D NumPad: KP_8 | KP_2 Nummernblock: KP_8 | KP_2 NumPad: KP_4 | KP_6 Nummernblock: KP_4 | KP_6 None Nichts Set the value to use as the limit for an axis. Useful for a worn out analog stick. Setze einen Wert als Limitierung einer Achse. Nützlich bei abgenutzten Analogsticks. Negative Half Throttle Negative Halbbeschleunigung Positive Half Throttle Positive Halbbeschleunigung Name: Name: Specify the name of an axis. Vergebe den Namen der Achse. Mouse Settings Mauseinstellungen Set the value of the dead zone for an axis. Bestimmt den Wert der Dead Zone einer Achse. Presets: Vorgaben: Dead Zone: Dead Zone: Max Zone: Max Zone: [NO KEY] [KEINE TASTE] Throttle setting that determines the behavior of how to interpret an axis hold or release. Beschleunigung gibt das Verhalten an wie das Halten oder Loslassen einer Achse interpretiert wird. Negative Throttle Negative Beschleunigung Normal Normal Positive Throttle Positive Beschleunigung Current Value: Aktueller Wert: Set Set Set %1 Set %1 Left Mouse Button Linke Maustaste Right Mouse Button Rechte Maustaste ButtonEditDialog Dialog Dialog To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Um eine neue Zuweisung zu machen, drück eine Taste oder klick einen Button im Tastatur oder Mausreiter Placeholder Platzhalter Toggle Umschalten Enables a key press or release to only occur when a controller button is pressed. Tasten werden erst, wenn der Button gedrückt wurde entweder festgehalten oder frei gelassen. Enables rapid key presses and releases. Turbo controller. Aktiviert schnelles Tastendrücken oder Freigeben. Autofeuer. Turbo Turbo Current: Aktuell: Last keyboard/mouse button: Letzte Tastatur-/Maustaste: Slots Slots Na&me: Na&me: Specify the name of a button. Vergebe den Namen des Buttons. Action: Aktion: Specify the action that will be performed in game while this button is being used. Gibt die Aktion des Buttons an, die Ingame genutzt wird. Advanced Advanced Set Set Set %1 Set %1 Choose your keyboard key Wähle deine Tastaturtaste No button Keine Taste Last button Letzte Taste To change settings for last button, it must be at least one assignment from keyboard to gamepad Um die Einstellungen für die letzte Taste zu ändern, muss es mindestens eine Zuordnung von der Tastatur zum Gamepad geben To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad Um die Einstellungen von Turbo für die letzte Taste zu ändern, muss es mindestens eine Zuordnung von Tastatur zu Gamepad geben No choice Keine Wahl Before you open window with advanced settins, you have to choice a key Bevor du ein Fenster mit den erweiterten Einstellungen öffnest, musst du einen Schlüssel wählen To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Um den erweiterten Dialog zu öffnen, muss mindestens eine Taste von der Tastatur auf das Gamepad gelegt werden Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Slots für die Tasten konnten nicht gelöscht werden, da es keine Taste für das Gamepad auf der Tastatur gab. Belege mindestens eine Taste von der Tastatur für das Gamepad As last gamepad button has been set Da die letzte Gamepad-Taste eingestellt wurde Index %1 Index %1 [NO KEY] [KEINE TASTE] Calibration Form Formular Start calibration Starte Kalibrierung Controller: Controller: Sticks: Stöcke: Reset settings Einstellungen zurücksetzen Cancel Abbrechen Save Speichern Calibration Kalibrierung Do you really want to reset settings of current axis? Willst du wirklich die Einstellungen der aktuellen Achse zurücksetzen? Calibration was saved for the preset. Do you really want to reset settings? Die Kalibrierung wurde für die Voreinstellung gespeichert. Willst du die Einstellungen wirklich zurücksetzen? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Stelle den Joystick in die Mittelposition. Das ist der Teil, bei dem du sich oft nicht bewegen müss. Überspringe ihn in einer solchen Situation einfach. Calibrating center Kalibrierungszentrum Start second step Starte zweiter Schritt Center X: %1 Zentrum X: %1 Center Y: %1 Zentrum Y: %1 Place the joystick in the top-left corner many times Platziere den Joystick viele Male in der linken oberen Ecke Calibrating position Kalibrierposition X: %1 X: %1 Y: %1 Y: %1 Place the joystick in the bottom-right corner Platziere den Joystick in der rechten unteren Ecke Start final step Starte letzter Schritt range X: %1 - %2 Bereich X: %1 - %2 range Y: %1 - %2 Bereich Y: %1 - %2 deadzone X: %1 Totzone X: %1 deadzone Y: %1 Totzone Y: %1 ---Calibration done!--- ---Kalibrierung beendet!--- Calibration values have been saved Kalibrierwerte wurden gespeichert Dead zone calibration Totzonen-Kalibrierung You have to move axes to the top-left corner at least five times. Du muss die Achsen mindestens fünf Mal in die linke obere Ecke bewegen. You have to move axes to the bottom-right corner at least five times. Du muss die Achsen mindestens fünfmal in die rechte untere Ecke verschieben. Do you want to save calibration of current axis? Möchtest du die Kalibrierung der aktuellen Achse speichern? Axis %1 Achse %1 CapturedWindowInfoDialog Captured Window Properties Erkannte Fenstereigenschaften Information About Window Fensterinformationen Class: Klasse: TextLabel Title: Titel: Path: Pfad: Match By Properties Nach Eigenschaften zuordnen Class Klasse Title Titel Path Pfad Full Path vollständiger Pfad File Name Dateinmae CommandLineUtility Profile location %1 is not an XML file. Profilort %1 ist keine XML Datei. Profile location %1 does not exist. Profilort %1 existiert nicht. Controller identifier is not a valid value. Controllernummer ist keine gültige Ziffer. No set number was specified. Kein Set gewählt. No controller was specified. Kein Controller wurde spezifiert. An invalid event generator was specified. Ein ungültiger Ereignisgenerator wurde angegeben. No event generator string was specified. Kein Ereignesgenerator String wurde angegeben. Qt style flag was detected but no style was specified. Qt style Parameter erkannt, aber kein Style spezifiziert. No log level specified. Kein Log-Level angegeben. AntiMicroX version AntiMicroX Version Options Optionen Print help text. diese Hilfe ausgeben. Print version information. Programmversion ausgeben. Launch program in system tray only. Nur im Systemtray starten. Launch program with the tray menu disabled. Starten mit deaktiviertem Systemtray. Launch program without the main window displayed. Starten mit verstecktem Hauptfenster. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Programm mit ausgewählter Konfigurations- datei als Standard für alle Controller starten. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Übernehme Konfigurationsdatei zu dem angegebenen Controller. Wert kann Controllerindex, Name oder GUID sein. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Aktuell aktiviertes Profil entladen. Wert kann Controllerindex, Name oder GUID sein. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Starte Joysticks beim angegebenen Set. Wert kann Controllerindex, Name oder GUID sein. Launch program as a daemon. Starte Programm als Dienst. Enable logging. Aktiviere Logging. Use specified display for X11 calls. Useful for ssh. Nutze angegebenes Display für X11. Nützlich für ssh. Choose between using XTest support and uinput support for event generation. Default: xtest. Wähle zwischen XTest Unterstützung und uinput Unterstützung zur Ereignisgenerierung. Standard: xtest. Choose between using SendInput and vmulti support for event generation. Default: sendinput. Wähle zwischen der Nutzung von SendInput und vmulti support zur Ereignisgenerierung. Standard: sendinput. Print information about joysticks detected by SDL. Zeige Informationen über Joysticks die von SDL erkannt wurden. Open game controller mapping window of selected controller. Value can be a controller index or GUID. Öffne Gamecontrollerzuweisungs-Fenster für den ausgewählten Controller. Wert kann ein Controller Index oder GUID sein. DPadContextMenu Mouse (Normal) Maus (Normal) Mouse (Inverted Horizontal) Maus (Invertiert Horizontal) Mouse (Inverted Vertical) Maus (Invertiert Vertikal) Mouse (Inverted Horizontal + Vertical) Maus (Invertiert Horizontal + Vertikal) Arrows Pfeiltasten Keys: W | A | S | D Tasten: W | A | S | D NumPad Nummerntastatur None Nichts Standard Standard Eight Way 8-Weg 4 Way Cardinal 4-Wege kardinal 4 Way Diagonal 4-Wege diagonal Mouse Settings Mauseinstellungen DPadEditDialog Dialog Dialog Presets: Vorgaben: Mouse (Normal) Maus (Normal) Mouse (Inverted Horizontal) Maus (Invertiert Horizontal) Mouse (Inverted Vertical) Maus (Invertiert Vertikal) Mouse (Inverted Horizontal + Vertical) Maus (Invertiert Horizontal + Vertikal) Arrows Pfeiltasten Keys: W | A | S | D Tasten: W | A | S | D NumPad Nummerntastatur None Nichts Dpad Mode: DPad Modus: &Name: &Name: 4 Way Cardinal 4-Wege kardinal 4 Way Diagonal 4-Wege diagonal DPad Delay: DPad-Verzögerung: Time lapsed before a direction change is taken into effect. Zeit abgelaufen bevor eine Richtungsänderung vollzogen wird. s Specify the name of a dpad. Vergebe den Namen des DPads. Mouse Settings Mauseinstellungen Standard Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Standard: 8-Regionen-Dpad mit zwei aktiven Richtungstasten wenn sich der dpad in einem diagonalen Bereich befindet. Acht Weg: 8 Region dpad, wobei jede Richtung ihre eigene dedizierte Taste. Nur eine Taste ist immer aktiv bei zur Zeit. Nützlich für Rouge-ähnliche Spiele. 4-Wege-Kardinal: 4 Region dpad mit Regionen entsprechend die Himmelsrichtungen des dpad. Nützlich für Menüs. 4-Wege-Diagonale: 4-Regionen-Dpad mit jeder Region entsprechend in eine diagonale Zone. Eight Way 8-Wege Set Set Set %1 Set %1 EditAllDefaultAutoProfileDialog Default Profile Standardprofil Profile: Profil: Browse Durchsuchen Open Config Konfiguration öffnen Profile file path is invalid. Profil-Dateipfad ist ungültig. ExtraProfileSettingsDialog Extra Profile Settings Weitere Profileinstellungen Key Press Time: Tastendruckzeit: 0.00 ms 0.00 ms Profile Name: Profilname: s s GameController Game Controller Gamecontroller GameControllerDPad DPad DPad GameControllerMappingDialog Game Controller Mapping Game Controller Zuweisung <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> <html><head/><body><p>AntiMicroX nutzt die von SDL 2 bereitgestellte <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a>, um verschiedene Gamepads zu abstrahieren und einem einheitlichen Standard anzupassen. Um eine Schaltflächenzuweisung vorzunehmen, markiere die Zuordnungszelle für die entsprechende Schaltflächenzeile unten. Du kannst dann eine Taste drücken oder eine Achse auf Ihrem Gamepad verschieben, und die Zelle wird mit der zu verwendenden physischen Taste oder Achse aktualisiert.</p><p>AntiMicroX verwendet das Mapping, das du gibst an, um einen Mapping-String zu speichern, der in SDL geladen wird.</p></body></html> A A B B X X Y Y Back Zurück Start Start Guide Guide Left Shoulder linker Schulterbutton Right Shoulder rechter Schulterbutton Left Stick Click linker Stick Klick Right Stick Click rechter Stick Klick Left Stick X linker Stick X Left Stick Y linker Stick Y Right Stick X rechter Stick X Right Stick Y rechter Stick Y Left Trigger linker Trigger Right Trigger rechter Trigger DPad Up DPad Hoch DPad Left DPad Links DPad Down DPad Runter DPad Right DPad Rechts Mapping Zuweisung SDL 2 Game Controller Mapping String SDL 2 Game Controller Zuweisungsstring Last Axis Event: Letztes Achsenereignis: Current Axis Detection Dead Zone: Aktuelle Achsenerkennungs Totzone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Spielecontroller Zuweisung (%1) (#%2) Discard Controller Mapping? Controller Zuweisung verwerfen? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Zuweisung für diesen Controller verwerfen? Wenn verworfen, kehrt der Controller zu einem Joystick zurück wenn alle Joysticks aktualisiert werden. GameControllerSet Back Zurück Guide Handbuch Start Start LS Click LS Klick RS Click RS Klick L Shoulder L Schulter R Shoulder R Schulter L Trigger L Trigger R Trigger R Trigger GameControllerTrigger Trigger Trigger JoyAxis Axis Achse JoyAxisButton Negative Negativ Positive Positiv Unknown Unbekannt Button Button JoyAxisContextMenu Mouse (Horizontal) Maus (Horizontal) Mouse (Inverted Horizontal) Maus (Invertiert Horizontal) Mouse (Vertical) Maus (Vertikal) Mouse (Inverted Vertical) Maus (Invertiert Vertikal) Arrows: Up | Down Pfeiltasten: Hoch | Runter Arrows: Left | Right Pfeiltasten: Links | Rechts Keys: W | S Tasten: W | S Keys: A | D Tasten: A | D NumPad: KP_8 | KP_2 Nummernblock: KP_8 | KP_2 NumPad: KP_4 | KP_6 Nummernblock: KP_4 | KP_6 None Nichts Mouse Settings Mauseinstellungen Left Mouse Button Linke Maustaste Right Mouse Button Rechte Maustaste JoyButton Processing turbo for #%1 - %2 Bearbeitungsturbo für #%1 - %2 Finishing turbo for button #%1 - %2 Finishing-Turbo für Taste #%1 - %2 Processing press for button #%1 - %2 Verarbeitungsdruck für Taste #%1 - %2 Processing release for button #%1 - %2 Verarbeitungsfreigabe für Taste #%1 - %2 Distance change for button #%1 - %2 Abstandsänderung für Taste #%1 - %2 Button Button [NO KEY] [KEINE TASTE] [Set %1 1W] [Set %1 1W] [Set %1 2W] [Set %1 2W] [Set %1 WH] [Set %1 WH] JoyButtonContextMenu Toggle Umschalten Turbo Turbo Clear Leeren Set Select Set-Auswahl Disabled Deaktiviert Set %1 Set %1 Set %1 1W Set %1 1W Set %1 2W Set %1 2W Set %1 WH Set %1 WH JoyButtonSlot Mouse Maus Up Hoch Down Runter Left Links Right Rechts LB LB MB MB RB RB B4 B4 B5 B5 Pause Pause Hold Halten Cycle Kreislauf Distance Distanz Release Freigeben Mouse Mod Maus Mod Press Time Druckzeit Delay Verzögerung Load %1 Lade %1 Set Change %1 Gruppewahl %1 [Text] %1 [Text] %1 [Exec] %1 [Exec] %1 [NO KEY] [KEINE TASTE] JoyControlStick Stick Stick JoyControlStickButton Up Hoch Down Runter Left Links Right Rechts Button Button JoyControlStickContextMenu Mouse (Normal) Maus (Normal) Mouse (Inverted Horizontal) Maus (Invertiert Horizontal) Mouse (Inverted Vertical) Maus (Invertiert Vertikal) Mouse (Inverted Horizontal + Vertical) Maus (Invertiert Horizontal + Vertikal) Arrows Pfeiltasten Keys: W | A | S | D Tasten: W | A | S | D NumPad Nummerntastatur None Nichts Standard Standard Eight Way 8-Wege 4 Way Cardinal 4-Wege kardinal 4 Way Diagonal 4-Wege diagonal Mouse Settings Mauseinstellungen JoyControlStickEditDialog Dialog Dialog X: X: 0 0 Y: Y: Distance: Distanz: Presets: Vorgaben: Mouse (Normal) Maus (Normal) Mouse (Inverted Horizontal) Maus (Invertiert Horizontal) Mouse (Inverted Vertical) Maus (Invertiert Vertikal) Mouse (Inverted Horizontal + Vertical) Maus (Invertiert Horizontal + Vertikal) Arrows Pfeiltasten Keys: W | A | S | D Tasten: W | A | S | D NumPad Nummerntastatur None Nichts Stick Mode: Stickmodus: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Standard: 8-Wege-Stick mit zwei Richtungstasten aktiv wenn der Stick in diagonaler Richtung ist. 8-Wege: 8-Wege-Stick mit jedem Weg einer eigenen Taste entsprechend. Nur eine Taste ist gleichzeitig aktiv. Nützlich für "rougelike" Spiele. 4-Wege Kardinal: 4-Regionen-Stick, wobei jede Region einer Kardinal-/Himmelsrichtung des Sticks entspricht. Nützlich für Menüs. 4-Wege Diagonal: 4-Regionen-Stick, wobei jede Region einer Diagonal-Zone des Sticks entspricht. 4 Way Cardinal 4-Wege kardinal 4 Way Diagonal 4-Wege diagonal Dead zone value to use for an analog stick. Totzonenwert für Analogsticks. Value when an analog stick is considered moved 100%. Wert für den ein Analogstick als 100% ausgelenkt betrachtet wird. The area (in degrees) that each diagonal region occupies. Den Bereich (in Grad) die jede diagonale Region einnimmt. Square Stick: quadratischer Stick: Percentage to modify a square stick coordinates to confine values to a circle Prozentsatz zur Änderung der Koordinaten einer quadratischen Stick, um die Werte auf einen Kreis zu beschränken % % Stick Delay: Stick Verzögerung: Time lapsed before a direction change is taken into effect. Abgelaufene Zeit bis eine Richtungsänderung wirksam wird. s Modifier: Modifikator: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. Bearbeiten-Button, der bei aktivem Stick aktiv ist. Diese Taste ist nützlich für die Zuweisung von Zonen mit Modifikationstasten, die verwendet werden können, um einem analogen Stick Geh-/Lauf-Funktionalität zuzuweisen. PushButton Taste Na&me: Name: Na&me: Specify the name of an analog stick. Vergebe den Namen eines Analogsticks. Mouse Settings Mauseinstellungen Standard Standard Bearing: Bearing: % Safe Zone: % Schutzzone: Eight Way 8-Wege Dead Zone: Dead Zone: Max Zone: Max Zone: Diagonal Range: diagonale Reichweite: Set Gruppe Set %1 Gruppe %1 JoyControlStickModifierButton Modifier Modifikator JoyDPad DPad DPad JoyDPadButton Up Hoch Down Runter Left Links Right Rechts Button Button JoyTabWidget <New> <Neu> Remove Entfernen Remove configuration from recent list. Entferne Konfiguration aus den letzten Einträgen. Load Laden Load configuration file. Lade Konfigurationsdatei. Save Speichern Save changes to configuration file. Änderungen in Konfigurationsdatei speichern. Save As Speichern unter Save changes to a new configuration file. Änderungen in neue Konfigurationsdatei speichern. Sets Gruppen Copy from Set Kopie aus Gruppe Settings Einstellungen Set 1 Gruppe 1 Set 2 Gruppe 2 Set 3 Gruppe 3 Set 4 Gruppe 4 Set 5 Gruppe 5 Set 6 Gruppe 6 Set 7 Gruppe 7 Set 8 Gruppe 8 Stick/Pad Assign Stick/Pad Zuweisung Controller Mapping Controllerzuweisung Quick Set Schnellkonfiguration Names Namen Toggle button name displaying. Buttonnamendarstellung wechseln. Pref Einst Change global profile settings. Globale Profileinstellungen ändern. Reset Reset Revert changes to the configuration. Reload configuration file. Änderungen der Konfiguration zurücksetzen. Neuladen der Konfiguration. Open Config Konfiguration öffnen Config Files (*.amgp *.xml) Konfigurationsdateien (*.amgp *.xml) Config File (*.%1.amgp) Konfigurationsdatei (*.%1.amgp) Do you really want to reset buttons settings for joystick? Willst du wirklich die Einstellungen der Tasten für den Joystick zurücksetzen? Save Profile Changes? Profiländerungen speichern? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Änderungen am neuen Profil wurden nicht gespeichert. Möchten Sie das aktuelle Profil speichern oder verwerfen? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Änderungen am neuen Profil %1 wurden nicht gespeichert. Möchten Sie das aktuelle Profil speichern oder verwerfen? Sticks Sticks DPads DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Es wurden keine Tasten zugewiesen. Bitte verwenden Sie den Schnellkonfiguration um Tasten zuzuweisen oder deaktivieren Sie das Ausblenden leerer Tasten. Set %1: %2 Gruppe %1: %2 Set %1 Gruppe %1 Copy Set Assignments Kopiere Gruppe-Zuweisungen Are you sure you want to copy the assignments and device properties from %1? Sind Sie sicher, dass Sie die Aufgaben-und Geräteeigenschaften von%1 kopieren möchten? Save Config Konfiguration speichern Set Gruppe Joystick Joystick Joystick JoystickStatusWindow Properties Eigenschaften Details Details Name: Name: %1 %1 Number: Nummer: Axes: Achsen: Buttons: Buttons: Hats: Hats: Battery: Batterie: Unknown Unbekannt GUID: GUID: Game Controller: Gamecontroller: Axes Achsen Buttons Buttons Hats Hats %1 (#%2) Properties %1 (#%2) Eigenschaften Axis %1 Achse %1 Hat %1 Hat %1 No Nein Yes Ja MainSettingsDialog Edit Settings Einstellungen ändern General Allgemein Controller Mappings Controllerzuweisungen Language Sprache Auto Profile Autoprofil Mouse Maus Advanced Fortgeschrittene <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Geben Sie das Standardverzeichnis an, dass das Programm im Dateidialog verwenden soll beim Laden oder Speichern eines Profils.</p></body></html> Recent Profile Count: Einträge an Profilen merken: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Anzahl der Profile, die in den letzten Profilen-Liste platziert werden können. 0 = keine Begrenzung.</p></body></html> Gamepad Poll Rate: Gamepad-Frequenz: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Ändere die Frequenz, die das Programm verwendet, um neue Ereignisse von Gamepads aus zu entdecken. Standardeinstellung: 10 ms. Eine Verringerung des Wertes kann dazu führen, dass die Anwendung mehr CPU-Leistung verbraucht. Teste daher die Einstellung, bevor du AntiMicroX unbeaufsichtigt verwendest. Hide main window when the main window close button is clicked instead of quitting the program. Verstecke Hauptfenster anstatt es zu schließen, wenn die "Schließen"-Schaltfläche gedrückt wurde. Close To Tray Schließen im Tray Have Windows start AntiMicroX at system startup. Lade AntiMicroX beim Systemstart. Launch At Windows Startup Beim Windows-Start starten Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Zeige die zuletzt benutzten Profile aller Controller als eine Liste anstatt als Untermenüs. Single Profile List in Tray Einzelprofil-Menü im Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimiere das Programm in die Taskleiste. Standardmäßig wird AntiMicroX, falls möglich, in das System-Tray minimiert. Minimize to Taskbar In die Taskleiste minimieren This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Diese Option versteckt alle Tasten denen keine Aktion zugeordnet wird. Der Schnelleinstellungs-Dialog muss benutzt werden um die Editier-Einstellungen aufzurufen. Hide Empty Buttons Verstecke leere Schaltflächen When the program is launched, open the last known profile that was opened during the previous session. Wenn das Programm gestartet wurde, öffne das zuletzt benutzte Profil. Auto Load Last Opened Profile Zuletzt geöffnetes Profil automatisch öffnen Only show the system tray icon when the program first launches. Zeige das System-Tray-Icon nur, wenn das Programm zum ersten Mal startet. Launch in Tray Starten im Tray Associate .amgp files with AntiMicroX in Windows Explorer. Assoziiere .amgp-Dateien mit AntiMicroX im Windows Explorer. Associate Profiles Assoziiere Profile Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Denke daran, dass es nicht funktioniert, wenn du diese Tastatur nicht an den Computer angeschlossen hast oder wenn die nicht wie bei Desktop-PCs eingebaut ist Attach the numeric keypad Anschluss einer numerischen Tastatur Combination of keys for quitting app Tastenkombination zum Beenden der App Choose keys combination Wähle Tastenkombination ! restart is needed after choice of combination ! ein Neustart ist nach der Wahl der Kombination erforderlich Key Repeat Tastenanschlag Active keys will be repeatedly pressed when this option is enabled. Dauerhaft gedrückte Tasten werden wiederholt gedrückt, wenn diese Option aktiviert ist. Enable Aktivieren Specifies how much time should elapse before key repeating begins. Bestimmt die Zeit die abläuft bis das Wiederholen des Tastenanschlags beginnt. Specifies how many times key presses will be performed per seconds. Bestimmt wie oft Tastenanschläge pro Sekunde durchgeführt werden. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntiMicroX wurde durch Mitwirkende in viele verschiedene Sprachen übersetzt. Standardmäßig wählt das Programm ein die entsprechende Übersetzung anhand der Einstellung Ihres Systems. Jedoch können Sie AntiMicroX eine andere Übersetzung anhand der Sprache von der Liste hierunter wählen.</p></body></html> Português do Brasil Português do Brasil Français Français Deutsch Deutsch Italiano Italiano 日本語 日本語 Русский Русский српски / srpski српски / srpski 简体中文 简体中文 Español Español українська українська Polski Polski History Si&ze: Historiengrö&ße: Weight Modi&fier: Gewichtsm&odifikator: Log File: Log-Datei: Log Level: Log-Stufe: None None Error Error Warning Warning Info Info Debug Debug Note: To see the change of log level in console output (not in log file), application restart is required Hinweis: Um die Änderung des Log-Levels in der Konsolenausgabe (nicht in der Log-Datei) zu sehen, ist ein Neustart der Anwendung erforderlich Reset Reset French Französisch Russian Russisch Serbian Serbisch Ukrainian Ukrainisch Class Klasse Title Titel Program Programm Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Deaktiviere die "Zeigerbeschleunigung verbessern" Windowseinstellung während AntiMicroX läuft. Dies erlaubt präzisere Mausbewegungen in AntiMicroX. Disable Enhance Pointer Precision Deaktiviere "Zeigerbeschleunigung verbessern" Smoothing Glättung Refresh Rate: Wiederholrate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Die Aktualisierungsrate ist die Zeitspanne, die zwischen den Mausereignissen vergeht. Seie vorsichtig, wenn du diese Einstellung änderst, da das Programm dadurch mehr CPU-Leistung verbraucht. Wenn du diesen Wert zu niedrig stellst ein, kann dies zu einer Instabilität des Systems führen. Teste die Einstellung, bevor du die unbeaufsichtigt verwendest. Spring Quelle Screen: Bildschirm: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Verwende den angegebenen Bildschirm für den Federmodus. Unter Linux wird standardmäßig der Hauptbildschirm verwendet. Unter Windows ist die Vorgabe, alle verfügbaren Bildschirme zu verwenden. Accel Numerator: Beschleunigungsnumerator: 0 0 Accel Denominator: Beschleunigungsdenominator: Accel Threshold: Beschleunigung Grenze: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Wenn die Beschleunigungswerte für die virtuelle Maus durch einen anderen Prozess geändert wurden, insbesondere beim Beenden eines älteren Spiels, dann möchtest du vielleicht die von der virtuellen Maus verwendeten Beschleunigungswerte zurücksetzen. Reset Acceleration Beschleunigung zurücksetzen Delay: Verzögerung: Pro&file Directory: Profilverzeich&nis: ms ms Rate: Rate: times/s mal/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Unten finden Sie eine Liste der benutzerdefinierten Zuordnungen, die gespeichert werden können. Sie können die folgende Tabelle verwenden, um Zuordnungen zu löschen bzw. Zuordnungen vorübergehend zu deaktivieren. Sie können auch Abbildungendeaktivieren, die in SDL enthalten sind, nur eine neue Zeile einfügen mit dem entsprechenden Joystick-GUID und prüfen deaktivieren. Die Einstellungen werden nicht wirksam werden, bis Sie entweder alle Joysticks aktualisieren oder diesen bestimmten Joystick trennen. GUID GUID Mapping String Zuweisungsstring Disable? Deaktivieren? Delete Löschen Insert Einfügen Default Standard Brazilian Portuguese Brasilianisches Portugiesisch English Englisch German Deutsch Active Aktiv Devices: Geräte: All Alles Device Gerät Profile Profil Default? Standard? Add Hinzufügen Edit Editieren Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Außerdem, Windows-Nutzer die einen geringen Wert nutzen möchten, sollten auch das "Deaktiviere 'Zeigerbeschleunigung verbessern'" Kontrollkästchen aktivieren, wenn die Option nicht in Windows deaktiviert ist. Select Default Profile Directory Wähle das Standard-Profil-Verzeichnis Are you sure you want to delete the profile? Sind Sie sicher, dass Sie das Profil löschen möchten? Save Log File As Speichere Logdatei unter Log Files (*.log) Logdateien (*.log) Do you really want to reset setting? Willst du die Einstellung wirklich zurücksetzen? Would you like to reset mappings too? Möchtest du auch Mappings zurücksetzen? [NO KEY] [KEINE TASTE] MainWindow No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Keine Joysticks gefunden. Stecken Sie eine Joystick ein und wählen Sie dann die Option "Joysticks aktualisieren" im Hauptmenü aus If events are not seen by a game, please click here to run this application as Administrator. Wenn Ereignisse von einem Spiel nicht gesehen werden, klicke hier, um diese Anwendung als Administrator auszuführen. &App &Anwendung Stick/Pad Assign Stick/Pad Zuweisung &Options &Optionen AntiMicroX If events are not seen by a game, please click here to run this application as the Adminstrator. Wenn die Ereignisse nicht erkannt werden, klicken Sie hier um als Administrator neuzustarten. &Help &Hilfe He&lp Hi&lfe &Quit B&eenden Ctrl+Q Strg+Q &Update Joysticks &Joysticks aktualisieren Ctrl+U Strg+U &Hide &Verstecken Ctrl+H Strg+H &About Ü&ber Ctrl+A Strg+A About &Qt Über &Qt Ctrl+T Ctrl+T &Properties &Eigenschaften Ctrl+P Ctrl+P &Key Checker &Tasteprüfer Ctrl+K Ctrl+K &GitHub Page &GitHub Seite Ctrl+G Ctrl+G &Game Controller Mapping &Spielcontroller-Mapping Ctrl+M Ctrl+M S&ettings &Einstellungen Ctrl+S Ctrl+S &Stick/Pad Assign &Stick/Pad-Zuordnung Ctrl+X Ctrl+X &Wiki &Wiki Ctrl+W Ctrl+W &Issues &Issues Ctrl+I Ctrl+I &Calibration &Kalibrierung Ctrl+C Ctrl+C About Qt Über Qt Properties Eigenschaften Key Checker Tastenkontrolle Home Page Webseite GitHub Page GitHub-Webseite Game Controller Mapping Gamecontroller-Zuweisung Settings Einstellungen Could not find a proper controller identifier. Exiting. Konnte keine passende Identifizierung des Controllers finden. Beenden. (%1) (%1) Open File Datei öffnen %1 battery %1 Batterie Battery level is less than %1 Der Batteriestand beträgt weniger als %1 Device number: %1 Device name: %2 Gerätenummer: %1 Name des Geräts: %2 Reading old profile Lesen des alten Profils This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 Dieses Profil verwendet die GUID-Nummern der Controller. Möchten Sie die GUID-Nummern in dieser Datei in UniqueID ändern, um sie in identischen Gamecontrollern zu verwenden? Eine solche alte Datei kann in AntiMicroX seit Version 2.25 nicht mehr geladen werden &Restore &Wiederherstellen Calibration couldn't be opened Das Kalibrierungsfenster konnte nicht geöffnet werden You must connect at least one controller to open the window Du muss mindestens einen Controller anschließen, um das Fenster zu öffnen Run as Administrator? Als Administrator ausführen? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Sind Sie sicher, dass Sie das Programm als Administrator ausführen wollen? Manche Spiele laufen als Administrator, weshalb manche Ereignisse durch AntiMicroX nicht von diesen Spielen erkannt werden, wenn AntiMicroX nicht auch als Administrator ausgeführt wird. Dies geschieht auf Grund von Erlaubnisproblemen durch Benutzerkontensteuerung (UAC) Einstellungen in Windows Vista und neuer. Failed to elevate program Berechtigungserhöhung fehlgeschlagen Failed to restart this program as the Administrator Neustart als Administrator ist fehlgeschlagen Could not find controller. Exiting. Konnte keinen Controller finden. Beenden. MouseAxisSettingsDialog Mouse Settings - Mauseinstellungen - Set %1 Set %1 MouseButtonSettingsDialog Mouse Settings - Mauseinstellungen - Set %1 Set %1 MouseControlStickSettingsDialog Mouse Settings Mauseinstellungen Set %1 Set %1 MouseDPadSettingsDialog Mouse Settings Mauseinstellungen Set %1 Set %1 MouseSettingsDialog Mouse Settings Mauseinstellungen Mouse Mode: Mausmodus: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Der Zeigermodus wird verwendet, um den Mauszeiger relativ zu der aktuellen Position auf dem Bildschirm zu bewegen je nachdem, wie viel Sie eine Achse bewegen oder wenn eine Taste gedrückt wird. Der Sprungmodus bewegt den Mauspfeil vom Mittelpunkt des Bildschirms je nach Bewegung einer Achse. Der Mauspfeil wandert zu seinem Mittelpunkt, wenn eine Achse zur Dead Zone zurück kehrt. Cursor Zeiger Spring Sprung Acceleration: Beschleunigung: Enhanced Precision Verbesserte Präzision Linear linear Quadratic quadratisch Cubic kubisch Quadratic Extreme extrem quadratisch Power Function Power Funktion Easing Quadratic Erleichternd quadratisch Easing Cubic Erleichternd kubisch Mouse Speed Settings Einstellungen der Mausgeschwindigkeit Enable to change the horizontal and vertical speed boxes at the same time. Aktivieren, um die horizontale und vertikale Geschwindigkeitseinstellungen zur gleichen Zeit zu ändern. Change Together Zusammen ändern Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Optionen, die ermöglichen deiner Mausbewegung mehr Beschleunigung hinzuzufügen, als sich aus der Beschleunigungskurve ergeben hätte. Je nachdem, wie schnell die Achse auf dem Gamepad bewegt wird, wird eine Beschleunigung hinzugefügt. Dies soll helfen, einige der Probleme mit dem sehr begrenzten Eingangsbereich zu umgehen, der bei typischen Gamepad-Analog-Sticks zur Verfügung steht. Delta Acceleration Deltabeschleunigung &Multiplier: &Multiplikator: Mi&n Threshold: Mi&n Grenze: Horizontal Speed: Geschw. horizontal: 1 = 20 pps 1 = 20 pps Vertical Speed: Geschw. vertikal: Wheel Hori. Speed: Rad-Gesch. horizontal: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Stellen Sie die Geschwindigkeit für die horizontale Mausrad-Bewegung entsprechend der Anzahl der simulierten Raster pro Sekunde ein. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Stellen Sie die Geschwindigkeit für die vertikale Mausrad-Bewegung entsprechend der Anzahl der simulierten Raster pro Sekunde ein. Sensitivit&y: Sensibilitä&t: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Für die Beschleunigungskurve des Power-funktiones. Gibt den Faktor an, der für die Kurvenempfindlichkeit verwendet werden soll. Wenn der Wert über 1,0 liegt, wird die Mausbewegung am unteren Ende einer Achse schneller beschleunigt. Easing Duration: Erleichternde Dauer: s Extra Acceleration Zusätzliche Beschleunigung Multiplier: Multiplikator: Highest value to accelerate mouse movement by Höchster Wert zur Beschleunigung der Mausbewegung durch x x Start %: Start %: Acceleration begins at this percentage of the base multiplier Die Beschleunigung beginnt bei diesem Prozentsatz des Basismultiplikators Minimum amount of axis travel required for acceleration to begin Minimaler Achshub zum Starten der Beschleunigung erforderlich Max Threshold: Max Grenze: Maximum axis travel before acceleration has reached the multiplier value Maximaler Achsabstand vor Erreichen des Multiplikator-Beschleunigungswertes E&xtra Duration: zu&sätzliche Dauer: Curve: Kurve: Ease Out Sine Ease Out Sinus Ease Out Quad Ease Out quadratisch Ease Out Cubic Ease Out kubisch Release Radius: Freigabe-Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Wenn aktiviert, Besagt, dass das Ursprungs-arreal durch ein nicht-relativen Ursprung relativ zur Mausposition sein wird. Relative Relativ Mouse Status Maus-Status X: X: 0 (0 pps) 0 (0 pps) Y: Y: 1 = 1 notch(es)/s 1 = 1 Raste Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Erweitert: Dreistufige Kurve, die die Maus bewegen lässt langsam am unteren Ende einer Achse und schnell am oberen Ende. Linear: Die Maus bewegt sich proportional zur Achse. Quadratisch: Die Maus wird am unteren Ende langsam beschleunigt. Kubisch: Kubisch: Die Maus wird langsamer als quadratisch beschleunigt. Quadratisch Extrem: Mausgeschwindigkeit wird einmal um das 1,5-fache erhöht. Der Verfahrweg von 95% der Achsen ist erreicht. Power-Funktion: Ermöglicht eine individuellere Kurvenoption. Erleichternd quadratisch: Quadratisch: Die Achse wird mit Hilfe einer quadratischen Kurve über einen bestimmten Zeitraum allmählich beschleunigt. Erleichternd kubisch: Das obere Ende der Achse wird allmählich beschleunigt über eine Zeitspanne unter Verwendung einer kubischen Kurve. Hori&zontal Speed: hori&zontale Geschwindigkeit: &Vertical Speed: &vertikale& Geschwindigkeit: Wheel Vert. Speed: Rad-Gesch vertikal: Sensitivity: Empfindlichkeit: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. Gibt die Zeit (in Sekunden) an, die benötigt wird, bevor die Maus nach Erreichen des oberen Endes einer Achse voll beschleunigt wird. % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Verlängert die Zeit, während der eine zusätzliche Beschleunigung angewendet wird. Achsbewegungen werden berücksichtigt. Langsameres Flackern reduziert die tatsächliche Zeit, für die eine zusätzliche Beschleunigung angewendet wird. Spring Settings Sprungeinstellungen Spring Width: Sprungweite: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Ändert die Breite der Region, die der Mauszeiger im Sprungmodus zurück legt. 0 wird die gesamte Breite auf Ihrem Bildschirm nutzen. Spring Height: Sprunghöhe: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Ändert die Höhe der Region, die der Mauszeiger im Sprungmodus zurück legt. 0 wird die gesamte Höhe auf Ihrem Bildschirm nutzen. %n notch(es)/s %n notch/s %n notches/s ProfileImporter Form Formular Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Abbrechen OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Tastenkontrolle <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Drücke eine Taste auf deiner Tastatur, um zu sehen, wie die Taste von dieser Anwendung erkannt wird. Das Fenster zeigt den systemeigenen Tastewert, den von Qt angegebenen Originalwert (falls zutreffend) und den von AntiMicroX verwendeten benutzerdefinierten Wert.</p><p>Der Tastewert von AntiMicroX und der Tastewert von Qt sind in der Regel gleich. AntiMicroX versucht, wenn möglich die in Qt definierten Tastewerte zu verwenden. Prüfe die Seite <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> Prüfe ob eine Liste der durch Qt definierten Werte auf der Seite vorhanden ist. Wenn du stellst fest, dass ein Wert von diesem Programm nicht unterstützt wird, melde das Problem an AntimicroX <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;"> GitHub-Seite</span></a> so dass das Programm direkt zur Unterstützung bearbeitet werden kann. Unbekannten Werten wird ein benutzerdefiniertes Präfix hinzugefügt, damit sie weiterhin verwendet werden können; das Hauptproblem besteht darin, dass das Profil nicht mehr portabel ist.</p></body></html> Event Handler: Ereignisbehandler: Native Key Value: Nativer Tastenwert: 0x00000000 0x00000000 Qt Key Value: Qt-Tastenwert: antimicro Key Value: Wert der Taste (AntiMicroX): QObject Super Super Menu Menü Mute Stummschalten Play/Pause Wiedergabe/Pause Play Wiedergabe Prev Zurück Next Vor Mail EMail Home Pos1 Search Suche Launch program with the tray menu disabled Starte das Programm mit deaktiviertem Traymenü Launch program without the main window displayed Starte das Programm, ohne das Hauptfenster anzuzeigen Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Starte das Programm mit der Konfigurationsdatei, die als Standard für ausgewählte Regler ausgewählt wurde. Standardeinstellung für alle Controller location Location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Konfigurationsdatei auf einen bestimmten Controller anwenden. Der Wert kann ein Controller-Index, ein Name oder eine GUID sein value Wert Unload currently enabled profile(s) Aktuell aktivierte(s) Profil(e) entladen value(s) Wert(e) Start joysticks on a specific set. Value can be a controller index, name, or GUID Starte Joysticks auf einem bestimmten Satz. Der Wert kann ein Controller-Index, ein Name oder eine GUID sein number value Nummernwert Launch program as a daemon. Use only on Linux. Starte das Programm als Dämon. Verwendung nur unter Linux. Enable logging Logging aktivieren log-type Log-type Choose a file for logs writing Wähle eine Datei zum Schreiben von Loggen filename Dateiname Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Wähle zwischen der Verwendung von XTest-Unterstützung und der Unterstützung von uinput für die Ereigniserzeugung. Verwende nur, wenn du die Optionen xtest und uinput unter Linux oder vmulti unter Windows aktiviert hast. Voreinstellung: xtest. event-generation-type event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Drucke Informationen über von SDL erkannte Joysticks aus. Verwende nur, wenn du über eine sdl-Bibliothek verfügst. Du kannst den Index, den Namen oder sogar die GUID Ihres Controllers überprüfst. Daemon launched Dienst gestartet Failed to launch daemon Dienst konnte nicht gestartet werden Launching daemon Starte Dienst Display string "%1" is not valid. Die Anzeigezeichenfolge "%1" ist nicht gültig. Failed to set a signature id for the daemon Signatur-ID konnte für den Dienst nicht gesetzt werden Failed to change working directory to / Arbeitsverzeichnis konnte nicht gesetzt werden zu / Quitting Program Beende Programm # of joysticks found: %1 # an Joysticks gefunden: %1 List Joysticks: Liste der Joysticks: --------------- Joystick %1: Index: %1 Index: %1 UniqueID: %1 UniqueID: %1 GUID: %1 GUID: %1 VendorID: %1 VendorID: %1 ProductID: %1 ProductID: %1 Product Version: %1 Produktversion: %1 Name: %1 Yes Ja No Nein Game Controller: %1 # of Axes: %1 # der Achsen: %1 # of Buttons: %1 # der Knöpfe: %1 # of Hats: %1 # der Hats: %1 Attempting to use fallback option %1 for event generation. Versuche Fallback-Option %1 zur Ereignisgenerierung. Failed to open event generator. Exiting. Öffnen des Ereignisgenerators fehlgeschlagen. Breche ab. Using %1 as the event generator. Nutze %1 als Ereignisgenerator. Could not raise process priority. Konnte Prozesspriorität nicht erhöhen. Last button Letzte Taste There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? In den Daten gibt es keine zuletzt vom Gamepad aus gedrückte Taste. Hast du mindestens eine Taste des Gamepads für die Tastatur eingestellt? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Aktives Fenster geändert auf: Titel = "%1", Klasse = "%2", Programm = "%3" oder "%4". Profile location %1 is not an XML file. Profilort %1 ist keine XML Datei. Profile location %1 does not exist. Profilort %1 existiert nicht. Controller identifier is not a valid value. Controllernummer ist keine gültige Ziffer. An invalid set number '%1' was specified. Es wurde eine ungültige Gruppenummer '%1' angegeben. Controller identifier '%s'' is not a valid value. Der Controller-Bezeichner '%s' ist kein gültiger Wert. No set number was specified. Keine Gruppe gewählt. No controller was specified. Kein Controller wurde spezifiert. No display string was specified. Es wurde keine Anzeigezeichenfolge angegeben. An invalid event generator was specified. Ein ungültiger Ereignisgenerator wurde angegeben. No event generator string was specified. Kein Ereignesgenerator String wurde angegeben. Qt style flag was detected but no style was specified. Qt style Parameter erkannt, aber kein Style spezifiziert. No log file specified. Keine Logdatei angegeben. AntiMicroX version AntiMicroX Version Options Optionen Print help text. diese Hilfe ausgeben. Print version information. Programmversion ausgeben. Launch program in system tray only. Nur im Systemtray starten. Launch program with the tray menu disabled. Starten mit deaktiviertem Systemtray. Launch program without the main window displayed. Starten mit verstecktem Hauptfenster. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Programm mit ausgewählter Konfigurations- datei als Standard für alle Controller starten. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Übernehme Konfigurationsdatei zu dem angegebenen Controller. Wert kann Controllerindex, Name oder GUID sein. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Aktuell aktiviertes Profil entladen. Wert kann Controllerindex, Name oder GUID sein. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Starte Joysticks beim angegebenen Set. Wert kann Controllerindex, Name oder GUID sein. Launch program as a daemon. Starte Programm als Dienst. Enable logging. Aktiviere Logging. Use specified display for X11 calls. Useful for ssh. Nutze angegebenes Display für X11. Nützlich für ssh. Choose between using XTest support and uinput support for event generation. Default: xtest. Wähle zwischen XTest Unterstützung und uinput Unterstützung zur Ereignisgenerierung. Standard: xtest. Choose between using SendInput and vmulti support for event generation. Default: sendinput. Wähle zwischen der Nutzung von SendInput und vmulti support zur Ereignisgenerierung. Standard: sendinput. Print information about joysticks detected by SDL. Zeige Informationen über Joysticks die von SDL erkannt wurden. Open game controller mapping window of selected controller. Value can be a controller index or GUID. Öffne Gamecontrollerzuweisungs-Fenster für den ausgewählten Controller. Wert kann ein Controller Index oder GUID sein. Logging started Logging gestartet Auto-switching to profile "%1". Automatische Umschaltung auf das Profil "%1". Auto-switching to nullptr profile! Automatisches Umschalten auf das Nullptr-Profil! xinput version must be at least 2.0. No mouse acceleration changes will occur. xinput Version muss mindestens 2.0 sein. Es wird keine Mausbeschleunigungsänderungen geben. QuickSetDialog Quick Set Schnellkonfiguration <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Bitte drücken Sie eine Taste oder bewegen Sie eine Achse auf %1 (<span style=" font-weight:600;">%2</span>).<br/>Dann erscheint ein Dialogfenter, dass Ihnen <br>erlaubt eine Zuordnung zu machen.</p></body></html> Quick Set %1 Schnellkonfiguration %1 SetAxisThrottleDialog Throttle Change Schubänderung The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? Auf Achse %1 wurde der Schub verändert. Möchten Sie die Änderungen an alle Sets übertragen? SetJoystick Set %1: %2 Set %1: %2 Set %1 Set %1 SetNamesDialog Set Name Settings Setnameneinstellungen Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Name Name SimpleKeyGrabberButton Mouse Maus SpringModeRegionPreview Spring Mode Preview Sprungmodus-Vorschau UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Konnte keine gültiges uinput Gerätedatei finden. Bitte überprüfen Sie, ob das uinput Modul geladen ist. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Konnte nicht uinput Gerätedatei öffnen Bitte überprüfen Sie ob Sie die Berechtigung haben auf dieses Gerät zu schreiben Using uinput device file %1 Nutze uinput Gerätedatei %1 UInputHelper a b c d e f g h i j k l m n o p q r s t u v w x y z Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - = BackSpace Rücktaste Tab Tabulator [ ] \ CapsLock Feststell ; ' Enter Eingabe Shift_L Umschalt_L , . / Ctrl_L Strg_L Super_L Super_L Alt_L Alt_L Space Leertaste Alt_R Alt_R Menu Menü Ctrl_R Strg_R Shift_R Umschalt_R Up Hoch Left Links Down Runter Right Rechts PrtSc Druck Ins Einfg Del Entf Home Pos1 End Ende PgUp Bild ↑ PgDn Bild ↓ NumLock * + KP_Enter KP_Enter KP_1 KP_1 KP_2 KP_2 KP_3 KP_3 KP_4 KP_4 KP_5 KP_5 KP_6 KP_6 KP_7 KP_7 KP_8 KP_8 KP_9 KP_9 KP_0 KP_0 SCLK Rol ↓ Pause Pause Super_R Mute Stumm VolDn Vol- VolUp Vol+ Play Wiedergabe Stop Prev Zurück Next Vor [NO KEY] [KEINE TASTE] UnixWindowInfoDialog Captured Window Properties Erkannte Fenstereigenschaften Information About Window Informationen über das Fenster Class: Klasse: TextLabel TextEtikett Title: Titel: Path: Pfad: Match By Properties Nach Eigenschaften zuordnen Class Klasse Title Titel Path Pfad VDPad VDPad VDPad VirtualKeyPushButton Space Leertaste Tab Shift (L) Umschalt (L) Shift (R) Umschalt (R) Ctrl (L) Strg (L) Ctrl (R) Strg (R) Alt (L) Alt (L) Alt (R) Alt (R) Alt Gr Alt Gr ` ~ - = [ ] \ Caps Feststell ; ' , . / ESC PRTSC Drucken SCLK Rollen INS Einfg PGUP Bild ↑ DEL Entf PGDN Bild ↓ 1 2 3 4 5 6 7 8 9 0 NUM LK NUM LOCK * + Enter Eingabe Del Entf E N T E R E I N G A B E < : Super (L) Menu Menü Up Hoch Down Runter Left Links Right Rechts VirtualKeyboardMouseWidget Keyboard Tastatur Mouse Maus Mouse Settings Mauseinstellungen Left Mouse Links Up Mouse Hoch Left Button Mouse Linke Taste Middle Button Mouse Mittlere Taste Right Button Mouse Rechte Taste Wheel Up Mouse Mausrad hoch Wheel Left Mouse Mausrad links Wheel Right Mouse Mausrad rechts Wheel Down Mouse Mausrad runter Down Mouse Runter Right Mouse Rechts Button 4 Mouse Taste 4 Mouse 8 Mouse Taste 8 Button 5 Mouse Taste 5 Mouse 9 Mouse Taste 9 NONE KEINE [NO KEY] [KEINE TASTE] Last button Letzte Taste Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Slots für die Tasten konnten nicht gelöscht werden, da es keine Taste für das Gamepad auf der Tastatur gab. Belege mindestens eine Taste von der Tastatur für das Gamepad Others Andere Browser Back Browser Back Browser Favorites Browser Favorites Browser Forward Browser Forward Browser Home Browser Home Browser Refresh Browser Refresh Browser Search Browser Search Browser Stop Browser Stop Calc Calc Email Email F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media Media Media Next Media Next Media Play Media Play Media Previous Media Previous Media Stop Media Stop Search Suche Volume Down Volume Down Volume Mute Volume Mute Volume Up Volume Up VirtualMousePushButton INVALID UNGÜLTIG WinAppProfileTimerDialog Capture Application Wähle Applikation After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Wählen Sie das Fenster aus mit dem Sie das Profil assozieren möchten, nachdem Sie auf den "Wähle Applikation" Button geklickt haben. Die aktive Applikation wird nach der angegebenen Zahl an Sekunden ausgewählt. Seconds Sekunden Cancel Abbrechen WinExtras [NO KEY] [KEINE TASTE] X11Extras ESC Tab Tabulator Space Leertaste DEL Entf Return Eingabe KP_Enter KP_Enter Backspace Rücktaste Alt Gr Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput Erweiterung wurde nicht gefunden. Es wird keine Mausbeschleunigungsänderungen geben. xinput version must be at least 2.0. No mouse acceleration changes will occur. xinput Version muss mindestens 2.0 sein. Es wird keine Mausbeschleunigungsänderungen geben. Virtual pointer found with id=%1. Virtueller Mauszeiger mit id=%1 gefunden. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 PtrFeedbackCalls wurde nicht für den virtuellen Mauszeiger gefunden. Es wird keine Mausbeschleunigungsänderungen für das Gerät mit id=%1 geben Changing mouse acceleration for device with id=%1 Ändere Mausbeschleunigung für Gerät der id=%1 XMLConfigReader Could not write updated profile XML to file %1. Konnte aktuelles Profil nicht als XML in Datei %1 schreiben. XMLConfigWriter Could not write to profile at %1. Konnte Profil nicht schreiben in %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. Grafisches Programm zur Zuordnung von Tastatur- und Maussteuerungen zu einem Gamepad. Nützlich für das Spielen von Spielen ohne Gamepad-Unterstützung. main Launch program in system tray only. Nur im Systemtray starten. Launch program with the tray menu disabled Starte das Programm mit deaktiviertem Traymenü Launch program without the main window displayed Starte das Programm, ohne das Hauptfenster anzuzeigen Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Starte das Programm mit der Konfigurationsdatei, die als Standard für ausgewählte Regler ausgewählt wurde. Standardeinstellung für alle Controller location Location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Konfigurationsdatei auf einen bestimmten Controller anwenden. Der Wert kann ein Controller-Index, ein Name oder eine GUID sein value Wert Unload currently enabled profile(s) Aktuell aktivierte(s) Profil(e) entladen value(s) Wert(e) Start joysticks on a specific set. Value can be a controller index, name, or GUID Starte Joysticks auf einem bestimmten Satz. Der Wert kann ein Controller-Index, ein Name oder eine GUID sein number value Nummernwert Launch program as a daemon. Use only on Linux. Starte das Programm als Dämon. Verwendung nur unter Linux. Enable logging Logging aktivieren log-type Log-type Choose a file for logs writing Wähle eine Datei zum Schreiben von Loggen filename Dateiname Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Wähle zwischen der Verwendung von XTest-Unterstützung und der Unterstützung von uinput für die Ereigniserzeugung. Verwende nur, wenn du die Optionen xtest und uinput unter Linux oder vmulti unter Windows aktiviert hast. Voreinstellung: xtest. event-generation-type event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Drucke Informationen über von SDL erkannte Joysticks aus. Verwende nur, wenn du über eine sdl-Bibliothek verfügst. Du kannst den Index, den Namen oder sogar die GUID Ihres Controllers überprüfst. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_en.ts000066400000000000000000021572511377703515000275070ustar00rootroot00000000000000 AboutDialog About About Version Version <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Copyright: 2013 - 2020 Copyright: 2013 - 2018 Copyright: 2013 - 2018 Info Info <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicroX group at https://github.com/AntiMicroX, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicroX group at https://github.com/AntiMicroX, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> Changelog Changelog Credits Credits AntiMicroX AntiMicroX About Development About Development License License Program Version %1 Program Version %1 Program Compiled on %1 at %2 Program Compiled on %1 at %2 Built Against SDL %1 Built Against SDL %1 Running With SDL %1 Running With SDL %1 Using Qt %1 Using Qt %1 Using Event Handler: %1 Using Event Handler: %1 AddEditAutoProfileDialog Auto Profile Dialog Auto Profile Dialog Profile: Profile: Pro&file: Pro&file: Browse Browse Window: Window: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties Detect Window Properties &Class: &Class: T&itle: T&itle: Class: Class: Title: Title: set partial title set partial title Application: Application: Select Select De&vices: De&vices: Devices: Devices: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller Set as Default for Controller A different profile is already selected as the default for this device. A different profile is already selected as the default for this device. Current (%1) Current (%1) Open Config Open Config Select Program Select Program Programs (*.exe) Programs (*.exe) Please use the main default profile selection. Please use the main default profile selection. Main Profile Main Profile Already selected Already selected Chosen Profile Chosen Profile The selection will be used instead of the all default profile option. The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Please select a window by using the mouse. Press Escape if you want to cancel. Capture Application Window Capture Application Window Could not obtain information for the selected window. Could not obtain information for the selected window. Application Capture Failed Application Capture Failed Profile file path is invalid. Profile file path is invalid. No window matching property was specified. No window matching property was specified. Program path is invalid or not executable. Program path is invalid or not executable. File is not an .exe file. File is not an .exe file. No window matching property was selected. No window matching property was selected. AdvanceButtonDialog Advanced Advanced Assignments Assignments Toggle Toggle Turbo Turbo Set Selector Set Selector Blank or KB/M Blank or KB/M Hold Hold Pause Pause Cycle Cycle Distance Distance Insert Insert Delete Delete Clear All Clear All Time: Time: 0.01s 0.01s 0s 0s Insert a pause that occurs in between key presses. Insert a pause that occurs in between key presses. Release Release Insert a new blank slot. Insert a new blank slot. Delete a slot. Delete a slot. Clear all currently assigned slots. Clear all currently assigned slots. Specify the duration of an inserted Pause or Hold slot. Specify the duration of an inserted Pause or Hold slot. 0m 0m &Mouse Speed Mod: &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Specify the range past an axis dead zone in which a sequence of actions will execute. Distance: Distance: % % Mouse Mod Mouse Mod Press Time Press Time Delay Delay Execute Execute Load Load Set Change Set Change Text Entry Text Entry Join Join Split Split Placeholder Placeholder 0 0 Set the percentage that mouse speeds will be modified by. Set the percentage that mouse speeds will be modified by. Auto Reset Cycle After Auto Reset Cycle After seconds seconds Executable: Executable: ... ... Arguments: Arguments: Enabled Enabled Mode: Mode: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Normal Gradient Gradient Pulse Pulse Delay: Delay: 0.10s 0.10s Rate: Rate: 10.0/s 10.0/s Disabled Disabled Select Set 1 One Way Select Set 1 One Way Select Set 1 Two Way Select Set 1 Two Way Select Set 1 While Held Select Set 1 While Held Select Set 2 One Way Select Set 2 One Way Select Set 2 Two Way Select Set 2 Two Way Select Set 2 While Held Select Set 2 While Held Select Set 3 One Way Select Set 3 One Way Select Set 3 Two Way Select Set 3 Two Way Select Set 3 While Held Select Set 3 While Held Select Set 4 One Way Select Set 4 One Way Select Set 4 Two Way Select Set 4 Two Way Select Set 4 While Held Select Set 4 While Held Select Set 5 One Way Select Set 5 One Way Select Set 5 Two Way Select Set 5 Two Way Select Set 5 While Held Select Set 5 While Held Select Set 6 One Way Select Set 6 One Way Select Set 6 Two Way Select Set 6 Two Way Select Set 6 While Held Select Set 6 While Held Select Set 7 One Way Select Set 7 One Way Select Set 7 Two Way Select Set 7 Two Way Select Set 7 While Held Select Set 7 While Held Select Set 8 One Way Select Set 8 One Way Select Set 8 Two Way Select Set 8 Two Way Select Set 8 While Held Select Set 8 While Held [NO KEY] [NO KEY] sec. sec. /sec. /sec. Not checked slots Not checked slots To delete slots, you need to select at least one To delete slots, you need to select at least one To insert slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Unknown current slot Click on chosen slots before joining them Click on chosen slots before joining them Not enough slots Not enough slots It's impossible to join slots. Add at least one other slot. It's impossible to join slots. Add at least one other slot. Not selected slots Not selected slots It's impossible to join slots. Select at least two slots before joining them It's impossible to join slots. Select at least two slots before joining them Only keyboard slots Only keyboard slots It's only possible to join simple and mix keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. It's impossible to split slots. Add at least one other slot. Not selected slot Not selected slot Select your slot before splitting. Select your slot before splitting. Too many mix slots Too many mix slots Select one mix slot. Select one mix slot. Only mix slots Only mix slots It's only possible to split mix slot. It's only possible to split mix slot. Empty execution path Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist File doesn't exist There is no such file locally, that could be executed. Check the file on your system There is no such file locally, that could be executed. Check the file on your system Set %1 Set %1 Select Set %1 Select Set %1 One Way One Way Two Way Two Way While Held While Held Choose Executable Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Choose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Execute program when slot is activated. Choose Profile Choose Profile Config Files (*.amgp *.xml) Config Files (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Stick/Pad Assignment Sticks Sticks DPads DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Joystick %2) Stick 1 Stick 1 Enabled Enabled Assign Assign X Axis: X Axis: Y Axis: Y Axis: Stick 2 Stick 2 Number of Physical DPads: %1 Number of Physical DPads: %1 Virtual DPad 1 Virtual DPad 1 Up: Up: Down: Down: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Left: Left: Right: Right: Axis %1 Axis %1 Axis %1 - Axis %1 - Axis %1 + Axis %1 + Button %1 Button %1 Move stick 1 along the X axis Move stick 1 along the X axis Move stick 1 along the Y axis Move stick 1 along the Y axis Move stick 2 along the X axis Move stick 2 along the X axis Move stick 2 along the Y axis Move stick 2 along the Y axis Press a button or move an axis Press a button or move an axis AxisEditDialog Axis Axis Mouse (Horizontal) Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Vertical) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Up | Down Arrows: Left | Right Arrows: Left | Right Keys: W | S Keys: W | S Keys: A | D Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 NumPad: KP_4 | KP_6 None None Set the value to use as the limit for an axis. Useful for a worn out analog stick. Set the value to use as the limit for an axis. Useful for a worn out analog stick. Negative Half Throttle Negative Half Throttle Positive Half Throttle Positive Half Throttle Name: Name: Specify the name of an axis. Specify the name of an axis. Mouse Settings Mouse Settings Set the value of the dead zone for an axis. Set the value of the dead zone for an axis. Presets: Presets: Dead Zone: Dead Zone: Max Zone: Max Zone: [NO KEY] [NO KEY] Throttle setting that determines the behavior of how to interpret an axis hold or release. Throttle setting that determines the behavior of how to interpret an axis hold or release. Negative Throttle Negative Throttle Normal Normal Positive Throttle Positive Throttle Current Value: Current Value: Set Set Set %1 Set %1 Left Mouse Button Left Mouse Button Right Mouse Button Right Mouse Button ButtonEditDialog Dialog Dialog To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Placeholder Placeholder Toggle Toggle Enables a key press or release to only occur when a controller button is pressed. Enables a key press or release to only occur when a controller button is pressed. Enables rapid key presses and releases. Turbo controller. Enables rapid key presses and releases. Turbo controller. Turbo Turbo Last keyboard/mouse button: Last keyboard/mouse button: Slots Slots Na&me: Na&me: Specify the name of a button. Specify the name of a button. Action: Action: Specify the action that will be performed in game while this button is being used. Specify the action that will be performed in game while this button is being used. Advanced Advanced Choose your keyboard key Choose your keyboard key No button No button Last button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice No choice Before you open window with advanced settins, you have to choice a key Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set As last gamepad button has been set Index %1 Index %1 [NO KEY] [NO KEY] Calibration Form Form Start calibration Start calibration Controller: Controller: Sticks: Sticks: Use settings from jstest-gtk Use settings from jstest-gtk Reset settings Reset settings Cancel Cancel Save Save Calibration Calibration Do you really want to reset settings of current axes? Do you really want to reset settings of current axes? Do you really want to reset settings of current axis? Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Calibrating center Start second step Start second step Center X: %1 Center X: %1 Center Y: %1 Center Y: %1 Place the joystick in the top-left corner many times Place the joystick in the top-left corner many times Calibrating position Calibrating position X: %1 X: %1 Y: %1 Y: %1 Place the joystick in the bottom-right corner Place the joystick in the bottom-right corner Start final step Start final step range X: %1 - %2 range X: %1 - %2 range Y: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone X: %1 deadzone Y: %1 deadzone Y: %1 ---Calibration done!--- ---Calibration done!--- Calibration values have been saved Calibration values have been saved Dead zone calibration Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Do you want to save calibration of current axis? You must move X axis to the right at least five times! Keep moving! You must move X axis to the right at least five times! Keep moving! You must move X axis to the left at least five times! Keep moving! You must move X axis to the left at least five times! Keep moving! Axis %1 Axis %1 CapturedWindowInfoDialog Captured Window Properties Captured Window Properties Information About Window Information About Window Class: Class: TextLabel TextLabel Title: Title: Path: Path: Match By Properties Match By Properties Class Class Title Title Path Path Full Path Full Path File Name File Name DPadContextMenu Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Standard Standard Eight Way Eight Way 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal Mouse Settings Mouse Settings DPadEditDialog Dialog Dialog Presets: Presets: Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Dpad Mode: Dpad Mode: &Name: &Name: 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal DPad Delay: DPad Delay: Time lapsed before a direction change is taken into effect. Time lapsed before a direction change is taken into effect. s s Specify the name of a dpad. Specify the name of a dpad. Mouse Settings Mouse Settings Standard Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way Eight Way Set Set Set %1 Set %1 EditAllDefaultAutoProfileDialog Default Profile Default Profile Profile: Profile: Browse Browse Open Config Open Config Profile file path is invalid. Profile file path is invalid. ExtraProfileSettingsDialog Extra Profile Settings Extra Profile Settings Key Press Time: Key Press Time: 0.00 ms 0.00 ms Profile Name: Profile Name: s s GameController Game Controller Game Controller GameControllerDPad DPad DPad GameControllerMappingDialog Game Controller Mapping Game Controller Mapping <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A A B B X X Y Y Back Back Start Start Guide Guide Left Shoulder Left Shoulder Right Shoulder Right Shoulder Left Stick Click Left Stick Click Right Stick Click Right Stick Click Left Stick X Left Stick X Left Stick Y Left Stick Y Right Stick X Right Stick X Right Stick Y Right Stick Y Left Trigger Left Trigger Right Trigger Right Trigger DPad Up DPad Up DPad Left DPad Left DPad Down DPad Down DPad Right DPad Right Mapping Mapping SDL 2 Game Controller Mapping String SDL 2 Game Controller Mapping String Last Axis Event: Last Axis Event: Current Axis Detection Dead Zone: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Game Controller Mapping (%1) (#%2) Discard Controller Mapping? Discard Controller Mapping? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. GameControllerSet Back Back Guide Guide Start Start LS Click LS Click RS Click RS Click L Shoulder L Shoulder R Shoulder R Shoulder L Trigger L Trigger R Trigger R Trigger GameControllerTrigger Trigger Trigger JoyAxis Axis Axis JoyAxisButton Negative Negative Positive Positive Unknown Unknown Button Button JoyAxisContextMenu Mouse (Horizontal) Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Vertical) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Up | Down Arrows: Left | Right Arrows: Left | Right Keys: W | S Keys: W | S Keys: A | D Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 NumPad: KP_4 | KP_6 None None Mouse Settings Mouse Settings Left Mouse Button Left Mouse Button Right Mouse Button Right Mouse Button JoyButton Processing turbo for #%1 - %2 Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Distance change for button #%1 - %2 Button Button [NO KEY] [NO KEY] [Set %1 1W] [Set %1 1W] [Set %1 2W] [Set %1 2W] [Set %1 WH] [Set %1 WH] JoyButtonContextMenu Toggle Toggle Turbo Turbo Clear Clear Set Select Set Select Disabled Disabled Set %1 Set %1 Set %1 1W Set %1 1W Set %1 2W Set %1 2W Set %1 WH Set %1 WH JoyButtonSlot Mouse Mouse Up Up Down Down Left Left Right Right LB LB MB MB RB RB B4 B4 B5 B5 Pause Pause Hold Hold Cycle Cycle Distance Distance Release Release Mouse Mod Mouse Mod Press Time Press Time Delay Delay Load %1 Load %1 Set Change %1 Set Change %1 [Text] %1 [Text] %1 [Exec] %1 [Exec] %1 [NO KEY] [NO KEY] JoyControlStick Stick Stick JoyControlStickButton Up Up Down Down Left Left Right Right Button Button JoyControlStickContextMenu Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Standard Standard Eight Way Eight Way 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal Mouse Settings Mouse Settings JoyControlStickEditDialog Dialog Dialog X: X: 0 0 Y: Y: Distance: Distance: Presets: Presets: Mouse (Normal) Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Arrows Keys: W | A | S | D Keys: W | A | S | D NumPad NumPad None None Stick Mode: Stick Mode: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4 Way Cardinal 4 Way Diagonal 4 Way Diagonal Dead zone value to use for an analog stick. Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. The area (in degrees) that each diagonal region occupies. Square Stick: Square Stick: Percentage to modify a square stick coordinates to confine values to a circle Percentage to modify a square stick coordinates to confine values to a circle % % Stick Delay: Stick Delay: Time lapsed before a direction change is taken into effect. Time lapsed before a direction change is taken into effect. s s Modifier: Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton PushButton Na&me: Name: Na&me: Specify the name of an analog stick. Specify the name of an analog stick. Mouse Settings Mouse Settings Standard Standard Bearing: Bearing: % Safe Zone: % Safe Zone: Eight Way Eight Way Dead Zone: Dead Zone: Max Zone: Max Zone: Diagonal Range: Diagonal Range: Set Set Set %1 Set %1 JoyControlStickModifierButton Modifier Modifier JoyDPad DPad DPad JoyDPadButton Up Up Down Down Left Left Right Right Button Button JoyTabWidget <New> <New> Remove Remove Remove configuration from recent list. Remove configuration from recent list. Load Load Load configuration file. Load configuration file. Save Save Save changes to configuration file. Save changes to configuration file. Save As Save As Save changes to a new configuration file. Save changes to a new configuration file. Sets Sets Copy from Set Copy from Set Settings Settings Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Stick/Pad Assign Stick/Pad Assign Controller Mapping Controller Mapping Quick Set Quick Set Names Names Toggle button name displaying. Toggle button name displaying. Pref Pref Change global profile settings. Change global profile settings. Reset Reset Revert changes to the configuration. Reload configuration file. Revert changes to the configuration. Reload configuration file. Open Config Open Config Config Files (*.amgp *.xml) Config Files (*.amgp *.xml) Config File (*.%1.amgp) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Do you really want to reset buttons settings for joystick? Save Profile Changes? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks Sticks DPads DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 Set %1: %2 Set %1 Set %1 Copy Set Assignments Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Are you sure you want to copy the assignments and device properties from %1? Save Config Save Config Set Set Joystick Joystick Joystick JoystickStatusWindow Properties Properties Details Details Name: Name: %1 %1 Number: Number: Axes: Axes: Buttons: Buttons: Hats: Hats: Battery: Battery: Unknown Unknown GUID: GUID: Game Controller: Game Controller: Axes Axes Buttons Buttons Hats Hats %1 (#%2) Properties %1 (#%2) Properties Axis %1 Axis %1 Hat %1 Hat %1 No No Yes Yes MainSettingsDialog Edit Settings Edit Settings General General Controller Mappings Controller Mappings Language Language Auto Profile Auto Profile Mouse Mouse Advanced Advanced Profile Direc&tory: Profile Direc&tory: <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> Recent Profile Count: Recent Profile Count: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> Gamepad Poll Rate: Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Hide main window when the main window close button is clicked instead of quitting the program. Close To Tray Close To Tray Have Windows start AntiMicroX at system startup. Have Windows start AntiMicroX at system startup. Launch At Windows Startup Launch At Windows Startup Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Single Profile List in Tray Single Profile List in Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimize to Taskbar Minimize to Taskbar This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Hide Empty Buttons Hide Empty Buttons When the program is launched, open the last known profile that was opened during the previous session. When the program is launched, open the last known profile that was opened during the previous session. Auto Load Last Opened Profile Auto Load Last Opened Profile Only show the system tray icon when the program first launches. Only show the system tray icon when the program first launches. Launch in Tray Launch in Tray Associate .amgp files with AntiMicroX in Windows Explorer. Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles Associate Profiles Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Attach the numeric keypad Combination of keys for quitting app Combination of keys for quitting app Choose keys combination Choose keys combination ! restart is needed after choice of combination ! restart is needed after choice of combination Key Repeat Key Repeat Active keys will be repeatedly pressed when this option is enabled. Active keys will be repeatedly pressed when this option is enabled. Enable Enable Specifies how much time should elapse before key repeating begins. Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Português do Brasil Français Français Deutsch Deutsch Italiano Italiano 日本語 日本語 Русский Русский српски / srpski српски / srpski 简体中文 简体中文 Español Español українська українська Polski Polski History Si&ze: History Si&ze: Weight Modi&fier: Weight Modi&fier: Log File: Log File: Log Level: Log Level: None None Error Error Warning Warning Info Info Debug Debug Note: To see the change of log level in console output (not in log file), application restart is required Note: To see the change of log level in console output (not in log file), application restart is required Reset Reset Class Class Pro&file Directory: Pro&file Directory: Title Title Program Program Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision Disable Enhance Pointer Precision Smoothing Smoothing Histor&y Size: Histor&y Size: Weight &Modifier: Weight &Modifier: Refresh Rate: Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Spring Screen: Screen: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: Accel Numerator: 0 0 Accel Denominator: Accel Denominator: Accel Threshold: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Reset Acceleration Delay: Delay: Profi&le Directory: Profi&le Directory: ms ms Rate: Rate: times/s times/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. GUID GUID Mapping String Mapping String Disable? Disable? Delete Delete Insert Insert Default Default English English Active Active Devices: Devices: All All Device Device Profile Profile Default? Default? Add Add Edit Edit Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Select Default Profile Directory Select Default Profile Directory Are you sure you want to delete the profile? Are you sure you want to delete the profile? Save Log File As Save Log File As Log Files (*.log) Log Files (*.log) Do you really want to reset setting? Do you really want to reset setting? Would you like to reset mappings too? Would you like to reset mappings too? [NO KEY] [NO KEY] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu If events are not seen by a game, please click here to run this application as Administrator. If events are not seen by a game, please click here to run this application as Administrator. &App &App &Options &Options &Help &Help He&lp He&lp &Quit &Quit Ctrl+Q Ctrl+Q &Update Joysticks &Update Joysticks Ctrl+U Ctrl+U &Hide &Hide Ctrl+H Ctrl+H &About &About Ctrl+A Ctrl+A About &Qt About &Qt Ctrl+T Ctrl+T &Properties &Properties Ctrl+P Ctrl+P &Key Checker &Key Checker Ctrl+K Ctrl+K &GitHub Page &GitHub Page Ctrl+G Ctrl+G &Game Controller Mapping &Game Controller Mapping Ctrl+M Ctrl+M S&ettings S&ettings Ctrl+S Ctrl+S &Stick/Pad Assign &Stick/Pad Assign Ctrl+X Ctrl+X &Wiki &Wiki Ctrl+W Ctrl+W &Issues &Issues Ctrl+I Ctrl+I &Calibration &Calibration Ctrl+C Ctrl+C Issues Issues Home Page Home Page Could not find a proper controller identifier. Exiting. Could not find a proper controller identifier. Exiting. (%1) (%1) Open File Open File %1 battery %1 battery Battery level is less than %1 Battery level is less than %1 Device number: %1 Device name: %2 Device number: %1 Device name: %2 Reading old profile Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore &Restore Calibration couldn't be opened Calibration couldn't be opened You must connect at least one controller to open the window You must connect at least one controller to open the window Run as Administrator? Run as Administrator? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Failed to elevate program Failed to elevate program Failed to restart this program as the Administrator Failed to restart this program as the Administrator Could not find controller. Exiting. Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Mouse Settings - Set %1 Set %1 MouseButtonSettingsDialog Mouse Settings - Mouse Settings - Set %1 Set %1 MouseControlStickSettingsDialog Mouse Settings Mouse Settings Set %1 Set %1 MouseDPadSettingsDialog Mouse Settings Mouse Settings Set %1 Set %1 MouseSettingsDialog Mouse Settings Mouse Settings Mouse Mode: Mouse Mode: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Cursor Spring Spring Acceleration: Acceleration: Enhanced Precision Enhanced Precision Linear Linear Quadratic Quadratic Cubic Cubic Quadratic Extreme Quadratic Extreme Power Function Power Function Easing Quadratic Easing Quadratic Easing Cubic Easing Cubic Mouse Speed Settings Mouse Speed Settings Enable to change the horizontal and vertical speed boxes at the same time. Enable to change the horizontal and vertical speed boxes at the same time. Change Together Change Together Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration Delta Acceleration &Multiplier: &Multiplier: Mi&n Threshold: Mi&n Threshold: 1 = 20 pps 1 = 20 pps Wheel Hori. Speed: Wheel Hori. Speed: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: Easing Duration: s s Highest value to accelerate mouse movement by Highest value to accelerate mouse movement by x x Start %: Start %: Acceleration begins at this percentage of the base multiplier Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Minimum amount of axis travel required for acceleration to begin Max Threshold: Max Threshold: Maximum axis travel before acceleration has reached the multiplier value Maximum axis travel before acceleration has reached the multiplier value E&xtra Duration: E&xtra Duration: Curve: Curve: Ease Out Sine Ease Out Sine Ease Out Quad Ease Out Quad Ease Out Cubic Ease Out Cubic Release Radius: Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Relative Mouse Status Mouse Status X: X: 0 (0 pps) 0 (0 pps) Y: Y: 1 = 1 notch(es)/s 1 = 1 notch(es)/s Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: Hori&zontal Speed: &Vertical Speed: &Vertical Speed: Wheel Vert. Speed: Wheel Vert. Speed: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Spring Settings Spring Width: Spring Width: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Spring Height: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. %n notch(es)/s %n notch/s %n notches/s ProfileImporter Form Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Cancel OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Key Checker <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-5.10/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-5.10/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Event Handler: Native Key Value: Native Key Value: 0x00000000 0x00000000 Qt Key Value: Qt Key Value: antimicro Key Value: AntiMicroX Key Value: AntiMicroX Key Value: AntiMicroX Key Value: QObject Super Super Menu Menu Mute Mute Vol+ Vol+ Vol- Vol- Play/Pause Play/Pause Play Play Pause Pause Prev Prev Next Next Mail Mail Home Home Media Media Search Search Launch program in system tray only. Launch program in system tray only. Launch program with the tray menu disabled Launch program with the tray menu disabled Launch program without the main window displayed Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value value Unload currently enabled profile(s) Unload currently enabled profile(s) value(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID Start joysticks on a specific set. Value can be a controller index, name, or GUID number value number value Launch program as a daemon. Use only on Linux. Launch program as a daemon. Use only on Linux. Enable logging Enable logging log-type log-type Choose a file for logs writing Choose a file for logs writing filename filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Daemon launched Failed to launch daemon Failed to launch daemon Launching daemon Launching daemon Display string "%1" is not valid. Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to set a signature id for the daemon Failed to change working directory to / Failed to change working directory to / Quitting Program Quitting Program # of joysticks found: %1 # of joysticks found: %1 List Joysticks: List Joysticks: --------------- --------------- Joystick %1: Joystick %1: Index: %1 Index: %1 GUID: %1 GUID: %1 UniqueID: %1 UniqueID: %1 VendorID: %1 VendorID: %1 ProductID: %1 ProductID: %1 Product Version: %1 Product Version: %1 Name: %1 Name: %1 Yes Yes No No Game Controller: %1 Game Controller: %1 # of Axes: %1 # of Axes: %1 # of Buttons: %1 # of Buttons: %1 # of Hats: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Failed to open event generator. Exiting. Using %1 as the event generator. Using %1 as the event generator. Could not raise process priority. Could not raise process priority. Last button Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Profile location %1 is not an XML file. Profile location %1 does not exist. Profile location %1 does not exist. Controller identifier is not a valid value. Controller identifier is not a valid value. An invalid set number '%1' was specified. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. Controller identifier '%s'' is not a valid value. No set number was specified. No set number was specified. No controller was specified. No controller was specified. No display string was specified. No display string was specified. An invalid event generator was specified. An invalid event generator was specified. No event generator string was specified. No event generator string was specified. No log file specified. No log file specified. Logging started Logging started Auto-switching to profile "%1". Auto-switching to profile "%1". Auto-switching to nullptr profile! Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set Quick Set <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> Quick Set %1 Quick Set %1 SetAxisThrottleDialog Throttle Change Throttle Change The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? SetJoystick Set %1: %2 Set %1: %2 Set %1 Set %1 SetNamesDialog Set Name Settings Set Name Settings Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Name Name SimpleKeyGrabberButton Mouse Mouse SpringModeRegionPreview Spring Mode Preview Spring Mode Preview UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Could not open uinput device file Please check that you have permission to write to the device Using uinput device file %1 Using uinput device file %1 UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z Esc Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock CapsLock ; ; ' ' Enter Enter Shift_L Shift_L , , . . / / Ctrl_L Ctrl_L Super_L Super_L Alt_L Alt_L Space Space Alt_R Alt_R Menu Menu Ctrl_R Ctrl_R Shift_R Shift_R Up Up Left Left Down Down Right Right PrtSc PrtSc Ins Ins Del Del Home Home End End PgUp PgUp PgDn PgDn NumLock NumLock * * + + KP_Enter KP_Enter KP_1 KP_1 KP_2 KP_2 KP_3 KP_3 KP_4 KP_4 KP_5 KP_5 KP_6 KP_6 KP_7 KP_7 KP_8 KP_8 KP_9 KP_9 KP_0 KP_0 SCLK SCLK Pause Pause Super_R Super_R Mute Mute VolDn VolDn VolUp VolUp Play Play Stop Stop Prev Prev Next Next [NO KEY] [NO KEY] UnixWindowInfoDialog Captured Window Properties Captured Window Properties Information About Window Information About Window Class: Class: TextLabel TextLabel Title: Title: Path: Path: Match By Properties Match By Properties Class Class Title Title Path Path VDPad VDPad VDPad VirtualKeyPushButton Space Space Tab Tab Shift (L) Shift (L) Shift (R) Shift (R) Ctrl (L) Ctrl (L) Ctrl (R) Ctrl (R) Alt (L) Alt (L) Alt (R) Alt (R) Alt Gr Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP PGUP DEL DEL PGDN PGDN 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK NUM LK * * + + Enter Enter Del Del < < : : Super (L) Super (L) Menu Menu Up Up Down Down Left Left Right Right VirtualKeyboardMouseWidget Keyboard Keyboard Mouse Mouse Mouse Settings Mouse Settings Left Mouse Left Up Mouse Up Left Button Mouse Left Button Middle Button Mouse Middle Button Right Button Mouse Right Button Wheel Up Mouse Wheel Up Wheel Left Mouse Wheel Left Wheel Right Mouse Wheel Right Wheel Down Mouse Wheel Down Down Mouse Down Right Mouse Right Button 4 Mouse Button 4 Mouse 8 Mouse Mouse 8 Button 5 Mouse Button 5 Mouse 9 Mouse Mouse 9 NONE NONE [NO KEY] [NO KEY] Last button Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Others Applications Applications Browser Back Browser Back Browser Favorites Browser Favorites Browser Forward Browser Forward Browser Home Browser Home Browser Refresh Browser Refresh Browser Search Browser Search Browser Stop Browser Stop Calc Calc Email Email F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media Media Media Next Media Next Media Play Media Play Media Previous Media Previous Media Stop Media Stop Search Search Volume Down Volume Down Volume Mute Volume Mute Volume Up Volume Up VirtualMousePushButton INVALID INVALID WinAppProfileTimerDialog Capture Application Capture Application After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Timer: Timer: Seconds Seconds Cancel Cancel WinExtras [NO KEY] [NO KEY] AntiMicroX Profile AntiMicroX Profile X11Extras ESC ESC Tab Tab Space Space DEL DEL Return Return KP_Enter KP_Enter Backspace Backspace Alt Gr Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput extension was not found. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. Virtual pointer found with id=%1. Virtual pointer found with id=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Changing mouse acceleration for device with id=%1 Changing mouse acceleration for device with id=%1 XMLConfigReader Could not write updated profile XML to file %1. Could not write updated profile XML to file %1. XMLConfigWriter Could not write to profile at %1. Could not write to profile at %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Launch program in system tray only. Launch program with the tray menu disabled Launch program with the tray menu disabled Launch program without the main window displayed Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value value Unload currently enabled profile(s) Unload currently enabled profile(s) value(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID Start joysticks on a specific set. Value can be a controller index, name, or GUID number value number value Launch program as a daemon. Use only on Linux. Launch program as a daemon. Use only on Linux. Enable logging Enable logging log-type log-type Choose a file for logs writing Choose a file for logs writing filename filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_es.ts000066400000000000000000013651661377703515000275210ustar00rootroot00000000000000 AboutDialog About sobre Version versión <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Copyright: 2013 - 2016 {2013 ?} {2013 ?} {2020?} Copyright: 2013 - 2018 Copyright: 2013 - 2016 {2013 ?} {2013 ?} {2018?} Info info Changelog Changelog Copyright: 2013 - 2016 Copyright: 2013 - 2016 {2013 ?} Since December 30, 2012, I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Once the Steam controller is finally released to the public, the need for this program might not exist anymore. Just based on the concept of the controller alone, the Steam controller would have so many advantages over using a program like this to provide KB+M emulation. Desde el 30 de diciembre de 2012, he estado trabajando en AntimicroX en mi tiempo libre. Lo que originalmente comenzó como un fork de QJoyPad y una manera de aprender programación orientada a eventos adecuado se ha convertido en algo mucho más grande de lo que originalmente pretendía. Aunque he pasado mucho tiempo aprendiendo nuevas técnicas, saber más sobre el dominio de la emulación KB + M, y pasar las noches de viernes golpeando la cabeza contra mi teclado, ha sido una experiencia divertida y enriquecedora en general. La necesidad de este programa vino de mí usando programas similares en Windows para jugar varios juegos que no proporcionan soporte para el controlador nativo. Aunque existían algunas alternativas en Linux, no había realmente nada de lo que me pareció que era lo suficientemente bueno en términos de funcionalidad o controles en el juego con el fin de disfrutar realmente de juegos que quería jugar con el uso de la emulación KB + M. QJoyPad fue el programa principal que había utilizado en el pasado a pesar de que había envejecido mucho y no proporcionar alguna funcionalidad básica que yo pensaba que era esencial. El proyecto estaba muerto, ya que no había sido actualizado en varios años, así que decidí hacer mi propia. Desde entonces, he tratado de averiguar lo que los otros programas hacen la derecha y luego mejorarlo. También he descubierto algunos truquitos en el camino y he aprendido más acerca de cómo los controles del gamepad nativas se implementan en algunos juegos de lo que nunca realmente quería saber. Aunque sin duda hay áreas en las que este programa podría mejorar, me parece que este programa ofrece la mejor experiencia de control en el juego para jugar más, y algunos nuevos, juegos que no proporcionan soporte para el controlador nativo. Una vez que el control de Steam finalmente se lanzó al público, la necesidad de este programa no podría existir más. Sólo se basa en el concepto del controlador solamete, el controlador de Steam tendría tantas ventajas sobre el uso de un programa como este para proporcionar la emulación KB + M. Credits Créditos AntiMicroX AntiMicroX <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Travis Nickles &lt;nickles.travis@gmail.com&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"><br /></span>Zerro Alvein</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">aybe</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx - Chinese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">phob - German</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tou omiya - Japanese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">burunduk - Ukrainian</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Travis Nickles &lt;nickles.travis@gmail.com&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"><br /></span>Zerro Alvein</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">aybe</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx - Chinese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Español</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">phob - German</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tou omiya - Japanese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">burunduk - Ukrainian</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> About Development Sobre el desenvolvimiento License Licencia Program Version %1 Versión del programa %1 Program Compiled on %1 at %2 Programa compilado en %1 a %2 Built Against SDL %1 Running With SDL %1 Using Qt %1 Usando Qt %1 Using Event Handler: %1 Usando Gestor de Eventos: %1 AddEditAutoProfileDialog Auto Profile Dialog Profile: Perfil: Pro&file: Browse Navegar Window: ventana: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties &Class: T&itle: Class: Clase: Title: Título: set partial title Application: Aplicación: Select seleccione De&vices: Devices: Dispositivos: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller A different profile is already selected as the default for this device. Current (%1) Open Config Abrir Config Select Program Seleccionar Programa Programs (*.exe) Programas (*.exe) Please use the main default profile selection. Por favor, utilice la selección principal perfil predeterminado. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Por favor, seleccione una ventana utilizando el ratón. Presione Escape si desea cancelar. Capture Application Window Could not obtain information for the selected window. Application Capture Failed Profile file path is invalid. La ruta de archivo de perfil es invalido. No window matching property was specified. Program path is invalid or not executable. File is not an .exe file. El Archivo no es un .exe. No window matching property was selected. AdvanceButtonDialog Advanced Avanzado Assignments Asignamientos Toggle Alternar Turbo Turbo Set Selector Selector de Set Blank or KB/M Vacio o KB/M Hold Mantener Pause Pausa Cycle Ciclo Distance Distancia Insert Inserir Delete Borrar Clear All Limpiar todo Time: Tiempo: 0.01s 0.01s 0s 0s Insert a pause that occurs in between key presses. Insertar una pausa que se produce en la introducción de la tecla. Release Soltar Insert a new blank slot. Inserte una nueva ranura en blanco. Join Split Delete a slot. Borrar ranura. Clear all currently assigned slots. Limpiar todos los slots asignados actualmente. Specify the duration of an inserted Pause or Hold slot. Especificar la duración de una ranura de pausa o de retención insertado. 0m 0m &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Especificar el rango más allá de una zona muerta eje en el que una secuencia de acciones se ejecutará. Distance: Distancia: % % Mouse Mod Raton Mod Press Time Tiempo de presionado Delay Retraso Execute Ejecutar Load Cargar Set Change Definir Cambio Text Entry Entrada de texto Placeholder marcador de posición 0 0 Mouse Speed Mod: Velovidad de Ratón Mod: Set the percentage that mouse speeds will be modified by. Establecer el porcentaje que las velocidades de ratón serán modificadas por. Auto Reset Cycle After Auto Resetear Ciclos Después seconds segundos Executable: ... ... Arguments: Enabled Habilitado Mode: Modo: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Normal:. Pulse y suelte repetidamente un botón por la tasa elegido </p><p> Gradiente: Modificar el retraso y liberación de un botón de acuerdo con la distancia de un eje se ha movido. La tasa seguirá siendo el mismo </p><p>Pulso:. Modifica como muchas veces un botón es presionado y liberado por segundo. El retraso botón seguirá siendo el mismo.</p></body></html> Normal Normal Gradient Gradiente Pulse Pulso Delay: Retraso: 0.10s 0.10s Rate: Taza: 10.0/s 10.0/s Disabled Inhabilitado Select Set 1 One Way Seleccione Set 1 Unidireccional Select Set 1 Two Way Seleccione Set 1 Bidireccional Select Set 1 While Held Seleccione Set 1 Mientras se Mantiene Select Set 2 One Way Seleccionar Set 2 Unidireccional Select Set 2 Two Way Seleccionar Set 2 Bidireccional Select Set 2 While Held Seleccionar Set 2 Mientras se Mantiene Select Set 3 One Way Seleccionar Set 3 Unidireccional Select Set 3 Two Way Seleccionar Set 3 Bidireccional Select Set 3 While Held Seleccionar Set 3 Mientras se Mantiene Select Set 4 One Way Seleccionar Set 4 Unidireccional Select Set 4 Two Way Seleccionar Set 4 Bidireccional Select Set 4 While Held Seleccionar Set 4 Mientras se Mantiene Select Set 5 One Way Seleccionar Set 5 Unidireccional Select Set 5 Two Way Seleccionar Set 5 Bidireccional Select Set 5 While Held Seleccionar Set 5 Mientras se Mantiene Select Set 6 One Way Seleccionar Set 6 Unidireccional Select Set 6 Two Way Seleccionar Set 6 Bidireccional Select Set 6 While Held Seleccionar Set 6 Mientras se Mantiene Select Set 7 One Way Seleccionar Set 7 Unidireccional Select Set 7 Two Way Seleccionar Set 7 Bidireccional Select Set 7 While Held Seleccionar Set 7 Mientras se Mantiene Select Set 8 One Way Seleccionar Set 8 Unidireccional Select Set 8 Two Way Seleccionar Set 8 Bidireccional Select Set 8 While Held Seleccionar Set 8 Mientras se Mantiene [NO KEY] [SIN TECLA] sec. Seg. /sec. /seg. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Set %1 Select Set %1 Seleccionar Set %1 One Way Unidireccional Two Way Bidireccional While Held Mientras se Mantiene Choose Executable Escojer Ejecutable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Las ranuras mas allá de un Ciclo de acción podrán ser ejecutados en la proxima vez que se presione el botón. ciclos múltiples se pueden agregar con el fin de crear particiones en una secuencia. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Retrasa el momento en que la siguiente ranura es activado por el tiempo especificado. Las ranuras activadas antes de que el retraso se mantendrá activa una vez transcurrido el tiempo de retardo. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Distancia acción especifica que las ranuras después sólo se ejecutan cuando un eje se mueve de un cierto rango más allá de la zona muerta designada. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Inserte una acción de retención. Las ranuras después de la acción sólo se ejecutarán si el botón se mantiene más allá del intervalo especificado. Chose a profile to load when this slot is activated. Elija un perfil para cargar cuando se activa esta ranura. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. El Mod de acción del ratón va a modificar todos los ajustes de velocidad del ratón en un porcentaje especificado, mientras que la acción se está procesando. Esto puede ser útil para ralentizar el ratón para francotiradores. Specify the time that keys past this slot should be held down. Especificar el tiempo que las teclas pasan en esta ranura deben mantenerse presionadas. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Insertar una acción de liberación. Las ranuras después de la acción sólo se ejecutarán después de la liberación del botón si este fue presionado más allá del intervalo especificado. Change to selected set once slot is activated. Cambiar al set seleccionado una vez que se activa la ranura. Full string will be typed when a slot is activated. La cadena completa se tecleará cuando se activa una ranura. Execute program when slot is activated. Ejecutar el programa cuando se activa la ranura. Choose Profile Elegir Perfil Config Files (*.amgp *.xml) Archivos de Config (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Asignamiento de Palanca/Pad Sticks Palancas DPads DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Mando %2) Stick 1 Palanca 1 Enabled Habilitar Assign Asignar X Axis: Eje X: Y Axis: Eje Y: Stick 2 Palanca 2 Number of Physical DPads: %1 Numero de DPads físicos: %1 Virtual DPad 1 DPad 1 Virtual Up: Arriba: Down: Abajo: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Nota: Esta ventana es para la retrocompatibilidad con los perfiles realizados antes AntimicroX 2.0. Desde la versión 2.0, se prefiere el uso de la ventana de juego Mapeo controlador. Left: Izquierda: Right: Derecha: Axis %1 Ejes %1 Axis %1 - Ejes %1 - Axis %1 + Ejes %1 + Button %1 Botón %1 Move stick 1 along the X axis Mueva la palanca 1 a lo largo del eje X Move stick 1 along the Y axis Mueva la palanca 1 a lo largo del eje Y Move stick 2 along the X axis Mueva la palanca 2 a lo largo del eje X Move stick 2 along the Y axis Mueva la palanca 2 a lo largo del eje Y Press a button or move an axis Presione un botón o mueva un eje AxisEditDialog Axis Ejes Mouse (Horizontal) Ratón (Horizontal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Vertical) Ratón (Vertical) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Arrows: Up | Down Direccionales: Arriba | Abajo Arrows: Left | Right Direccionales: Izquierda | Derecha Keys: W | S Teclas: W | S Keys: A | D Teclas: A | D NumPad: KP_8 | KP_2 Teclado Num: 8 | 2 NumPad: KP_4 | KP_6 Teclado Num: 4 | 6 None Nada Set the value to use as the limit for an axis. Useful for a worn out analog stick. Establecer el valor a utilizar como límite para un eje. Útil para una palancas analógicas desgastadas. Negative Half Throttle Mitad de Acelerador Negativo Positive Half Throttle Mitad de Acelerador Positivo Name: Nombre: Specify the name of an axis. Especificar un nombre para un eje. Mouse Settings Configuraciones de Ratón Set the value of the dead zone for an axis. Establecer el valor de la zona muerta para un eje. Presets: Presets: Dead Zone: Zona Muerta: Max Zone: Zona Maxima: [NO KEY] [SIN TECLA] Throttle setting that determines the behavior of how to interpret an axis hold or release. Ajuste del acelerador la que determina el comportamiento de la forma de interpretar un eje de retención o liberación. Negative Throttle Acelerador Negativo Normal Normal Positive Throttle Acelerador Positivo Current Value: Valor Actual: Set Set %1 Left Mouse Button Botón Izquierdo del Ratón Right Mouse Button Botón Derecho del Ratón ButtonEditDialog Dialog Dialogo To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Para realizar una nueva asignación, pulse cualquier tecla del teclado o haga clic en un botón en el teclado o en la pestaña ratón Placeholder marcador de posición Toggle Alternar Enables a key press or release to only occur when a controller button is pressed. Habilita la pulsación de una tecla o la liberación que sólo ocurren cuando se pulsa un botón del mando. Enables rapid key presses and releases. Turbo controller. Permite a las pulsaciones de teclas rápidas y liberaciones. Controlador Turbo. Turbo Turbo Current: Presente: Last keyboard/mouse button: Slots Ranuras Na&me: No&mbre: Specify the name of a button. Especifique el nombre de un botón. Action: Acción: Specify the action that will be performed in game while this button is being used. Especificar la acción que se llevará a cabo en juego, mientras se está utilizando este botón. Advanced Avanzado Set Set Set %1 Set %1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [SIN TECLA] Calibration Form Start calibration Sticks: Reset settings Cancel Cancelar Save Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 Ejes %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: Clase: TextLabel Title: Titulo: Path: Camino: Match By Properties Class Clase Title Titulo Path Camino Full Path File Name CommandLineUtility Profile location %1 is not an XML file. Localización de Perfil %1 no es un archivo XML válido. Profile location %1 does not exist. Localización de Perfil %1 No existe. An invalid set number '%1' was specified. Un numero de Set inválido '%1' fué especificado. Controller identifier '%s'' is not a valid value. Controlador idendificado '%s'' no es un valor válido (valga la redundancia). No display string was specified. Ninguna cadena de exibición fué especificado. DPadContextMenu Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad Teclado Num None Nada Standard Estándar Eight Way Ocho Vías 4 Way Cardinal 4 Vias Cardinal 4 Way Diagonal 4 Vias Diagonal Mouse Settings Configuracion de Ratón DPadEditDialog Dialog Dialogo Presets: Presets: Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad Teclado Num None Nada Dpad Mode: Modo Dpad: &Name: &Nombre: 4 Way Cardinal 4 Vias Cardinal 4 Way Diagonal 4 Vias Diagonal DPad Delay: Retraso de Dpad: Time lapsed before a direction change is taken into effect. Tiempo transcurrido antes de un cambio de dirección se tenga en efecto. s s Specify the name of a dpad. Especificar un nombre para Dpad. Mouse Settings Configuracion de Ratón Standard Estándar Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Estándar: Dpad de 8 regiones con dos botones de dirección activa cuando el dpad está en una región diagonal. Ocho manera: Dpad de 8 regiones con cada dirección que tiene su botón dedicado propio. Sólo un botón está siempre activo en en el momento. Útil para los juegos rougelike. 4 Way cardenal: Dpad de 4 regiones con las regiones correspondientes a los puntos cardinales de la DPAD. Útil para los menús. 4 Way Diagonal: Dpad de 4 regiones con cada región que corresponde a una zona de diagonal. Eight Way Ocho Vías Set Set Set %1 Set %1 EditAllDefaultAutoProfileDialog Default Profile Perfil por Defecto Profile: Perfil: Browse Navegar Open Config Abrir Config Profile file path is invalid. La ruta de archivo de perfil es invalido. ExtraProfileSettingsDialog Extra Profile Settings Configuraciones Extra de Perfil Key Press Time: Tiempo de presionado de Tecla: 0.00 ms 0.00 ms Profile Name: Nombre del Perfil: s s GameController Game Controller Controlador de juego GameControllerDPad DPad DPad GameControllerMappingDialog Game Controller Mapping Mapeo de Controles de Juego <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A B X Y Back Start Guide Left Shoulder Right Shoulder Left Stick Click Right Stick Click Left Stick X Left Stick Y Right Stick X Right Stick Y Left Trigger Right Trigger DPad Up DPad Left DPad Down DPad Right Mapping SDL 2 Game Controller Mapping String Last Axis Event: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Mapeo de Controles de Juego (%1) (#%2) Discard Controller Mapping? ¿Descartar Mapeo de Controlador? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. ¿Descartar Mapeo para este controlador? Si lo descarta, el controlador podrá revertirse a un mando una vez que se actualicen todos los mandos. GameControllerSet Back Guide Start LS Click RS Click L Shoulder R Shoulder L Trigger R Trigger GameControllerTrigger Trigger Gatillo JoyAxis Axis Ejes JoyAxisButton Negative Negativo Positive Positivo Unknown Desconocido Button Botón JoyAxisContextMenu Mouse (Horizontal) Ratón (Horizontal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Vertical) Ratón (Vertical) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Arrows: Up | Down Direccionales: Arriba | Abajo Arrows: Left | Right Direccionales: Izquierda | Derecha Keys: W | S Teclas: W | S Keys: A | D Teclas: A | D NumPad: KP_8 | KP_2 Teclado Num: 8 | 2 NumPad: KP_4 | KP_6 Teclado Num: 4 | 6 None Nada Mouse Settings Configuracion de Ratón Left Mouse Button Botón Izquierdo del Ratón Right Mouse Button Botón Derecho del Ratón JoyButton Processing turbo for #%1 - %2 Procesando turbo para #%1 - %2 Finishing turbo for button #%1 - %2 Finalizando turbo para botón #%1 - %2 Processing press for button #%1 - %2 Procesando de presionado para botón #%1 - %2 Processing release for button #%1 - %2 Procesando de liberacion de botón #%1 - %2 Distance change for button #%1 - %2 Distancia de cambio para botón #%1 - %2 Button Botón [NO KEY] [SIN TECLA] [Set %1 1W] [Set %1 1W] [Set %1 2W] [Set %1 2W] [Set %1 WH] [Set %1 WH] JoyButtonContextMenu Toggle Alternar Turbo Turbo Clear Limpiar Set Select Seleccionar Set Disabled Inhabilitado Set %1 Set %1 Set %1 1W Set %1 1W Set %1 2W Set %1 2W Set %1 WH Set %1 WH JoyButtonSlot Mouse Ratón Up Arriba Down Abajo Left Izquierda Right Derecha LB BI MB BM RB BD B4 B4 B5 B5 Pause Pausa Hold Mantener Cycle Ciclo Distance Distancia Release Soltar Mouse Mod Raton Mod Press Time Tiempo de presionado Delay Retraso Load %1 Cargar %1 Set Change %1 Cambiar Set %1 [Text] %1 [Texto] %1 [Exec] %1 [Ejec] %1 [NO KEY] [SIN TECLA] JoyControlStick Stick Palanca JoyControlStickButton Up Arriba Down Abajo Left Izquierda Right Derecha Button Botón JoyControlStickContextMenu Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad Teclado Num None Nada Standard Estándar Eight Way Ocho Vías 4 Way Cardinal 4 Vias Cardinal 4 Way Diagonal 4 Vias Diagonal Mouse Settings Configuracion de Ratón JoyControlStickEditDialog Dialog Dialogo X: 0 0 Y: Distance: Distancia: Presets: Presets: Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad Teclado Num None Nada Stick Mode: Modo Palanca: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Estándar: Dpad de 8 regiones con dos botones de dirección activa cuando el dpad está en una región diagonal. Ocho manera: Dpad de 8 regiones con cada dirección que tiene su botón dedicado propio. Sólo un botón está siempre activo en en el momento. Útil para los juegos rougelike. 4 Way cardenal: Dpad de 4 regiones con las regiones correspondientes a los puntos cardinales de la DPAD. Útil para los menús. 4 Way Diagonal: Dpad de 4 regiones con cada región que corresponde a una zona de diagonal. 4 Way Cardinal 4 Vias Cardinal 4 Way Diagonal 4 Vias Diagonal Dead zone value to use for an analog stick. Valores de Zona Muerta usadas para una palanca analogica. Value when an analog stick is considered moved 100%. Valor cuando una palanca analogica se considera que se movió al 100%. The area (in degrees) that each diagonal region occupies. El área (en grados) que cada región ocupa. Square Stick: Palanca cuadrada: Percentage to modify a square stick coordinates to confine values to a circle Porcentaje para modificar las coordenadas de la palanca cuadrada para confinar valores para el ciclo % % Stick Delay: Retraso de Palanca: Time lapsed before a direction change is taken into effect. Tiempo transcurrido antes de un cambio de dirección tomado en efecto. s s Modifier: Modificador: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Presione un Botón Na&me: Name: Nombre: Specify the name of an analog stick. Especificar un nombre para una palanca analogica. Mouse Settings Configuraciones de Ratón Standard Estándar Bearing: % Safe Zone: % Zona Segura: Eight Way Ocho Vías Dead Zone: Zona Muerta: Max Zone: Zona Maxima: Diagonal Range: Rango Diagonal: Set Set Set %1 Set %1 JoyControlStickModifierButton Modifier Modificador JoyDPad DPad DPad JoyDPadButton Up Arriba Down Abajo Left Izquierda Right Derecha Button Botón JoyTabWidget <New> Remove Remove configuration from recent list. Load Cargar Load configuration file. Save Save changes to configuration file. Save As Save changes to a new configuration file. Sets Copy from Set Settings Configuraciones Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Stick/Pad Assign Asignación de Palanca/Pad Controller Mapping Quick Set Configuración rápida Names Toggle button name displaying. Pref Change global profile settings. Reset Revert changes to the configuration. Reload configuration file. Open Config Abrir Config Config Files (*.amgp *.xml) Archivos de Config (*.amgp *.xml) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks Palancas DPads DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 Set %1: %2 Set %1 Set %1 Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Save Config Set Set Joystick Joystick Mando JoystickStatusWindow Properties Propiedades Details Detalles Name: Nombre: %1 %1 Number: Numero: Axes: Ejes: Buttons: Botones: Hats: Hats: Battery: Unknown Desconocido GUID: GUID: Game Controller: Controlador de Juego: Axes Ejes Buttons Botones Hats Hats %1 (#%2) Properties %1 (#%2) Propiedades Axis %1 Ejes %1 Hat %1 Hat %1 No No Yes Si MainSettingsDialog Edit Settings Editar Configuraciones General General Controller Mappings Mapeo de controles Language Lenguaje Auto Profile Auto Perfil Mouse Ratón Advanced Avanzado Pro&file Directory: <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Especificar el directorio por defecto que el programa debe utilizar en los diálogos de archivo cuando se carga un perfil o guardar un nuevo perfil.</p></body></html> Recent Profile Count: Contaje de Perfiles Recientes: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Número de perfiles que se puede colocar en la lista de perfil reciente. 0 dará lugar a que el programa no cumplir un límite en el número de perfiles que se muestran.</p></body></html> Gamepad Poll Rate: Taza de Sondeo de Mando: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Cambiar la velocidad de sondeo que el programa utiliza para descubrir nuevos eventos de mandos. El valor predeterminado es de 10 ms. La reducción del valor de velocidad de sondeo podría causar que la aplicación usar más energía de la CPU así que por favor probar la configuración que utilice antes de usar AntimicroX desatendida. Hide main window when the main window close button is clicked instead of quitting the program. Ocultar ventana principal cuando el botón de la ventana principal es estrecha se hace clic en lugar de salir del programa. Close To Tray Cerrar para la bandeja del sistema Have Windows start AntiMicroX at system startup. Hacer que Windows inicie AntimicroX junto con el sistema. Launch At Windows Startup Iniciar junto con Windows Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Mostrar perfiles más recientes de todos los mandos como una única lista en el menú de la bandeja. predeterminados a la utilización de los submenús. Single Profile List in Tray Lista única de perfiles en la bandeja de sistema Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Hacer que el programa minimize la barra de tareas. Por defecto, el programa se minimiza en el sistema la bandeja si está disponible. Minimize to Taskbar Minimizar para la barra de tareas This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Esta opción hará que el programa para ocultar todos los botones que no tienen ranuras asignadas. La ventana de diálogo de configuración rápida tendrá que ser utilizado para que aparezca el diálogo de edición para los botones del mando. Hide Empty Buttons Ocultar Botones Vacíos When the program is launched, open the last known profile that was opened during the previous session. Cuando el programa esté en marcha, abrir el último perfil conocido que se abrió durante la sesión anterior. Auto Load Last Opened Profile Auto Cargar el ultimo perfil abierto Only show the system tray icon when the program first launches. Solamente mostrar el icono en la bandeja de sistema cuando el programa inicie por primera vez. Launch in Tray Lanzar en la bandeja del sistema Associate .amgp files with AntiMicroX in Windows Explorer. Asociar archivos .amgp con AntiMicroX en Windows Explorer. Associate Profiles Asociar Perfiles Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Repetición de Tecla Active keys will be repeatedly pressed when this option is enabled. Las teclas activadas serán presionadas repetidamente cuando esta opción esté activada. Enable Habilitar Specifies how much time should elapse before key repeating begins. Especifica cuánto tiempo debe transcurrir antes de repetión de tecla comienza. Specifies how many times key presses will be performed per seconds. Especifica cuántas veces se llevarán a cabo las pulsaciones de teclas por segundo. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntimicroX ha sido traducido a muchos idiomas diferentes por los contribuyentes. Por defecto, el programa elegirá una traducción apropiada basada en la configuración regional de su sistema. Sin embargo, puede hacer que la carga AntimicroX una traducción diferente en función del idioma que elija en la lista siguiente.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Nada Error Warning Info info Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset French Francés Japanese Japonés Russian Ruso Serbian Serbio Simplified Chinese Chino Simplificado Ukrainian Ucraniano Class Clase Title Titulo Program Programa Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Deshabilitar la configuración de Windows "mejorada precisión del puntero" mientras AntimicroX se está ejecutando. La desactivación "mejorada precisión del puntero" permitirá el movimiento del ratón dentro de AntimicroX a ser más preciso. Disable Enhance Pointer Precision Desactivar la precisión del puntero mejorado Smoothing suavizado Histor&y Size: Tamaño del &Historial: Weight &Modifier: &Modificador de peso: Refresh Rate: Taza de Actualizacion: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. La frecuencia de actualización es la cantidad de tiempo que transcurrirá entre los eventos del ratón. Por favor tenga cuidado cuando la edición de este ajuste ya que esto haría que el programa utilice más potencia de CPU. Un valor demasiado bajo puede causar inestabilidad del sistema. Por favor, probar la configuración antes de usar sin vigilancia. Spring Spring Screen: Pantalla: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Utilizar la pantalla especificada para el modo spring. En Linux, el por defecto es el uso de la pantalla principal. En Windows, el valor por defecto es utilizar todas las pantallas disponibles. Accel Numerator: Numerador de Aceleración: 0 0 Accel Denominator: Denominador de Aceleración: Accel Threshold: Límite de Aceleración: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Si los valores de aceleración para el ratón virtual han sido cambiados por un proceso diferente, particularmente cuando se cierra un juego antiguo, entonces es posible que desee restablecer la aceleración Los valores utilizados por el ratón virtual. Reset Acceleration Resetear Aceleración Delay: Retraso: Profi&le Directory: Directorio de Perfi&l: ms ms Rate: Taza: times/s tiempo/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. A continuación se muestra una lista de las asignaciones personalizados que se han guardado. Puede usar la siguiente tabla para eliminar las asignaciones o tienen asignaciones temporalmente deshabilitados. También puede desactivar las asignaciones que se incluyen con SDL; sólo tiene que insertar una nueva fila con el GUID de la palanca de mando correspondiente y vaya desactivar. Los ajustes no tendrán efecto hasta que actualizar todos los mandos o desenchufar el mando en particular. GUID GUID Mapping String Cadena de Mapeo Disable? Inhabilitar? Delete Borrar Insert Insertar Default Por Defecto Brazilian Portuguese Portugués de Brasil English Inglés German Alemán Active Activo Devices: Dispositivos: All Todo Device Dispositivo Profile Perfil Default? Por Defecto? Add Agregar Edit Editar Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Además, los usuarios de Windows que deseen utilizar un valor bajo,pueden tambien marcarl "Desactivar el puntero de precisión" en caso de que no haya desactivado la opción en Windows. Select Default Profile Directory Seleccionar el Directorio de Perfil por defecto Are you sure you want to delete the profile? Está seguro que quiere borrar el perfil? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [SIN TECLA] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Ningún Mando fue encontrado Por favor conecte un Mando y elija la opción "Actualizar Mandos" en el menu principal If events are not seen by a game, please click here to run this application as the Adminstrator. Si los eventos no son vistos por un juego, por favor haga clic aquí para ejecutar esta aplicación como administrador. If events are not seen by a game, please click here to run this application as Administrator. &App &App &Options &Opciones &Help A&yuda He&lp &Quit S&alir Ctrl+Q Ctrl+Q &Update Joysticks Act&ualizar Mandos Ctrl+U Ctrl+U &Hide O&cultar Ctrl+H Ctrl+H &About So&bre Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt Sobre Qt Properties Propiedades Key Checker Verificador de Teclas Home Page Home Page GitHub Page Página GitHub Game Controller Mapping Mapeo de Controles de Juego Settings Configuraciones Stick/Pad Assign Asignación de Palanca/Pad Wiki Wiki Could not find a proper controller identifier. Exiting. No se pudo encontrar un identificador de controlador apropiado.Saliendo. (%1) (%1) Open File Abrir Archivo %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore &Restaurar Calibration couldn't be opened You must connect at least one controller to open the window Run as Administrator? ¿Ejecutar como Administrador? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. ¿Estás seguro de que desea ejecutar este programa como Adminstrator? Algunos juegos se ejecutan como administrador lo que hará que los eventos generados por AntimicroX para no ser utilizado por aquellos juegos a menos AntimicroX también se ejecuta como el Adminstrator. Esto se debe a problemas de permisos causadas por las opciones de Control de cuentas de usuario (UAC) en Windows Vista y versiones posteriores. Failed to elevate program Fallo al elevar el programa Failed to restart this program as the Administrator Fallo al reiniciar este programa como administrador Could not find controller. Exiting. No se pudo encontrar un controlador. Saliendo. MouseAxisSettingsDialog Mouse Settings - Configuraciones de Ratón - Set %1 Set %1 MouseButtonSettingsDialog Mouse Settings - Configuraciones de Ratón - Set %1 Set %1 MouseControlStickSettingsDialog Mouse Settings Configuraciones de Ratón Set %1 Set %1 MouseDPadSettingsDialog Mouse Settings Configuraciones de Ratón Set %1 Set %1 MouseSettingsDialog Mouse Settings Configuracion de Ratón Mouse Mode: Modo Ratón: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Cursor Spring Spring Acceleration: Aceleración: Enhanced Precision Puntero Mejorado Linear Quadratic Cubic Quadratic Extreme Power Function Easing Quadratic Easing Cubic Mouse Speed Settings Enable to change the horizontal and vertical speed boxes at the same time. Change Together Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: Horizontal Speed: Velocidad Horizontal: 1 = 20 pps Vertical Speed: Velocidad Vertical: Wheel Hori. Speed: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: s s Extra Acceleration Aceleración Extra Multiplier: Multiplicador: Highest value to accelerate mouse movement by x Start %: Acceleration begins at this percentage of the base multiplier La aceleración comienza en este porcentaje de la base de multiplicador Min Threshold: Límite Mínimo: Minimum amount of axis travel required for acceleration to begin cantidad mínima de recorrido del eje requerido para la aceleración a comenzar Max Threshold: Límite Máximo: Maximum axis travel before acceleration has reached the multiplier value El recorrido máximo del eje antes de la aceleración ha alcanzado el valor del multiplicador E&xtra Duration: Curve: Curva: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Mouse Status X: 0 (0 pps) Y: 1 = 1 notch(es)/s Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Spring Width: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. %n notch(es)/s %n notch/s %n notches/s ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Cancelar OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Verificador de Teclas <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Presione una tecla del teclado para ver cómo se detecta la tecla por esta aplicación. La ventana mostrará el valor de la tecla del sistema nativo, el valor original dada por Qt (si es el caso), y el valor personalizado utilizado por AntimicroX. </p><p> El valor de la tecla AntimicroX y el valor de tecla Qt generalmente es la misma . AntiMicroX intenta utilizar los valores de las claves definidas en Qt cuando sea posible. Vea la página <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> para una lista de valores definidos por Qt. Si descubre que la tecla no es compatible de forma nativa por este programa, por favor informa del problema al estilo de AntiMicroX <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> para que el programa pueda editarlo para soportarlo directamente. Tal como es, se añade un prefijo personalizado para valores desconocidos por lo que todavía se pueden utilizar; el principal problema es que el perfil ya no será portátil.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Controlador de eventos: Native Key Value: Valor de tecla nativo: 0x00000000 0x00000000 Qt Key Value: Valor QT de Tecla: antimicro Key Value: AntiMicroX Key Value: Valor AntimicroX de Tecla: QObject Menu Menu Pause Pausa Media Media Search Buscar Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Failed to launch daemon Launching daemon Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to change working directory to / Quitting Program Saliendo del Programa # of joysticks found: %1 # de mandos econtrados: %1 List Joysticks: Lista de Mandos: --------------- Joystick %1: Index: %1 GUID: %1 GUID: %1 UniqueID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Nombre: %1 Yes Si No No Game Controller: %1 Controlador de Juego: %1 # of Axes: %1 # of Buttons: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Localización de Perfil %1 no es un archivo XML válido. Profile location %1 does not exist. Localización de Perfil %1 No existe. Controller identifier is not a valid value. An invalid set number '%1' was specified. Un numero de Set inválido '%1' fué especificado. Controller identifier '%s'' is not a valid value. Controlador idendificado '%s'' no es un valor válido (valga la redundancia). No set number was specified. No controller was specified. No display string was specified. Ninguna cadena de exibición fué especificado. An invalid event generator was specified. No event generator string was specified. No log file specified. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. La versión xinput debe ser al menos 2,0. no se producirán cambios en la aceleración del ratón. QuickSetDialog Quick Set Configuración rápida <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Por favor, pulse un botón o mueva un eje en %1 (<span style=" font-weight:600;">%2</span>).<br/>una ventana de diálogo aparecerá entonces<br/>permitirá crear una asignación.</p></body></html> Quick Set %1 Configuración rápida %1 SetAxisThrottleDialog Throttle Change Cambio del acelerador The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? La posición del acelerador para el Eje %1 ha sido cambiado ¿Le gustaría distribuir este cambio acelerador para todos los sets? SetJoystick Set %1: %2 Set %1: %2 Set %1 Set %1 SetNamesDialog Set Name Settings Config Nombre de Set Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Name Nombre SimpleKeyGrabberButton Mouse Ratón SpringModeRegionPreview Spring Mode Preview Vista previa de modo Spring UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput No se pudo encontrar un archivo de dispositivo uinput válida. Por favor, compruebe que tiene el módulo uinput cargado. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device No se pudo abrir archivo de dispositivo uinput Por favor, compruebe que tiene permiso para escribir en el dispositivo Using uinput device file %1 El uso de archivos del dispositivo uinput %1 UInputHelper a b c d e f g h i j k l m n o p q r s s t u v w x y z Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace Tab [ [ ] ] \ \ CapsLock ; ; ' ' Enter Shift_L , , . . / / Ctrl_L Super_L Alt_L Space Alt_R Menu Menu Ctrl_R Shift_R Up Arriba Left Izquierda Down Abajo Right Derecha PrtSc Ins Del Home End PgUp PgDn NumLock * * + + KP_Enter Enter_Num KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9 KP_0 SCLK SCLK Pause Pausa Super_R Mute VolDn VolUp Play Stop Prev Next [NO KEY] [SIN TECLA] UnixWindowInfoDialog Captured Window Properties Information About Window Class: Clase: TextLabel Title: Titulo: Path: Camino: Match By Properties Class Clase Title Titulo Path Camino VDPad VDPad VDPad VirtualKeyPushButton Space Espaciador Tab Tabulador Shift (L) Mayus (Izq) Shift (R) Mayus (Der) Ctrl (L) Ctrl (Izq) Ctrl (R) Ctrl (Der) Alt (L) Alt (Izq) Alt (R) Alt (Der) Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP RePag DEL SUPR PGDN AvPag 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK BLOCK NUM * * + + Enter Del E N T E R E N T E R < < : : Super (L) Super (Izq) Menu Menu Up Arriba Down Abajo Left Izquierda Right Derecha VirtualKeyboardMouseWidget Keyboard Teclado Mouse Ratón Mouse Settings Configuraciones de Ratón Left Mouse Ratón Izquierda Up Mouse Ratón Arriba Left Button Mouse Ratón Boton Izquierdo Middle Button Mouse Ratón Boton del Medio Right Button Mouse Ratón Botón Derecho Wheel Up Mouse Ratón Rueda Arriba Wheel Left Mouse Ratón Rueda Izquierda Wheel Right Mouse Ratón Rueda Derecha Wheel Down Mouse Ratón Rueda Abajo Down Mouse Ratón Abajo Right Mouse Ratón Derecha Button 4 Mouse Ratón Botón 4 Mouse 8 Mouse Ratón Ratón 8 Button 5 Mouse Ratón Botón 5 Mouse 9 Mouse Ratón Ratón 9 NONE NADA [NO KEY] [SIN TECLA] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Applications Aplicaciones Browser Back Navegador Atrás Browser Favorites Navegador Favoritos Browser Forward Navegador Adelante Browser Home Navegador Inicio Browser Refresh Navegador Actualizar Browser Search Navegador Busca Browser Stop Navegador Parar Calc Calc Email Email F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 Media Media Media Next Media Próximo Media Play Media Reproduzir Media Previous Media Anterior Media Stop Media Parar Search Buscar Volume Down Volume Bajar Volume Mute Volume Mudo Volume Up Volume Subir VirtualMousePushButton INVALID INVALIDO WinAppProfileTimerDialog Capture Application Solicitación de Captura After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Después de pulsar el botón "Solicitud de captura", por favor, seleccione la ventana de la aplicación que desea tener un perfil asociado. La aplicación activa será capturado después del número de segundos seleccionado. Timer: Temporizador: Seconds Segundos Cancel Cancelar WinExtras [NO KEY] [SIN TECLA] AntiMicroX Profile Perfil AntiMicroX X11Extras ESC ESC Tab Tab Space espaciador DEL SUPR Return ENTER KP_Enter Enter_Num Backspace Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. No se ha encontrado la extensión xinput. no se producirán cambios en la aceleración del ratón. xinput version must be at least 2.0. No mouse acceleration changes will occur. La versión xinput debe ser al menos 2,0. no se producirán cambios en la aceleración del ratón. Virtual pointer found with id=%1. Puntero virtual encontrado con el id=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 PeerFeedback clase no se encontró para el puntero virtual. Ningún cambio en la aceleración del ratón se producirá para el dispositivo con el id=%1 Changing mouse acceleration for device with id=%1 Cambiando la aceleración del ratón para el dispositivo con id=%1 XMLConfigReader Could not write updated profile XML to file %1. No se puede escribir XML del perfil actualizado en el archivo %1. XMLConfigWriter Could not write to profile at %1. No se pudo escribir al perfil en %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_fr.ts000066400000000000000000013047651377703515000275170ustar00rootroot00000000000000 AboutDialog About À propos Version <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Info Changelog Credits Crédits AntiMicroX About Development License License Program Version %1 Program Compiled on %1 at %2 Built Against SDL %1 Running With SDL %1 Using Qt %1 Using Event Handler: %1 AddEditAutoProfileDialog Auto Profile Dialog Browse Window: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties Pro&file: &Class: T&itle: set partial title Application: Select De&vices: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller A different profile is already selected as the default for this device. Current (%1) Open Config Charger un fichier de configuration Select Program Please use the main default profile selection. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Capture Application Window Could not obtain information for the selected window. Application Capture Failed Profile file path is invalid. No window matching property was specified. Program path is invalid or not executable. No window matching property was selected. AdvanceButtonDialog Advanced Avancé Assignments Assignements Toggle Maintient de la pression Turbo Turbo Set Selector Séléction de réglage Blank or KB/M Hold Maintenir Pause Pause Cycle Cycle Distance Distance Insert Insérer Delete Supprimer Clear All Nettoyer Time: Temps : 0.01s 0,01s 0s 0s Insert a pause that occurs in between key presses. Insére une pause de la durée indiquée entre la pression des touches. Release Relâchement Insert a new blank slot. Insere un nouvel emplacement vide. Join Split Delete a slot. Supprime un emplacement. Clear all currently assigned slots. Supprime tous les emplacements assignés. Specify the duration of an inserted Pause or Hold slot. Spécifie la durée de Pause ou de Maintien. 0m 0m &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Spécifie la distance par rapport à la zone morte pour exécuter la suite des actions. Distance: Distance : % % Mouse Mod Mode de la Souris Press Time Delay Execute Load Charger Set Change Text Entry Placeholder Espace réservé 0 0 Mouse Speed Mod: Vitesse du Mode de la Souris : Set the percentage that mouse speeds will be modified by. Régler toutes les vitesses de la souris avec le pourcentage spécifié. Auto Reset Cycle After seconds Executable: ... Arguments: Enabled Activé Mode: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Normal Gradient Pulse Delay: Intervalle : 0.10s 0,10s Rate: Taux : 10.0/s 10,0/s Disabled Désactivé Select Set 1 One Way Séléction du réglage N°1 : Aller Select Set 1 Two Way Séléction du réglage N°1 : Aller-Retour Select Set 1 While Held Séléction du réglage N°1 : Pendant la pression Select Set 2 One Way Séléction du réglage N°2 : Aller Select Set 2 Two Way Séléction du réglage N°2 : Aller-Retour Select Set 2 While Held Séléction du réglage N°2 : Pendant la pression Select Set 3 One Way Séléction du réglage N°3 : Aller Select Set 3 Two Way Séléction du réglage N°3 : Aller-Retour Select Set 3 While Held Séléction du réglage N°3 : Pendant la pression Select Set 4 One Way Séléction du réglage N°4 : Aller Select Set 4 Two Way Séléction du réglage N°4 : Aller-Retour Select Set 4 While Held Séléction du réglage N°4 : Pendant la pression Select Set 5 One Way Séléction du réglage N°5 : Aller Select Set 5 Two Way Séléction du réglage N°5 : Aller-Retour Select Set 5 While Held Séléction du réglage N°5 : Pendant la pression Select Set 6 One Way Séléction du réglage N°6 : Aller Select Set 6 Two Way Séléction du réglage N°6 : Aller-Retour Select Set 6 While Held Séléction du réglage N°6 : Pendant la pression Select Set 7 One Way Séléction du réglage N°7 : Aller Select Set 7 Two Way Séléction du réglage N°7 : Aller-Retour Select Set 7 While Held Séléction du réglage N°7 : Pendant la pression Select Set 8 One Way Séléction du réglage N°8 : Aller Select Set 8 Two Way Séléction du réglage N°8 : Aller-Retour Select Set 8 While Held Séléction du réglage N°8 : Pendant la pression [NO KEY] [AUCUNE TOUCHE] sec. /sec. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Select Set %1 One Way Two Way While Held Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Choose Profile Config Files (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Assignement du Stick/Pad Sticks Sticks DPads DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Manette %2) Stick 1 Stick 1 Enabled Activé Assign Assigner X Axis: Axe X : Y Axis: Axe Y : Stick 2 Stick 2 Number of Physical DPads: %1 Numéro du DPads Physique : %1 Virtual DPad 1 DPad Virtuel 1 Up: Haut : Down: Bas : Left: Gauche : Right: Droite : Axis %1 Axe %1 Axis %1 - Axe %1 - Axis %1 + Axe %1 + Button %1 Bouton %1 Move stick 1 along the X axis Déplacer le stick 1 selon l'axe X Move stick 1 along the Y axis Déplacer le stick 1 selon l'axe Y Move stick 2 along the X axis Déplacer le stick 2 selon l'axe X Move stick 2 along the Y axis Déplacer le stick 1 selon l'axe Y Press a button or move an axis Presser un bouton ou bouger un axe AxisEditDialog Axis Axe Mouse (Horizontal) Souris (Horizontal) Mouse (Inverted Horizontal) Souris (Horizontal Inversé) Mouse (Vertical) Souris (Vertical) Mouse (Inverted Vertical) Souris (Vertical Inversé) Arrows: Up | Down Flèches : Haut | Bas Arrows: Left | Right Flèches : Gauche | Droite Keys: W | S Touches : W | S Keys: A | D Touches : A | D NumPad: KP_8 | KP_2 Pavé Numérique : KP_8 | KP_2 NumPad: KP_4 | KP_6 Pavé Numérique : KP_4 | KP_6 None Aucun Set the value to use as the limit for an axis. Useful for a worn out analog stick. Negative Half Throttle Demie accélération négative Positive Half Throttle Demie accélération positive Name: Nom : Specify the name of an axis. Indiquer le nom d'un axe. Mouse Settings Configurations de la Souris Set the value of the dead zone for an axis. Régler la valeur de la zone morte pour un axe. Presets: Pré-réglages : Dead Zone: Zone morte : Max Zone: Zone maximale : [NO KEY] [AUCUNE TOUCHE] Throttle setting that determines the behavior of how to interpret an axis hold or release. Configure l’accélération qui détermine le comportement de maintien ou de relâchement d'un axe. Negative Throttle Accélération négative Normal Normal Positive Throttle Accélération positive Current Value: Valeur actuelle : Set Configuration Set %1 Left Mouse Button Right Mouse Button ButtonEditDialog Dialog Dialogue To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Pour assigner une touche à ce bouton, presser celle-ci ou cliquer sur son équivalent graphique dans les onglets clavier et souris Placeholder Espace réservé Toggle Pression continue Enables a key press or release to only occur when a controller button is pressed. Permet d'appuyer ou de relâcher une touche uniquement lorsqu'un bouton est pressé. Enables rapid key presses and releases. Turbo controller. Permet d'appuyer et de relâcher très rapidement une touche en maintenant pressé un bouton. Contrôle du Turbo. Turbo Turbo Current: Actuellement : Last keyboard/mouse button: Slots Emplacements Na&me: Nom : Specify the name of a button. Indiquer le nom d'un bouton. Action: Action : Specify the action that will be performed in game while this button is being used. Indiquer l'action qui sera exécutée pendnt le jeu lorsque que ce bouton est utilisé. Advanced Avancé Set Configuration Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [AUCUNE TOUCHE] Calibration Form Start calibration Sticks: Reset settings Cancel Save Enregistrer Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 Axe %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path Full Path File Name CommandLineUtility Profile location %1 is not an XML file. Le fichier profile %1 n'est pas un fichier XML. Profile location %1 does not exist. Le fichier profile %1 n'existe pas. Controller identifier is not a valid value. L'identifiant du contrôleur n'est pas une valeur valide. Options Options Print help text. Affiche le texte d'aide. Print version information. Affiche des informations sur la version. Launch program in system tray only. Lance le logiciel directement dans la zone de notification. Launch program with the tray menu disabled. Lance le logiciel avec le menu de la zone de notification désactivé. Launch program without the main window displayed. Lance le logiciel sans afficher la fenêtre principale. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Lance le programme avec le fichier de configuration séléctionné par défaut pour le contrôleur choisi. Par défaut, tous les contrôleurs. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Appliquer le fichier de configuration à un contrôleur specifique. La valeur peut être un index, un nom ou le GUID d'un controleur. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Déchargé le(s) profil(s) actuellement activés. La valeur peut être un index, un nom ou le GUID d'un controleur. DPadContextMenu Mouse (Normal) Souris (Normal) Mouse (Inverted Horizontal) Souris (Horizontal Inversé) Mouse (Inverted Vertical) Souris (Vertical Inversé) Mouse (Inverted Horizontal + Vertical) Souris (Vertical et Horizontal Inversés) Arrows Flèches Keys: W | A | S | D Touches :W | A | S | D NumPad None Standard Standard Eight Way Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings Configurations de la Souris DPadEditDialog Dialog Dialogue Presets: Pré-réglages : Mouse (Normal) Souris (Normal) Mouse (Inverted Horizontal) Souris (Horizontal Inversé) Mouse (Inverted Vertical) Souris (Vertical Inversé) Mouse (Inverted Horizontal + Vertical) Souris (Vertical et Horizontal Inversés) Arrows Flèches Keys: W | A | S | D Touches :W | A | S | D NumPad Pavé Numérique None Aucun Dpad Mode: Mode Dpad : &Name: 4 Way Cardinal 4 Way Diagonal DPad Delay: Time lapsed before a direction change is taken into effect. s Specify the name of a dpad. Indiquer le nom d'un dpad. Mouse Settings Configurations de la Souris Standard Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way Eight Way Set Configuration Set %1 EditAllDefaultAutoProfileDialog Default Profile Profile: Browse Open Config Charger un fichier de configuration Profile file path is invalid. ExtraProfileSettingsDialog Extra Profile Settings Key Press Time: 0.00 ms Profile Name: s GameController Game Controller GameControllerDPad DPad GameControllerMappingDialog Game Controller Mapping Cartographie de contrôleur de jeu <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A B X Y Back Retour Start Guide Left Shoulder Latéral gauche Right Shoulder Latéral droit Left Stick Click Clic Stick Gauche Right Stick Click Clic Stick Droite Left Stick X Stick Gauche X Left Stick Y Stick Gauche Y Right Stick X Stick Droit X Right Stick Y Stick Droit Y Left Trigger Gachette gauche Right Trigger Gachette droite DPad Up DPad Haut DPad Left DPad Gauche DPad Down DPad Bas DPad Right DPad Droit Mapping Cartographie SDL 2 Game Controller Mapping String Last Axis Event: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Discard Controller Mapping? Désactivé la cartographie de contrôleur de jeu ? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Eliminer la cartographie pour ce contrôleur ? S'il est éliminé, le contrôleur redeviendra un joystick une fois tous les joysticks mis à jour. GameControllerSet Back Retour Guide Start LS Click RS Click L Shoulder R Shoulder L Trigger R Trigger GameControllerTrigger Trigger Gachette JoyAxis Axis Axe JoyAxisButton Negative Négatif Positive Positif Unknown Inconnu Button Bouton JoyAxisContextMenu Mouse (Horizontal) Souris (Horizontal) Mouse (Inverted Horizontal) Souris (Horizontal Inversé) Mouse (Vertical) Souris (Vertical) Mouse (Inverted Vertical) Souris (Vertical Inversé) Arrows: Up | Down Flèches : Haut | Bas Arrows: Left | Right Flèches : Gauche | Droite Keys: W | S Touches : W | S Keys: A | D Touches : A | D NumPad: KP_8 | KP_2 Pavé Numérique : KP_8 | KP_2 NumPad: KP_4 | KP_6 Pavé Numérique : KP_4 | KP_6 None Mouse Settings Configurations de la Souris Left Mouse Button Right Mouse Button JoyButton Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Button Bouton [NO KEY] [AUCUNE TOUCHE] [Set %1 1W] [Set %1 2W] [Set %1 WH] JoyButtonContextMenu Toggle Turbo Turbo Clear Set Select Disabled Désactivé Set %1 Set %1 1W Set %1 2W Set %1 WH JoyButtonSlot Mouse Souris Up Haut Down Bas Left Gauche Right Droite LB BG MB BC RB BD B4 B4 B5 B5 Pause Pause Hold Maintenir Cycle Cycle Distance Distance Release Relâchement Mouse Mod Mode de la Souris Press Time Delay Load %1 Set Change %1 [Text] %1 [Exec] %1 [NO KEY] [AUCUNE TOUCHE] JoyControlStick Stick JoyControlStickButton Up Haut Down Bas Left Gauche Right Droite Button Bouton JoyControlStickContextMenu Mouse (Normal) Souris (Normal) Mouse (Inverted Horizontal) Souris (Horizontal Inversé) Mouse (Inverted Vertical) Souris (Vertical Inversé) Mouse (Inverted Horizontal + Vertical) Souris (Vertical et Horizontal Inversés) Arrows Flèches Keys: W | A | S | D Touches :W | A | S | D NumPad None Standard Standard Eight Way Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings Configurations de la Souris JoyControlStickEditDialog Dialog Dialogue X: X : 0 0 Y: Y : Distance: Distance : Presets: Pré-réglages : Mouse (Normal) Souris (Normal) Mouse (Inverted Horizontal) Souris (Horizontal Inversé) Mouse (Inverted Vertical) Souris (Vertical Inversé) Mouse (Inverted Horizontal + Vertical) Souris (Vertical et Horizontal Inversés) Arrows Flèches Keys: W | A | S | D Touches :W | A | S | D NumPad NumPad None Aucub Stick Mode: Mode du Stick : Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4 Way Diagonal Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. Square Stick: Percentage to modify a square stick coordinates to confine values to a circle % % Stick Delay: Time lapsed before a direction change is taken into effect. s Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Na&me: Name: Nom : Specify the name of an analog stick. Indiquer le nom d'un stick analogue. Mouse Settings Configurations de la Souris Standard Standard Bearing: % Safe Zone: Eight Way Eight Way Dead Zone: Zone morte : Max Zone: Zone maximale : Diagonal Range: Valleur de diagonale : Set Configuration Set %1 JoyControlStickModifierButton Modifier JoyDPad DPad JoyDPadButton Up Haut Down Bas Left Gauche Right Droite Button Bouton JoyTabWidget <New> <Nouveau> Remove Supprimer Remove configuration from recent list. Supprimer la configuration depuis la liste des recents. Load Charger Load configuration file. Charger un fichier de configuration. Save Enregistrer Save changes to configuration file. Enregistrer les modifications dans le fichier de configuration. Save As Enregistrer Sous Save changes to a new configuration file. Enregistrer les modifications dans un nouveau fichier de configuration. Sets Copy from Set Settings Set 1 Set 2 Set 3 Set 4 Set 5 Set 6 Set 7 Set 8 Stick/Pad Assign Assignement du Stick/Pad Controller Mapping Quick Set Configuration Rapide Names Noms Toggle button name displaying. Alterner nom du bouton d'affichage. Pref Change global profile settings. Reset Réinitialiser Revert changes to the configuration. Reload configuration file. Annuler les changements de configuration. Recharger le fichier de configuration. Open Config Charger un fichier de configuration Config Files (*.amgp *.xml) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks Sticks DPads DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 Set %1 Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Save Config Enregistrer le fichier de configuration Set Configuration Joystick Joystick Manette JoystickStatusWindow Properties Propriétés Details Détails Name: Nom : %1 %1 Number: Nombre : Axes: Axes : Buttons: Boutons : Hats: Hats : Battery: Unknown Inconnu GUID: GUID : Game Controller: Axes Axes Buttons Boutons Hats Hats %1 (#%2) Properties %1 (#%2) Propriétés Axis %1 Axe %1 Hat %1 Hat %1 No Yes MainSettingsDialog Edit Settings Modifier les paramètres General Controller Mappings Cartographie de contrôleur Language Auto Profile Mouse Souris Advanced Avancé <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> Recent Profile Count: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Close To Tray Have Windows start AntiMicroX at system startup. Launch At Windows Startup Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Single Profile List in Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimize to Taskbar This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Hide Empty Buttons When the program is launched, open the last known profile that was opened during the previous session. Auto Load Last Opened Profile Only show the system tray icon when the program first launches. Launch in Tray Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Active keys will be repeatedly pressed when this option is enabled. Enable Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Error Warning Info Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset Réinitialiser Class Title Program Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision Smoothing Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Ressort Screen: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: 0 0 Accel Denominator: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Delay: Intervalle : Pro&file Directory: ms Rate: Taux : times/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Voici une liste des cartographies personnalisées qui ont été enregistrées. Utiliser le tableau suivant pour supprimer les cartographies ou désactiver temporairement une cartographie. Il est également possible de désactiver les cartographies qui sont inclus avec SDL, il suffit d'insérer une nouvelle ligne avec le GUID du manette approprié et cocher la case désactiver. Les paramètres ne prennent effet que lors de la prochaine réactualisation des joysticks ou en débranchant la manette spécifique. GUID Mapping String Chaîne de cartographie Disable? Désactiver ? Delete Supprimer Insert Insérer Default English Active Devices: All Device Profile Default? Add Edit Select Default Profile Directory Are you sure you want to delete the profile? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [AUCUNE TOUCHE] MainWindow No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Aucune manette n'a été détéctée. Merci de brancher une manette et de choisir l'option "Mettre à jour les manettes" du menu principal If events are not seen by a game, please click here to run this application as Administrator. &App Stick/Pad Assign Assignement du Stick/Pad &Options &Options AntiMicroX &Help &Aide He&lp &Quit &Quitter Ctrl+Q Ctrl+Q &Update Joysticks &Mettre à jour les manettes Ctrl+U Ctrl+U &Hide &Masquer Ctrl+H Ctrl+H &About &À propos Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt À propos de Qt Properties Propriétés Key Checker Vérificateur de clé Home Page Page d'accueil GitHub Page Page GitHub Game Controller Mapping Cartographie de contrôleur de jeu Could not find a proper controller identifier. Exiting. (%1) Open File Ouvrir fichier %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore &Restaurer Calibration couldn't be opened You must connect at least one controller to open the window Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Configurations de la Souris - Set %1 MouseButtonSettingsDialog Mouse Settings - Configurations de la Souris - Set %1 MouseControlStickSettingsDialog Mouse Settings Configurations de la Souris Set %1 MouseDPadSettingsDialog Mouse Settings Configurations de la Souris Set %1 MouseSettingsDialog Mouse Settings Configurations de la Souris Mouse Mode: Mode de la Souris : Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Le mode "curseur" est utilisé pour déplacer le curseur de la souris autour de l'écran par rapport à sa position actuelle en fonction de la pression d'un axe ou d'un bouton. Le mode "ressort" est utilisé pour déplacer la souris depuis le centre de l'écran en fonction de la pression d'un axe. Le curseur de la souris retourne au centre de l'écran quand l'axe est déplacé vers la zone morte. Cursor Curseur Spring Ressort Acceleration: Accélération : Enhanced Precision Linear Linéair Quadratic Quadratique Cubic Cubique Quadratic Extreme Quadratique Extreme Power Function Fonction Énergie Easing Quadratic Easing Cubic Mouse Speed Settings Configurations de la Vitesse de la Souris Enable to change the horizontal and vertical speed boxes at the same time. Activer la modification simultanée des boîtes de vitesse horizontale et verticale. Change Together Modifier en même temps Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: Horizontal Speed: Vitesse horizontale : 1 = 20 pps 1 = 20 pps Vertical Speed: Vitesse verticale : Wheel Hori. Speed: Molette Hori. Vitesse : Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: s Highest value to accelerate mouse movement by x Start %: Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Max Threshold: Maximum axis travel before acceleration has reached the multiplier value E&xtra Duration: Curve: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Mouse Status X: X : 0 (0 pps) Y: Y : 1 = 1 notch(es)/s 1 = 1 cran(s)/s Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Molette Vert. Vitesse : Sensitivity: Sensibilité : Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Configuration du Ressort Spring Width: Largeur du Ressort : Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Modifie la largeur de la région dans laquelle le curseur peut se déplacer en mode "ressort". 0 utilise toute la largeur de l'écran. Spring Height: Hauteur du Ressort : Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Modifie la hauteur de la région dans laquelle le curseur peut se déplacer en mode "ressort". 0 utilise toute la hauteur de l'écran. %n notch(es)/s %n cran/s %n crans/s ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Vérificateur de touche <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Native Key Value: Valeur native de la touche : 0x00000000 Qt Key Value: Valeur de la touche Qt : antimicro Key Value: QObject Super Super Pause Pause Next Suivant Home Début Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Failed to launch daemon Launching daemon Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to change working directory to / Quitting Program # of joysticks found: %1 List Joysticks: --------------- Joystick %1: Index: %1 UniqueID: %1 GUID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Yes No Game Controller: %1 # of Axes: %1 # of Buttons: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Le fichier profile %1 n'est pas un fichier XML. Profile location %1 does not exist. Le fichier profile %1 n'existe pas. Controller identifier is not a valid value. L'identifiant du contrôleur n'est pas une valeur valide. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. No controller was specified. No display string was specified. An invalid event generator was specified. No event generator string was specified. No log file specified. Options Options Print help text. Affiche le texte d'aide. Print version information. Affiche des informations sur la version. Launch program in system tray only. Lance le logiciel directement dans la zone de notification. Launch program with the tray menu disabled. Lance le logiciel avec le menu de la zone de notification désactivé. Launch program without the main window displayed. Lance le logiciel sans afficher la fenêtre principale. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Lance le programme avec le fichier de configuration séléctionné par défaut pour le contrôleur choisi. Par défaut, tous les contrôleurs. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Appliquer le fichier de configuration à un contrôleur specifique. La valeur peut être un index, un nom ou le GUID d'un controleur. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Déchargé le(s) profil(s) actuellement activés. La valeur peut être un index, un nom ou le GUID d'un controleur. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set Configuration Rapide <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Merci de presser un bouton ou de bouger un axe de %1 (<span style=" font-weight:600;">%2</span>).<br/>Une fenêtre de dialogue va apparaître<br/>pour permettre de faire une assignation.</p></body></html> Quick Set %1 Configuration Rapide %1 SetAxisThrottleDialog Throttle Change Modifier l'accélération The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? axes ou axe dans ce cas ? La configuration de l'accélération de l'axe %1 a été modifié. Faut-il appliquer cette valeur d'accélération à tous les réglages ? SetJoystick Set %1: %2 Set %1 SetNamesDialog Set Name Settings Set 1 Set 2 Set 3 Set 4 Set 5 Set 6 Set 7 Set 8 Name SimpleKeyGrabberButton Mouse Souris SpringModeRegionPreview Spring Mode Preview Aperçu du mode ressort UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Using uinput device file %1 UInputHelper a q b c d e f g h i j k l m , n o p q a r s t u v w z x y z w Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - = BackSpace Retour Arrière Tab Tab [ ] \ CapsLock ; ' Enter Shift_L Maj_G , . / Ctrl_L Super_L Super_L Alt_L Alt_L Space Espace Alt_R Alt_R Menu Menu Ctrl_R Shift_R Maj_D Up Haut Left Gauche Down Bas Right Droite PrtSc Ins Del Home Début End End PgUp PgDn NumLock * + KP_Enter KP_Entrée KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9 KP_0 SCLK Arrêt Defil Pause Pause Super_R Mute VolDn VolUp Play Stop Prev Next Suivant [NO KEY] [AUCUNE TOUCHE] UnixWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path VDPad VDPad VirtualKeyPushButton Space Espace Tab Tab Shift (L) Maj (G) Shift (R) Maj (D) Ctrl (L) Ctrl (G) Ctrl (R) Ctrl (D) Alt (L) Alt (G) Alt (R) Alt (D) Alt Gr ` ~ - = [ ] \ Caps Verr Maj ; ' , . / ESC ECHAP PRTSC Impr Ecran SCLK Arrêt Defil INS INSER PGUP PGUP DEL SUPPR PGDN PGDN 1 2 3 4 5 6 7 8 9 0 NUM LK VERR NUM * + Enter Del E N T E R E N T R É E < : Super (L) Super (G) Menu Up Haut Down Bas Left Gauche Right Droite VirtualKeyboardMouseWidget Keyboard Clavier Mouse Souris Mouse Settings Configurations de la Souris Left Mouse Gauche Up Mouse Haut Left Button Mouse Middle Button Mouse Right Button Mouse Wheel Up Mouse Molette bas Wheel Left Mouse Molette gauche Wheel Right Mouse Molette droite Wheel Down Mouse Molette bas Down Mouse Bas Right Mouse Droite Button 4 Mouse Bouton 4 Mouse 8 Mouse Souris 8 Button 5 Mouse Bouton 5 Mouse 9 Mouse Souris 9 NONE AUCUNE [NO KEY] [AUCUNE TOUCHE] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Browser Back Browser Favorites Browser Forward Browser Home Browser Refresh Browser Search Browser Stop Calc Email F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 Media Media Next Media Play Media Previous Media Stop Search Volume Down Volume Mute Volume Up VirtualMousePushButton INVALID INVALIDE WinExtras [NO KEY] [AUCUNE TOUCHE] X11Extras ESC ECHAP Tab Tab Space Espace DEL SUPPR Return KP_Enter KP_Entrée Backspace Retour arrière Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Changing mouse acceleration for device with id=%1 XMLConfigReader Could not write updated profile XML to file %1. Impossible de mettre à jour le profil XML du fichier %1. XMLConfigWriter Could not write to profile at %1. Impossible d'écrire le profil %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Lance le logiciel directement dans la zone de notification. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_it.ts000066400000000000000000013703631377703515000275210ustar00rootroot00000000000000 AboutDialog About A proposito Version Versione <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Copyright: 2013 - 2016 {2013 ?} {2020?} {2013 ?} Copyright: 2013 - 2018 Copyright: 2013 - 2016 {2013 ?} {2018?} {2013 ?} Info Info Changelog Changelog Copyright: 2013 - 2016 Copyright: 2013 - 2016 {2013 ?} {2016?} Credits Ringraziamenti AntiMicroX AntiMicroX About Development Informazioni sviluppo License Licenza Program Version %1 Versione programma %1 Program Compiled on %1 at %2 Programma compilato il %1 alle %2 Built Against SDL %1 Costruito con SDL %1 Running With SDL %1 Eseguito con SDL %1 Using Qt %1 Utilizzando Qt %1 Using Event Handler: %1 Gestore di eventi in uso: %1 AddEditAutoProfileDialog Auto Profile Dialog Finestra di auto-profilo Profile: Profilo: Pro&file: Browse Sfoglia Window: Finestra: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Seleziona la finestra. Clicca la finestra giusta e il percorso al file dell'applicazione riempirà il campo. Detect Window Properties Rileva proprietà finestra &Class: T&itle: Class: Classe: Title: Titolo: set partial title Application: Applicazione: Select Seleziona De&vices: Devices: Dispositivi: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Seleziona questo profilo per renderlo il predefinito per il dispositivo specificato. La selezione verrà usata al posto di qualsiasi altro profilo predefinito. Set as Default for Controller Imposta come controller predefinito A different profile is already selected as the default for this device. È già stato selezionato un altro profilo come predefinito per questo dispositivo. Current (%1) Corrente (%1) Open Config Apri configurazione Select Program Seleziona programma Programs (*.exe) Programmi (*.exe) Please use the main default profile selection. Per favore usa la selezione profilo predefinita principale. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Per favore seleziona una finestra utilizzando il mouse. Premi Esc se vuoi annullare. Capture Application Window Cattura finestra applicazione Could not obtain information for the selected window. Impossibile ottenere le informazioni della finestra selezionata. Application Capture Failed Cattura applicazione fallita Profile file path is invalid. Percorso del file di profilo invalida. No window matching property was specified. Non è stata specificata alcuna proprietà per identificare la finestra. Program path is invalid or not executable. Il programma è invalido o non è un eseguibile. File is not an .exe file. Il file non è un .exe. No window matching property was selected. Non è stata selezionata alcuna proprietà per identificare la finestra. AdvanceButtonDialog Advanced Avanzate Assignments Assegnazioni Toggle Cambio stato Turbo Turbo Set Selector Selezionatore set Blank or KB/M Vuoto o Tastiera/Mouse Hold Tieni Pause Pausa Cycle Ciclo Distance Distanza Insert Inserisci Delete Cancella Clear All Cancella tutto Time: Tempo: 0.01s 0.01s 0s 0s Insert a pause that occurs in between key presses. Inserisci una pausa tra un tasto e l'altro. Release Rilascia Insert a new blank slot. Inserisci un nuovo slot vuoto. Join Split Delete a slot. Cancella uno slot. Clear all currently assigned slots. Cancella tutti gli slot assegnati. Specify the duration of an inserted Pause or Hold slot. Specifica la durata di una Pausa inserita o di un Tieni. 0m 0m &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Specifica l'intervallo dopo la zona morta di un'asse in cui una sequenza di azioni verrà eseguita. Distance: Distanza: % % Mouse Mod Modifica mouse Press Time Tempo di pressione Delay Ritardo Execute Esegui Load Carica Set Change Cambio di set Text Entry Inserimento testo Placeholder Segnaposto 0 0 Mouse Speed Mod: Modifica velocità mouse: Set the percentage that mouse speeds will be modified by. Imposta la percentuale con cui le velocità del mouse verranno modificate. Auto Reset Cycle After Auto-resetta ciclo dopo seconds secondi Executable: ... ... Arguments: Enabled Attivato Mode: Modalità: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Normale: preme e rilascia ripetutamente un tasto a seconda del rapporto scelto.</p><p>Gradiente: modifica il tasto premuto e il ritardo di un tasto rilasciato a seconda di quanto è stata mossa un'asse. Il rapporto rimarrà lo stesso.</p><p>Pulsa: modifica quante volte un tasto viene premuto e rilasciato al secondo. Il ritardo del tasto rimarrà lo stesso.</p></body></html> Normal Normale Gradient Gradiente Pulse Pulsa Delay: Ritardo: 0.10s 0.10s Rate: Rapporto: 10.0/s 10.0/s Disabled Disattivato Select Set 1 One Way Selezione set 1 a una direzione Select Set 1 Two Way Selezione set 1 a due direzioni Select Set 1 While Held Selezione set 1 finché premuto Select Set 2 One Way Selezione set 2 a una direzione Select Set 2 Two Way Selezione set 2 a due direzioni Select Set 2 While Held Selezione set 2 finché premuto Select Set 3 One Way Selezione set 3 a una direzione Select Set 3 Two Way Selezione set 3 a due direzioni Select Set 3 While Held Selezione set 3 finché premuto Select Set 4 One Way Selezione set 4 a una direzione Select Set 4 Two Way Selezione set 4 a due direzioni Select Set 4 While Held Selezione set 4 finché premuto Select Set 5 One Way Selezione set 5 a una direzione Select Set 5 Two Way Selezione set 5 a due direzioni Select Set 5 While Held Selezione set 5 finché premuto Select Set 6 One Way Selezione set 6 a una direzione Select Set 6 Two Way Selezione set 6 a due direzioni Select Set 6 While Held Selezione set 6 finché premuto Select Set 7 One Way Selezione set 7 a una direzione Select Set 7 Two Way Selezione set 7 a due direzioni Select Set 7 While Held Selezione set 7 finché premuto Select Set 8 One Way Selezione set 8 a una direzione Select Set 8 Two Way Selezione set 8 a due direzioni Select Set 8 While Held Selezione set 8 finché premuto [NO KEY] [NO TASTO] sec. sec. /sec. /sec. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Set %1 Select Set %1 Seleziona set %1 One Way a una direzione Two Way a due direzioni While Held finché premuto Choose Executable Scegli eseguibile Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Gli slot dopo un'azione Ciclo verranno eseguiti al prossimo tasto premuto. Cicli multipli possono essere aggiunti per creare partizioni in sequenza. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Ritarda il tempo dopo il quale il prossimo slot viene attivato per il tempo specificato. Gli slot attivati prima del ritardo rimarranno attivi finché il ritardo non trascorre. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. L'azione Distanza specifica che gli slot successivi verranno eseguiti solo quando un'asse si muove oltre un certo intervallo dopo la zona morta. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Inserisce un'azione Tieni. Gli slot dopo l'azione verranno eseguiti solo se il tasto viene tenuto premuto oltre all'intervallo specificato. Chose a profile to load when this slot is activated. Scegli un profilo da caricare quando questo slot viene attivato. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. L'azione Modifica mouse modificherà tutte le impostazioni della velocità mouse di una percentuale specifica mentre l'azione viene processata. Questo può tornare utile per rallentare il mouse usando un fucile da cecchino. Specify the time that keys past this slot should be held down. Specifica il tempo in cui i tasti dopo questo slot debbano restare premuti. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Inserisce un'azione di rilascio. Gli slot dopo l'azione verranno eseguiti solo dopo il rilascio di un tasto se il tasto è stato premuto dopo l'intervallo specificato. Change to selected set once slot is activated. Cambia il set selezionato quando lo slot viene attivato. Full string will be typed when a slot is activated. Una stringa verrà digitata quando uno slot viene attivato. Execute program when slot is activated. Esegue un programma quando lo slot viene attivato. Choose Profile Scegli profilo Config Files (*.amgp *.xml) File di configurazione (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Assegnazioni analogico/pad Sticks Analogici DPads DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Joystick %2) Stick 1 Analogico 1 Enabled Attivato Assign Assegna X Axis: Asse X: Y Axis: Asse Y: Stick 2 Analogico 2 Number of Physical DPads: %1 Numero di DPad fisici: %1 Virtual DPad 1 DPad virtuale 1 Up: Su: Down: Giù: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Nota: questa finestra è destinata alla retrocompatibilità coi profili creati prima di AntiMicroX 2.0. Dalla versione 2.0, è preferibile l'uso della finestra Mappatura controller di gioco. Left: Sinistra: Right: Destra: Axis %1 Asse %1 Axis %1 - Asse %1 - Axis %1 + Asse %1 + Button %1 Tasto %1 Move stick 1 along the X axis Muovere analogico 1 lungo l'asse X Move stick 1 along the Y axis Muovere analogico 1 lungo l'asse Y Move stick 2 along the X axis Muovere analogico 2 lungo l'asse X Move stick 2 along the Y axis Muovere analogico 2 lungo l'asse Y Press a button or move an axis Premere un tasto o muovere un'asse AxisEditDialog Axis Asse Mouse (Horizontal) Mouse (orizzontale) Mouse (Inverted Horizontal) Mouse (orizzontale invertito) Mouse (Vertical) Mouse (verticale) Mouse (Inverted Vertical) Mouse (verticale invertito) Arrows: Up | Down Frecce: Su | Giù Arrows: Left | Right Frecce: Sinistra | Destra Keys: W | S Tasti: W | S Keys: A | D Tasti: A | D NumPad: KP_8 | KP_2 TastNum: TN_8 | TN_2 NumPad: KP_4 | KP_6 TastNum: TN_4 | TN_6 None Niente Set the value to use as the limit for an axis. Useful for a worn out analog stick. Imposta il valore da usare come limite per un'asse. Utile per un analogico consumato. Negative Half Throttle Acceleratore negativo a metà Positive Half Throttle Acceleratore positivo a metà Name: Nome: Specify the name of an axis. Specifica il nome di un'asse. Mouse Settings Impostazioni mouse Set the value of the dead zone for an axis. Imposta il valore della zona morta per un'asse. Presets: Preimpostazioni: Dead Zone: Zona morta: Max Zone: Zona massima: [NO KEY] [NO TASTO] Throttle setting that determines the behavior of how to interpret an axis hold or release. Impostazione dell'acceleratore che determina come interpretare il rilascio o la pressione di un'asse. Negative Throttle Acceleratore negativo Normal Normale Positive Throttle Acceleratore positivo Current Value: Valore corrente: Set Set Set %1 Set %1 Left Mouse Button Tasto sinistro del mouse Right Mouse Button Tasto destro del mouse ButtonEditDialog Dialog Finestra di dialogo To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Per assegnare un nuovo tasto, premere qualunque tasto della tastiera o cliccare un pulsante nella sezione Tastiera o Mouse Placeholder Segnaposto Toggle Cambio stato Enables a key press or release to only occur when a controller button is pressed. Abilita la pressione o il rilascio di un tasto solo quando il tasto di un controller viene premuto. Enables rapid key presses and releases. Turbo controller. Abilita la pressione e il rilascio rapidi di un tasto. Controller turbo. Turbo Turbo Current: Corrente: Last keyboard/mouse button: Slots Slot Na&me: Nome: Specify the name of a button. Specifica il nome di un tasto. Action: Azione: Specify the action that will be performed in game while this button is being used. Specifica l'azione che verrà eseguita in gioco mentre questo tasto viene usato. Advanced Avanzate Set Set Set %1 Set %1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [NO TASTO] Calibration Form Start calibration Sticks: Reset settings Cancel Annulla Save Salva Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 Asse %1 CapturedWindowInfoDialog Captured Window Properties Proprietà finestra catturata Information About Window Informazioni sulla finestra Class: Classe: TextLabel etichetta di testo Title: Titolo: Path: Percorso: Match By Properties Trova per proprietà Class Classe Title Titolo Path Percorso Full Path Percorso completo File Name Nome file CommandLineUtility Profile location %1 is not an XML file. Il profilo in %1 non è un file XML. Profile location %1 does not exist. Il profilo in %1 non esiste. An invalid set number '%1' was specified. È stato specificato un numero di set '%1' invalido. Controller identifier '%s'' is not a valid value. L'identificatore controller '%s'' non è un valore valido. No display string was specified. Non è stata specificata una stringa di visualizzazione. Controller identifier is not a valid value. L'identificatore controller non è un valore valido. No set number was specified. Non è stato specificato un numero di set. No controller was specified. Non è stato specificato un controller. An invalid event generator was specified. È stato specificato un generatore di eventi invalido. No event generator string was specified. Nessuna stringa di generatore eventi è stata specificata. Qt style flag was detected but no style was specified. È stato rilevato il flag stile Qt ma non è stato specificato alcuno stile. No log level specified. Nessun livello di log specificato. AntiMicroX version versione AntiMicroX Usage: AntiMicroX [options...] [profile] Utilizzo: AntiMicroX [options...] [profile] Options Opzioni Print help text. Stampa testo di aiuto. Print version information. Stampa informazioni versione. Launch program in system tray only. Esegui programma solo nella barra di sistema. Launch program with the tray menu disabled. Esegui programma con la barra di sistema disattivata. Launch program without the main window displayed. Esegui programma senza visualizzare la finestra principale. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Esegui programma con il file di configurazione selezionato come predefinito per i controller selezionati. Diventa il valore predefinito di tutti i controller. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Applica file di configurazione ad un controller specifico. Il valore può essere un indice controller, nome, o GUID. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Libera profilo/i attivati. Il valore può essere un indice controller, nome, o GUID. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Esegui joystick su un set specifico. Il valore può essere un indice controller, nome, o GUID. Advance profile loading set options. Avanza caricamento opzioni set profilo. Launch program as a daemon. Esegui programma come demone. Enable logging. Abilita logging. Use specified display for X11 calls. Useful for ssh. Usa il display specificato per le chiamate X11. Utile per l'SSH. Choose between using XTest support and uinput support for event generation. Default: xtest. Scegli se usare il supporto XTest o uinput per la generazione di eventi. Predefinito: xtest. Choose between using SendInput and vmulti support for event generation. Default: sendinput. Scegli se usare il supporto SentInput o vmulti per la generazione di eventi. Predefinito: sendinput. Print information about joysticks detected by SDL. Stampa informazioni riguardo i joystick rilevati da SDL. Open game controller mapping window of selected controller. Value can be a controller index or GUID. Apri finestra Mappatura controller di gioco del controller scelto. Il valore può essere un indice controller o GUID. DPadContextMenu Mouse (Normal) Mouse (normale) Mouse (Inverted Horizontal) Mouse (orizzontale invertito) Mouse (Inverted Vertical) Mouse (verticale invertito) Mouse (Inverted Horizontal + Vertical) Mouse (orizzontale + verticale invertito) Arrows Frecce Keys: W | A | S | D Tasti: W | A | S | D NumPad TastNum None Niente Standard Standard Eight Way 8 direzioni 4 Way Cardinal 4 direzioni cardinali 4 Way Diagonal 4 direzioni diagonali Mouse Settings Impostazioni mouse DPadEditDialog Dialog Finestra di dialogo Presets: Preimpostazioni: Mouse (Normal) Mouse (normale) Mouse (Inverted Horizontal) Mouse (orizzontale invertito) Mouse (Inverted Vertical) Mouse (verticale invertito) Mouse (Inverted Horizontal + Vertical) Mouse (orizzontale + verticale invertito) Arrows Frecce Keys: W | A | S | D Tasti: W | A | S | D NumPad TastNum None Niente Dpad Mode: Modalità DPad: &Name: Nome: 4 Way Cardinal 4 direzioni cardinali 4 Way Diagonal 4 direzioni diagonali DPad Delay: Ritardo DPad: Time lapsed before a direction change is taken into effect. Tempo trascorso prima che il cambiamento di una direzione abbia effetto. s s Specify the name of a dpad. Specifica il nome di un DPad. Mouse Settings Impostazioni mouse Standard Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Standard: DPad a 8 regioni con due tasti direzionali attivi quando il DPad è in una regione diagonale. 8 direzioni: DPad a 8 regioni con ogni direzione che ha un tasto dedicato. Solo un tasto alla volta viene premuto. Utile per i giochi come Rogue. 4 direzioni cardinali: DPad a 4 regioni con regioni corrispondenti alla direzione cardinale del DPad. Utile per i menu. 4 direzioni diagonali: DPad a 4 regioni con ogni regione corrispondente alla zona diagonale del DPad. Eight Way 8 direzioni Set Set Set %1 Set %1 EditAllDefaultAutoProfileDialog Default Profile Profilo predefinito Profile: Profilo: Browse Sfoglia Open Config Apri configurazione Profile file path is invalid. Il percorso del profilo è invalido. ExtraProfileSettingsDialog Extra Profile Settings Altre impostazioni profilo Key Press Time: Tempo pressione tasto: 0.00 ms 0.00 ms Profile Name: Nome profilo: s s GameController Game Controller Controller di gioco GameControllerDPad DPad DPad GameControllerMappingDialog Game Controller Mapping Mappatura controller di gioco <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> <html><head/><body><p>AntiMicroX utilizza la <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> fornita da SDL 2 per astrarre vari gamepad e adattarli a un unico standard. Per assegnare un tasto, per favore evidenzia la cella di mappatura per il tasto della riga giusta qui sotto. Dopodiché puoi premere un tasto o muovere un'asse sul tuo gamepad e la cella si aggiornerà con il tasto fisico o l'asse che verrà usata.</p><p>AntiMicroX userà la mappatura che hai specificato per salvare una stringa di mappatura che verrà caricata in SDL.</p></body></html> A A B B X X Y Y Back Back Start Start Guide Guide Left Shoulder Dorsale sinistro Right Shoulder Dorsale destro Left Stick Click Click analogico sinistro Right Stick Click Click analogico destro Left Stick X Analogico sinistro X Left Stick Y Analogico sinistro Y Right Stick X Analogico destro X Right Stick Y Analogico destro Y Left Trigger Grilletto sinistro Right Trigger Grilletto destro DPad Up DPad su DPad Left DPad sinistra DPad Down DPad giù DPad Right DPad destra Mapping Mappatura SDL 2 Game Controller Mapping String Stringa di mappatura Game controller SDL 2 Last Axis Event: Ultimo evento asse: Current Axis Detection Dead Zone: Rilevamento corrente della zona morta dell'asse: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Mappatura controller di gioco (%1) (#%2) Discard Controller Mapping? Scartare mappatura controller? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Scartare mappatura di questo controller? Scartandola, il controller tornerà ad essere un joystick una volta aggiornati tutti i joystick. GameControllerSet Back Indietro Guide Guida Start Start LS Click Click analog SX RS Click Click analog DX L Shoulder Dorsale SX R Shoulder Dorsale DX L Trigger Grilletto SX R Trigger Grilletto DX GameControllerTrigger Trigger Grilletto JoyAxis Axis Asse JoyAxisButton Negative Negativo Positive Positivo Unknown Sconosciuto Button Tasto JoyAxisContextMenu Mouse (Horizontal) Mouse (orizzontale) Mouse (Inverted Horizontal) Mouse (orizzontale invertito) Mouse (Vertical) Mouse (verticale) Mouse (Inverted Vertical) Mouse (verticale invertito) Arrows: Up | Down Frecce: Su | Giù Arrows: Left | Right Frecce: Sinistra | Destra Keys: W | S Tasti: W | S Keys: A | D Tasti: A | D NumPad: KP_8 | KP_2 TastNum: TN_8 | TN_2 NumPad: KP_4 | KP_6 TastNum: TN_4 | TN_6 None Niente Mouse Settings Impostazioni mouse Left Mouse Button Tasto sinistro del mouse Right Mouse Button Tasto destro del mouse JoyButton Processing turbo for #%1 - %2 Processando turbo per #%1 - %2 Finishing turbo for button #%1 - %2 Finendo turbo per tasto #%1 - %2 Processing press for button #%1 - %2 Processando pressione per tasto #%1 - %2 Processing release for button #%1 - %2 Processando rilascio per tasto #%1 - %2 Distance change for button #%1 - %2 Cambio di distanza per tasto #%1 - %2 Button Tasto [NO KEY] [NO TASTO] [Set %1 1W] [Set %1 1DIREZ] [Set %1 2W] [Set %1 2DIREZ] [Set %1 WH] [Set %1 PREMENDO] JoyButtonContextMenu Toggle Cambio stato Turbo Turbo Clear Cancella Set Select Seleziona set Disabled Disattivato Set %1 Set %1 Set %1 1W Set %1 1DIREZ Set %1 2W Set %1 2DIREZ Set %1 WH Set %1 PREMENDO JoyButtonSlot Mouse Mouse Up Su Down Giù Left Sinistra Right Destra LB TastoMouseSX MB TastoMouseCENTRO RB TastoMouseDX B4 Tasto4 B5 Tasto5 Pause Pausa Hold Tieni Cycle Ciclo Distance Distanza Release Rilascia Mouse Mod Modifica mouse Press Time Tempo di pressione Delay Ritardo Load %1 Carica %1 Set Change %1 Cambio di set %1 [Text] %1 [Testo] %1 [Exec] %1 [Esec] %1 [NO KEY] [NO TASTO] JoyControlStick Stick Analogico JoyControlStickButton Up Su Down Giù Left Sinistra Right Destra Button Tasto JoyControlStickContextMenu Mouse (Normal) Mouse (normale) Mouse (Inverted Horizontal) Mouse (orizzontale invertito) Mouse (Inverted Vertical) Mouse (verticale invertito) Mouse (Inverted Horizontal + Vertical) Mouse (orizzontale + verticale invertito) Arrows Frecce Keys: W | A | S | D Tasti: W | A | S | D NumPad TastNum None Niente Standard Standard Eight Way 8 direzioni 4 Way Cardinal 4 direzioni cardinali 4 Way Diagonal 4 direzioni diagonali Mouse Settings Impostazioni mouse JoyControlStickEditDialog Dialog Finestra di dialogo X: X: 0 0 Y: Y: Distance: Distanza: Presets: Preimpostazioni: Mouse (Normal) Mouse (normale) Mouse (Inverted Horizontal) Mouse (orizzontale invertito) Mouse (Inverted Vertical) Mouse (verticale invertito) Mouse (Inverted Horizontal + Vertical) Mouse (orizzontale + verticale invertito) Arrows Frecce Keys: W | A | S | D Tasti: W | A | S | D NumPad TastNum None Niente Stick Mode: Modalità analogico: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Standard: analogico a 8 regioni con due tasti direzionali attivi quando l'analogico è in una regione diagonale. 8 direzioni: analogico a 8 regioni con ogni direzione che ha un tasto dedicato. Solo un tasto alla volta viene premuto. Utile per i giochi come Rogue. 4 direzioni cardinali: analogico a 4 regioni con regioni corrispondenti alla direzione cardinale dell'analogico. Utile per i menu. 4 direzioni diagonali: analogico a 4 regioni con ogni regione corrispondente alla zona diagonale dell'analogico. 4 Way Cardinal 4 direzioni cardinali 4 Way Diagonal 4 direzioni diagonali Dead zone value to use for an analog stick. Valore zona morta da usare per un analogico. Value when an analog stick is considered moved 100%. Valore in cui un analogico viene considerato spostato al 100%. The area (in degrees) that each diagonal region occupies. L'area (in gradi) che ogni regione diagonale occupa. Square Stick: Analogico quadrato: Percentage to modify a square stick coordinates to confine values to a circle Percentuale per modificare le coordinate di un analogico quadrato per confinare i valori ad un cerchio. % % Stick Delay: Ritardo analogico: Time lapsed before a direction change is taken into effect. Tempo trascorso prima che il cambio di una direzione entri in funzione. s s Modifier: Modificatore: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. Modifica tasto che è attivo mentre l'analogico è attivo. Questo tasto è utile per assegnare zone con tasti di modificatore che possono essere usate per assegnare funzionalità cammina/corri ad un analogico. PushButton PremiTasto Na&me: Name: Nome: Specify the name of an analog stick. Specifica il nome di un analogico. Mouse Settings Impostazioni mouse Standard Standard Bearing: Tolleranza: % Safe Zone: % Zona sicura: Eight Way 8 direzioni Dead Zone: Zona morta: Max Zone: Zona massima: Diagonal Range: Raggio diagonale: Set Set Set %1 Set %1 JoyControlStickModifierButton Modifier Modificatore JoyDPad DPad DPad JoyDPadButton Up Su Down Giù Left Sinistra Right Destra Button Tasto JoyTabWidget <New> <Nuovo> Remove Rimuovi Remove configuration from recent list. Rimuovi configurazione dalla lista dei recenti. Load Carica Load configuration file. Carica file di configurazione. Save Salva Save changes to configuration file. Salva cambiamenti sul file di configurazione. Save As Salva come Save changes to a new configuration file. Salva cambiamenti su un nuovo file di configurazione. Sets Set Copy from Set Copia da Set Settings Impostazioni Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Stick/Pad Assign Assegna analogico/pad Controller Mapping Mappatura controller Quick Set Set rapido Names Nomi Toggle button name displaying. Aziona visualizzazione del nome del tasto. Pref Pref Change global profile settings. Cambia opzioni globali profilo. Reset Reset Revert changes to the configuration. Reload configuration file. Ripristina modifiche alla configurazione. Ricarica file di configurazione. Open Config Apri configurazione Config Files (*.amgp *.xml) File di configurazione (*.amgp *.xml) Config File (*.%1.amgp) File di configurazione (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Salvare cambiamenti profilo? Changes to the new profile have not been saved. Would you like to save or discard the current profile? I cambiamenti del nuovo profilo non sono stati salvati. Vuoi salvare o scartare il profilo corrente? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? I cambiamenti del profilo "%1" non sono stati salvati. Vuoi salvare o scartare il profilo corrente? Sticks Analogici DPads DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Nessun tasto è stato assegnato. Per favore usa il Set rapido per assegnare funzioni ai tasti o disattiva il nascondimento dei tasti vuoti. Set %1: %2 Set %1: %2 Set %1 Set %1 Copy Set Assignments Copia assegnazioni set Are you sure you want to copy the assignments and device properties from %1? Sei sicuro di voler copiare le assegnazioni e le proprietà dispositivo da %1? Save Config Salva configurazione Set Set Joystick Joystick Joystick JoystickStatusWindow Properties Proprietà Details Dettagli Name: Nome: %1 %1 Number: Numero: Axes: Assi: Buttons: Tasti: Hats: Hat switch: Battery: Unknown Sconosciuto GUID: GUID: Game Controller: Controller di gioco: Axes Assi Buttons Tasti Hats Hat switch %1 (#%2) Properties %1 (#%2) Proprietà Axis %1 Asse %1 Hat %1 Hat switch %1 No No Yes MainSettingsDialog Edit Settings Modifica impostazioni General Generale Controller Mappings Mappatura controller Language Lingua Auto Profile Auto-profilo Mouse Mouse Advanced Avanzate Pro&file Directory: <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Specifica la cartella predefinita che il programma deve usare nelle finestre di dialogo file mentre si carica un profilo o se ne salva uno nuovo.</p></body></html> Recent Profile Count: Conteggio profili recenti: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Numero di profili che possono essere messi nella lista dei profili recenti. 0 significa che il programma non impone alcun limite sui profili visualizzati.</p></body></html> Gamepad Poll Rate: Velocità di polling del gamepad: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Cambia la velocità di polling che il programma usa per scoprire nuovi eventi dai gamepad. Predefinito: 10 ms. Ridurre la velocità di polling potrebbe causare un consumo di CPU maggiore quindi per favore esamina l'impostazione che userai. Hide main window when the main window close button is clicked instead of quitting the program. Nascondi finestra principale quando il tasto chiusura della finestra principale viene cliccato invece di uscire dal programma. Close To Tray Riduci nell'area di notifica Have Windows start AntiMicroX at system startup. Avvia AntiMicroX automaticamente all'avvio di Windows. Launch At Windows Startup Esegui all'avvio di Windows Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Mostra profili recenti per tutti i controller come una lista singola nell'area di notifica. Di predefinito, usa i sottomenu. Single Profile List in Tray Lista profili singola nell'area di notifica Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Riduci a icona il programma. Di predefinito, il programma si riduce a icona se possibile. Minimize to Taskbar Riduci a icona This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Questa opzione farà nascondere tutti i tasti che non hanno slot assegnati. Bisognerà quindi usare la finestra di dialogo Set rapido per mostrare la finestra di dialogo di modifica per i tasti gamepad. Hide Empty Buttons Nascondi tasti vuoti When the program is launched, open the last known profile that was opened during the previous session. Quando il programma viene eseguito, apri l'ultimo profilo conosciuto usato nella precedente sessione. Auto Load Last Opened Profile Auto-carica l'ultimo profilo aperto Only show the system tray icon when the program first launches. Mostra solo l'icona dell'area di notifica quando il programma si apre la prima volta. Launch in Tray Esegui nell'area di notifica Associate .amgp files with AntiMicroX in Windows Explorer. Associa file .amgp con AntiMicroX in Windows Explorer. Associate Profiles Associa profili Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Ripetizione tasto Active keys will be repeatedly pressed when this option is enabled. I tasti attivi verranno premuti a ripetizione quando questa opzione è attivata. Enable Attiva Specifies how much time should elapse before key repeating begins. Specifica quanto tempo debba passare prima che cominci la ripetizione tasto. Specifies how many times key presses will be performed per seconds. Specifica quante volte al secondo verranno premuti i tasti. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntiMicroX è stato tradotto in molte lingue da collaboratori. Di base, il programma sceglierà una traduzione adatta basandosi sulle impostazioni della lingua del tuo sistema. Tuttavia, puoi far caricare ad AntiMicroX una lingua differente a seconda di quella che scegli nella lista qui sotto.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Niente Error Warning Info Info Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset Reset French Francese Japanese Giapponese Russian Russo Serbian Serbo Simplified Chinese Cinese semplificato Ukrainian Ucraino Class Classe Title Titolo Program Programma Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disabilita l'impostazione di Windows "Aumenta precisione puntatore" mentre AntiMicroX è in esecuzione. Disattivare "Aumenta precisione puntatore" permetterà movimenti del mouse più precisi. Disable Enhance Pointer Precision Disattiva Aumenta precisione puntatore Smoothing Histor&y Size: Dimensioni storia: Weight &Modifier: Modificatore peso: Refresh Rate: Frequenza di aggiornamento: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. La frequenza di aggiornamento è la quantità di tempo che trascorre tra un evento mouse e l'altro. Per favore fai attenzione quando modifichi questa impostazione dato che farà consumare più CPU. Impostare un valore troppo basso può causare instabilità al sistema. Per favore esamina l'impostazione che userai. Spring Fonte Screen: Schermo: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Utilizza lo schermo specificato per la modalità fonte. Su Linux, di predefinito viene usato lo schermo primario. Su Windows, di predefinito vengono usati tutti gli schermi disponibili. Accel Numerator: Numeratore accelerazione: 0 0 Accel Denominator: Denominatore accelerazione: Accel Threshold: Soglia accelerazione: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Se i valori di accelerazione per il mouse virtuale sono stati cambiati da un altro processo, specialmente uscendo da un vecchio gioco, allora potresti voler resettare i valori di accelerazione usati dal mouse virtuale. Reset Acceleration Resetta accelerazione Delay: Ritardo: Profi&le Directory: Cartella profilo: ms ms Rate: Rapporto: times/s volte/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Qui sotto c'è una lista di mappature personalizzate salvate. Puoi utilizzare la seguente tabella per cancellare le mappature o disattivarle temporaneamente. Puoi anche disattivare le mappature incluse con SDL; basta inserire una nuova riga con il joystick GUID giusto e mettere la spunta su disattiva. Le impostazioni non avranno effetto finché non aggiorni tutti i joystick o disconnetti quel joystick in particolare. GUID GUID Mapping String Stringa di mappatura Disable? Disattivare? Delete Cancella Insert Inserisci Default Predefinito Brazilian Portuguese Portoghese brasiliano English Inglese German Tedesco Active Attivo Devices: Dispositivi: All Tutto Device Dispositivi Profile Profili Default? Predefinito? Add Aggiungi Edit Modifica Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Inoltre, gli utenti Windows che vogliono usare un valore basso dovrebbero anche mettere la spunta su "Disattiva Aumenta precisione puntatore" se non hanno già disattivato tale opzione in Windows. Select Default Profile Directory Seleziona la cartella del profilo predefinito Are you sure you want to delete the profile? Sei sicuro di voler cancellare il profilo? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [NO TASTO] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Non è stato trovato alcun joystick. Per favore collega un joystick e scegli l'opzione "Aggiorna i joystick" dal menu principale If events are not seen by a game, please click here to run this application as the Adminstrator. Se gli eventi non vengono registrati dal gioco, clicca qui per eseguire l'applicazione da Amministratore. If events are not seen by a game, please click here to run this application as Administrator. &App App &Options Opzioni &Help Aiuto He&lp &Quit Esci Ctrl+Q Ctrl+Q &Update Joysticks Aggiorna i joystick Ctrl+U Ctrl+U &Hide Nascondi Ctrl+H Ctrl+H &About A proposito Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt A proposito di Qt Properties Proprietà Key Checker Controllo tasti Home Page Homepage GitHub Page Pagina GitHub Game Controller Mapping Mappatura controller di gioco Settings Impostazioni Stick/Pad Assign Assegna analogico/pad Wiki Wiki Could not find a proper controller identifier. Exiting. Impossibile trovare un identificatore controller adatto. Esco. (%1) (%1) Open File Apri file %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore Ripristina Calibration couldn't be opened You must connect at least one controller to open the window Run as Administrator? Eseguire come amministratore? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Sei sicuro di voler eseguire questo programma come Amministratore? Certi giochi vengono eseguiti come Amministratore, il che rende inutilizzabili certi eventi generati da AntiMicroX a meno che anche AntiMicroX venga eseguito come Amministratore. Questo succede per via dei problemi causati dalle opzioni del Controllo account utente (UAC) da Windows Vista in poi. Failed to elevate program Impossibile elevare il programma Failed to restart this program as the Administrator Impossibile riavviare questo programma come Amministratore Could not find controller. Exiting. Impossibile trovare controller. Esco. MouseAxisSettingsDialog Mouse Settings - Impostazioni mouse - Set %1 Set %1 MouseButtonSettingsDialog Mouse Settings - Impostazioni mouse - Set %1 Set %1 MouseControlStickSettingsDialog Mouse Settings Impostazioni mouse Set %1 Set %1 MouseDPadSettingsDialog Mouse Settings Impostazioni mouse Set %1 Set %1 MouseSettingsDialog Mouse Settings Impostazioni mouse Mouse Mode: Modalità mouse: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. La modalità cursore viene usata per muovere il cursore del mouse sullo schermo in relazione alla sua posizione corrente a seconda di quanto muovi un'asse o se viene premuto un tasto. La modalità fonte viene usata per muovere il cursore del mouse dal centro dello schermo a seconda di quanto muovi un'asse. Il cursore del mouse tornerà al centro dello schermo quando l'asse torna nella la zona morta. Cursor Cursore Spring Fonte Acceleration: Accelerazione: Enhanced Precision Aumenta precisione Linear Lineare Quadratic Quadratico Cubic Cubico Quadratic Extreme Quadratico estremo Power Function Funzione di potenza Easing Quadratic Interpolazione quadratica Easing Cubic Interpolazione cubica Mouse Speed Settings Impostazioni velocità mouse Enable to change the horizontal and vertical speed boxes at the same time. Permette di modificare i campi di velocità orizzontale e verticale allo stesso tempo. Change Together Modifica insieme Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: Horizontal Speed: Velocità orizzontale: 1 = 20 pps 1 = 20 pixel/sec Vertical Speed: Velocità verticale: Wheel Hori. Speed: Velocità orizz. rotella: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Imposta la velocità usata per il movimento orizzontale della rotella del mouse a seconda del numero di tacche al secondo simulate. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Imposta la velocità usata per il movimento verticale della rotella del mouse a seconda del numero di tacche al secondo simulate. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Per la funzione di potenza della curva di accelerazione. Specifica il fattore da utilizzare per la sensibilità della curva. Quando il valore supera 1, il movimento del mouse verrà accelerato più velocemente nella parte bassa di un'asse. Easing Duration: Durata interpolazione: s s Extra Acceleration Accelerazione supplementare Multiplier: Moltiplicatore: Highest value to accelerate mouse movement by Il valore più grande per cui accelerare il mouse x x Start %: Inizio %: Start %: Acceleration begins at this percentage of the base multiplier L'accelerazione comincia da questa percentuale del moltiplicatore di base Min Threshold: Soglia minima: Minimum amount of axis travel required for acceleration to begin Valore minimo di spostamento asse richiesto per far sì che cominci l'accelerazione Max Threshold: Soglia massima: Maximum axis travel before acceleration has reached the multiplier value Valore massimo di spostamento asse prima che l'accelerazione raggiunga il valore del moltiplicatore E&xtra Duration: Curve: Curva: Ease Out Sine Sinusoidale graduale Ease Out Quad Quadratico graduale Ease Out Cubic Cubico graduale Release Radius: Raggio di rilascio: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Specifica che l'area della fonte sarà relativa alla posizione del mouse impostata da una fonte non relativa. Relative Relativa Mouse Status Stato mouse X: X: 0 (0 pps) 0 (0 pixel/sec) Y: Y: 1 = 1 notch(es)/s 1 = 1 tacca(tacche)/sec Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Aumentato: curva a tre livelli che fa muovere il mouse lentamente verso la parte bassa di un'asse e velocemente nella parte alta. Lineare: il mouse si muove in modo proporzionale in un'asse. Quadratico: il mouse accelera lentamente nella parte bassa. Cubico: il mouse accelera più lentamente di Quadratico. Quadratico estremo: aumenta la velocità del mouse per 1.5 una volta che lo spostamento di un'asse raggiunge il 95%. Funzione di potenza: permette l'opzione di una curva più personalizzata. Interpolazione quadratica: la parte alta di un'asse viene gradualmente accelerata per un periodo di tempo usando una curva quadratica. Interpolazione cubica: la parte alta di un'asse viene gradualmente accelerata per un periodo di tempo usando una curva cubica. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Velocità orizz. rotella: Sensitivity: Sensibilità: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. Specifica il periodo di tempo (in secondi) che saranno necessari prima che il mouse sia pienamente accelerato dopo aver raggiunto la parte alta di un'asse. Options for adding extra acceleration to the mouse movement beyond what the acceleration curve would produce. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Opzioni per aggiungere più accelerazione al movimento del mouse oltre a quello che la curva di accelerazione produrrebbe. Questo serve a risolvere alcuni problemi legati all'estremamente limitata gamma di input disponibili usando i tipici analogici dei gamepad. % % Extra Duration: Durata aggiuntiva: Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Estende il tempo in cui l'accelerazione aggiuntiva viene applicata. Il percorso dell'asse verrà considerato. Un movimento più lento diminuirà il tempo effettivo in cui verrà applicata l'accelerazione supplementare. Spring Settings Impostazioni fonte Spring Width: Larghezza fonte: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Cambia la larghezza della regione in cui il cursore può muoversi in modalità fonte. 0 utilizzerà l'intera grandezza dello schermo. Spring Height: Altezza fonte: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Cambia l'altezza della regione in cui il cursore può muoversi in modalità fonte. 0 utilizzerà l'intera grandezza dello schermo. %n notch(es)/s %n notch/s %n notches/s ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Annulla OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Controllo tasti <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Premi un tasto sulla tua tastiera per vedere come viene rilevato da questa applicazione. La finestra mostrerà il valore tasto nativo, il valore originale dato da Qt (se applicabile), e il valore personalizzato usato da AntiMicroX.</p><p>Il valore tasto AntiMicroX e il valore tasto Qt solitamente saranno gli stessi. AntiMicroX cerca di i valori tasto definiti in Qt se possibile. Guarda la pagina <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> per una lista di valori definiti da Qt. Se scopri un tasto che non è supportato nativamente da questo programma, per favore segnala il problema alla <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">pagina GitHub</span></a> cosicché il programma possa essere modificato per supportarlo direttamente. In questo momento, un prefisso personalizzato viene aggiunto ai valori sconosciuti in modo che possano essere ancora utilizzati; il problema principale è che il profilo non sarà più portatile.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Gestore di eventi: Native Key Value: Valore tasto nativo: 0x00000000 0x00000000 Qt Key Value: Valore tasto Qt: antimicro Key Value: AntiMicroX Key Value: Valore tasto AntiMicroX: QObject Super Super Menu Menu Mute Muto Vol+ Vol+ Vol- Vol- Play/Pause Play/Pausa Play Play Pause Pausa Prev Prec Next Succ Mail Mail Home Home Media Media Search Cerca Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Demone avviato Failed to launch daemon Impossibile avviare demone Launching daemon Avviando demone Display string "%1" is not valid. La stringa di display "%1" non è valida. Failed to set a signature id for the daemon Impossibile impostare un ID firma per il demone Failed to change working directory to / Impossibile cambiare la cartella di lavoro per / Quitting Program Chiudendo il programma # of joysticks found: %1 № di joystick trovati: %1 List Joysticks: Lista joystick: --------------- --------------- Joystick %1: Joystick %1: Index: %1 Indice: %1 GUID: %1 GUID: %1 UniqueID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Nome: %1 Yes No No Game Controller: %1 Controller di gioco: %1 # of Axes: %1 № di assi: %1 # of Buttons: %1 № di tasti: %1 # of Hats: %1 № di hat switch: %1 Attempting to use fallback option %1 for event generation. Tentativo di utilizzo dell'opzione alternativa %1 per la generazione eventi. Failed to open event generator. Exiting. Impossibile aprire il generatore di eventi. Esco. Using %1 as the event generator. Sto usando %1 come generatore eventi. Could not raise process priority. Impossibile aumentare la priorità del processo. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Il profilo in %1 non è un file XML. Profile location %1 does not exist. Il profilo in %1 non esiste. Controller identifier is not a valid value. L'identificatore controller non è un valore valido. An invalid set number '%1' was specified. È stato specificato un numero di set '%1' invalido. Controller identifier '%s'' is not a valid value. L'identificatore controller '%s'' non è un valore valido. No set number was specified. Non è stato specificato un numero di set. No controller was specified. Non è stato specificato un controller. No display string was specified. Non è stata specificata una stringa di visualizzazione. An invalid event generator was specified. È stato specificato un generatore di eventi invalido. No event generator string was specified. Nessuna stringa di generatore eventi è stata specificata. Qt style flag was detected but no style was specified. È stato rilevato il flag stile Qt ma non è stato specificato alcuno stile. No log file specified. AntiMicroX version versione AntiMicroX Usage: AntiMicroX [options...] [profile] Utilizzo: AntiMicroX [options...] [profile] Options Opzioni Print help text. Stampa testo di aiuto. Print version information. Stampa informazioni versione. Launch program in system tray only. Esegui programma solo nella barra di sistema. Launch program with the tray menu disabled. Esegui programma con la barra di sistema disattivata. Launch program without the main window displayed. Esegui programma senza visualizzare la finestra principale. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Esegui programma con il file di configurazione selezionato come predefinito per i controller selezionati. Diventa il valore predefinito di tutti i controller. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Applica file di configurazione ad un controller specifico. Il valore può essere un indice controller, nome, o GUID. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Libera profilo/i attivati. Il valore può essere un indice controller, nome, o GUID. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Esegui joystick su un set specifico. Il valore può essere un indice controller, nome, o GUID. Advance profile loading set options. Avanza caricamento opzioni set profilo. Launch program as a daemon. Esegui programma come demone. Enable logging. Abilita logging. Use specified display for X11 calls. Useful for ssh. Usa il display specificato per le chiamate X11. Utile per l'SSH. Choose between using XTest support and uinput support for event generation. Default: xtest. Scegli se usare il supporto XTest o uinput per la generazione di eventi. Predefinito: xtest. Choose between using SendInput and vmulti support for event generation. Default: sendinput. Scegli se usare il supporto SentInput o vmulti per la generazione di eventi. Predefinito: sendinput. Print information about joysticks detected by SDL. Stampa informazioni riguardo i joystick rilevati da SDL. Open game controller mapping window of selected controller. Value can be a controller index or GUID. Apri finestra Mappatura controller di gioco del controller scelto. Il valore può essere un indice controller o GUID. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. La versione xinput dev'essere almeno 2.0. Non avverrà alcuna modifica all'accelerazione mouse. QuickSetDialog Quick Set Set rapido <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Per favore premi un tasto o muovi un'asse su %1 (<span style=" font-weight:600;">%2</span>).<br/>Verrà mostrata una finestra di dialogo che<br/>ti permetterà di creare un'assegnazione.</p></body></html> Quick Set %1 Set rapido %1 SetAxisThrottleDialog Throttle Change Modifica acceleratore The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? L'impostazione dell'acceleratore per l'asse %1 è cambiata. Vuoi distribuire questa modifica su tutti i set? SetJoystick Set %1: %2 Set %1: %2 Set %1 Set %1 SetNamesDialog Set Name Settings Impostazioni nome set Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Name Nome SimpleKeyGrabberButton Mouse Mouse SpringModeRegionPreview Spring Mode Preview Anteprima modalità fonte UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Impossibile trovare un valido file di dispositivo uinput. Per favore controlla di aver caricato il modulo uinput. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Impossibile aprire il file di dispositivo uinput. Per favore controlla di avere i permessi di scrittura sul dispositivo. Using uinput device file %1 File di dispositivo uinput %1 in uso UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z Esc Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock BlocMaiusc ; ; ' ' Enter Invio Shift_L Maiusc_SX , , . . / / Ctrl_L Ctrl_SX Super_L Super_SX Alt_L Alt_SX Space Spazio Alt_R Alt_DX Menu Menu Ctrl_R Ctrl_DX Shift_R Maiusc_DX Up Su Left Sinistra Down Giù Right Destra PrtSc Stamp Ins Ins Del Canc Home Home End Fine PgUp PgSu PgDn PgGiù NumLock BlocNum * * + + KP_Enter TN_Invio KP_1 TN_1 KP_2 TN_2 KP_3 TN_3 KP_4 TN_4 KP_5 TN_5 KP_6 TN_6 KP_7 TN_7 KP_8 TN_8 KP_9 TN_9 KP_0 TN_0 SCLK BlocScorr Pause Pausa Super_R Super_DX Mute Muto VolDn VolGiù VolUp VolSu Play Play Stop Stop Prev Prec Next Succ [NO KEY] [NO TASTO] UnixWindowInfoDialog Captured Window Properties Finestra proprietà catturate Information About Window Informazioni sulla finestra Class: Classe: TextLabel etichetta di testo Title: Titolo: Path: Percorso: Match By Properties Trova per proprietà Class Classe Title Titolo Path Percorso VDPad VDPad VDPad VirtualKeyPushButton Space Spazio Tab Tab Shift (L) Maiusc (SX) Shift (R) Maiusc (DX) Ctrl (L) Ctrl (SX) Ctrl (R) Ctrl (DX) Alt (L) Alt (SX) Alt (R) Alt (DX) Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC STAMP SCLK BLOCSCORR INS INS PGUP PGSU DEL CANC PGDN PGGIU 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK BLOC NUM * * + + Enter Invio Del Canc E N T E R I N V I O < < : : Super (L) Super (SX) Menu Menu Up Su Down Giù Left Sinistra Right Destra VirtualKeyboardMouseWidget Keyboard Tastiera Mouse Mouse Mouse Settings Impostazioni mouse Left Mouse Sinistra Up Mouse Su Left Button Mouse Tasto sinistro Middle Button Mouse Tasto centrale Right Button Mouse Tasto destro Wheel Up Mouse Rotella su Wheel Left Mouse Rotella sinistra Wheel Right Mouse Rotella destra Wheel Down Mouse Rotella giù Down Mouse Giù Right Mouse Destra Button 4 Mouse Tasto 4 Mouse 8 Mouse Mouse 8 Button 5 Mouse Tasto 5 Mouse 9 Mouse Mouse 9 NONE NIENTE [NO KEY] [NO TASTO] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Applications Applicazioni Browser Back Browser indietro Browser Favorites Browser preferiti Browser Forward Browser avanti Browser Home Browser home Browser Refresh Browser aggiorna Browser Search Browser cerca Browser Stop Browser stop Calc Calc Email Email F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media Media Media Next Media successivo Media Play Media play Media Previous Media precedente Media Stop Media stop Search Cerca Volume Down Volume giù Volume Mute Volume muto Volume Up Volume su VirtualMousePushButton INVALID INVALIDO WinAppProfileTimerDialog Capture Application Cattura applicazione After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Dopo aver premuto il tasto "Cattura applicazione", per favore seleziona la finestra dell'applicazione con cui vuoi associare un profilo. L'applicazione attiva verrà catturata dopo il numero di secondi scelto. Timer: Timer: Seconds Secondi Cancel Annulla WinExtras [NO KEY] [NO TASTO] AntiMicroX Profile Profilo AntiMicroX X11Extras ESC ESC Tab Tab Space Spazio DEL CANC Return Invio KP_Enter TN_Invio Backspace Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. Estensione xinput non trovata. Non avverrà alcuna modifica all'accelerazione mouse. xinput version must be at least 2.0. No mouse acceleration changes will occur. La versione xinput dev'essere almeno 2.0. Non avverrà alcuna modifica all'accelerazione mouse. Virtual pointer found with id=%1. Trovato puntatore virtuale con id=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 PtrFeedbackClass non è stato trovato per il puntatore virtuale. Non avverrà alcuna modifica all'accelerazione del mouse con id=%1 Changing mouse acceleration for device with id=%1 Modificando l'accelerazione mouse per il dispositivo con id=%1 XMLConfigReader Could not write updated profile XML to file %1. Impossibile scrivere profilo XML aggiornato sul file %1. XMLConfigWriter Could not write to profile at %1. Impossibile scrivere su profilo a %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Esegui programma solo nella barra di sistema. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_ja.ts000066400000000000000000012637131377703515000274770ustar00rootroot00000000000000 AboutDialog About Version バージョン <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Info 情報 Changelog Credits AntiMicroX AntiMicroX About Development License ライセンス Program Version %1 Program Compiled on %1 at %2 Built Against SDL %1 Running With SDL %1 Using Qt %1 Using Event Handler: %1 AddEditAutoProfileDialog Auto Profile Dialog Profile: プロファイル: Pro&file: Browse Window: ウィンドウ: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties &Class: T&itle: Title: タイトル: set partial title Application: アプリケーション: Select De&vices: Devices: デバイス: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller A different profile is already selected as the default for this device. Current (%1) Open Config Select Program Please use the main default profile selection. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Capture Application Window Could not obtain information for the selected window. Application Capture Failed Profile file path is invalid. No window matching property was specified. Program path is invalid or not executable. No window matching property was selected. AdvanceButtonDialog Advanced 詳細設定 Assignments 割り当て Toggle トグル Turbo 連射 Set Selector Blank or KB/M Hold Pause Pause Cycle Distance Insert Delete 削除 Clear All Time: 0.01s 0.01 秒 0s 0 秒 Insert a pause that occurs in between key presses. Release Insert a new blank slot. Delete a slot. Clear all currently assigned slots. Specify the duration of an inserted Pause or Hold slot. 0m 0 分 &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Distance: % % Mouse Mod Press Time Delay Execute Load 読み込み Set Change Text Entry Join Split Placeholder 0 0 Set the percentage that mouse speeds will be modified by. Auto Reset Cycle After seconds Executable: ... Arguments: Enabled 有効 Mode: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Gradient Pulse Delay: 0.10s 0.10 秒 Rate: 10.0/s Disabled Select Set 1 One Way Select Set 1 Two Way Select Set 1 While Held Select Set 2 One Way Select Set 2 Two Way Select Set 2 While Held Select Set 3 One Way Select Set 3 Two Way Select Set 3 While Held Select Set 4 One Way Select Set 4 Two Way Select Set 4 While Held Select Set 5 One Way Select Set 5 Two Way Select Set 5 While Held Select Set 6 One Way Select Set 6 Two Way Select Set 6 While Held Select Set 7 One Way Select Set 7 Two Way Select Set 7 While Held Select Set 8 One Way Select Set 8 Two Way Select Set 8 While Held [NO KEY] [割り当てなし] sec. /sec. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 セット %1 Select Set %1 One Way Two Way While Held Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Choose Profile Config Files (*.amgp *.xml) 構成ファイル (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Sticks スティック DPads 十字キー Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (ジョイスティック %2) Stick 1 スティック 1 Enabled 有効 Assign 割り当て X Axis: X 軸: Y Axis: Y 軸: Stick 2 スティック 2 Number of Physical DPads: %1 物理方向キーの数: %1 Virtual DPad 1 仮想方向キー 1 Up: 上: Down: 下: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. 注: このウィンドウは、バージョン 2.0 より前の AntiMicroX で作成したプロファイルとの後方互換性を確保するために使用します。バージョン 2.0 以降では「ゲームコントローラーマッピング」ウィンドウの使用を推奨します。 Left: 左: Right: 右: Axis %1 軸 %1 Axis %1 - 軸 %1 - Axis %1 + 軸 %1 + Button %1 ボタン %1 Move stick 1 along the X axis Move stick 1 along the Y axis Move stick 2 along the X axis Move stick 2 along the Y axis Press a button or move an axis AxisEditDialog Axis Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Left | Right Keys: W | S Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 None Set the value to use as the limit for an axis. Useful for a worn out analog stick. Negative Half Throttle Positive Half Throttle Name: 名前: Specify the name of an axis. Mouse Settings マウスの設定 Set the value of the dead zone for an axis. Presets: プリセット: Dead Zone: Max Zone: [NO KEY] [割り当てなし] Throttle setting that determines the behavior of how to interpret an axis hold or release. Negative Throttle Normal Positive Throttle Current Value: Set セット Set %1 セット %1 Left Mouse Button 左マウスボタン Right Mouse Button 右マウスボタン ButtonEditDialog Dialog To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab 割り当てを新規作成するには、キーボードのキーを押すか、「キーボード」あるいは「マウス」タブのいずれかのボタンをクリックしてください Placeholder Toggle トグル Enables a key press or release to only occur when a controller button is pressed. Enables rapid key presses and releases. Turbo controller. Turbo 連射 Current: 現在の割り当て: Last keyboard/mouse button: Slots Na&me: 名前(&M): Specify the name of a button. Action: アクション: Specify the action that will be performed in game while this button is being used. Advanced 詳細設定 Set セット Set %1 セット %1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [割り当てなし] Calibration Form Start calibration Sticks: Reset settings Cancel キャンセル Save 保存 Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 軸 %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: タイトル: Path: Match By Properties Class Title タイトル Path Full Path File Name CommandLineUtility Options オプション DPadContextMenu Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Standard Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings マウスの設定 DPadEditDialog Dialog Presets: プリセット: Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Dpad Mode: &Name: 4 Way Cardinal 4 Way Diagonal DPad Delay: Time lapsed before a direction change is taken into effect. s Specify the name of a dpad. Mouse Settings マウスの設定 Standard Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way Set セット Set %1 セット %1 EditAllDefaultAutoProfileDialog Default Profile Profile: プロファイル: Browse Open Config Profile file path is invalid. ExtraProfileSettingsDialog Extra Profile Settings Key Press Time: 0.00 ms Profile Name: プロファイル名: s s GameController Game Controller ゲームコントローラー GameControllerDPad DPad 十字キー GameControllerMappingDialog Game Controller Mapping <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A A B B X X Y Y Back Start Guide Left Shoulder Right Shoulder Left Stick Click Right Stick Click Left Stick X 左スティック X Left Stick Y 左スティック Y Right Stick X 右スティック X Right Stick Y 右スティック Y Left Trigger 左トリガー Right Trigger 右トリガー DPad Up 十字キー↑ DPad Left 十字キー← DPad Down 十字キー↓ DPad Right 十字キー→ Mapping SDL 2 Game Controller Mapping String Last Axis Event: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Discard Controller Mapping? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. GameControllerSet Back Guide Start LS Click RS Click L Shoulder R Shoulder L Trigger 左トリガー R Trigger 右トリガー GameControllerTrigger Trigger トリガー JoyAxis Axis JoyAxisButton Negative Positive Unknown 不明 Button ボタン JoyAxisContextMenu Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Left | Right Keys: W | S Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 None Mouse Settings マウスの設定 Left Mouse Button 左マウスボタン Right Mouse Button 右マウスボタン JoyButton Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Button ボタン [NO KEY] [割り当てなし] [Set %1 1W] [Set %1 2W] [Set %1 WH] JoyButtonContextMenu Toggle トグル Turbo 連射 Clear Set Select Disabled Set %1 セット %1 Set %1 1W セット %1 1W Set %1 2W セット %1 2W Set %1 WH JoyButtonSlot Mouse マウス Up Down Left Right LB MB RB Pause Pause Hold Cycle Distance Release Mouse Mod Press Time Delay Load %1 Set Change %1 [Text] %1 [Exec] %1 [NO KEY] [割り当てなし] JoyControlStick Stick スティック JoyControlStickButton Up Down Left Right Button ボタン JoyControlStickContextMenu Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Standard Eight Way 4 Way Cardinal 4 Way Diagonal Mouse Settings マウスの設定 JoyControlStickEditDialog Dialog X: X: 0 0 Y: Y: Distance: Presets: プリセット: Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Stick Mode: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4 Way Diagonal Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. Square Stick: Percentage to modify a square stick coordinates to confine values to a circle % % Stick Delay: Time lapsed before a direction change is taken into effect. s Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Na&me: Name: 名前: Specify the name of an analog stick. Mouse Settings マウスの設定 Standard Bearing: % Safe Zone: Eight Way Dead Zone: Max Zone: Diagonal Range: Set セット Set %1 セット %1 JoyControlStickModifierButton Modifier JoyDPad DPad 十字キー JoyDPadButton Up Down Left Right Button ボタン JoyTabWidget <New> <新規> Remove 削除 Remove configuration from recent list. Load 読み込み Load configuration file. Save 保存 Save changes to configuration file. Save As 別名保存 Save changes to a new configuration file. Sets セット Copy from Set セットからコピー Settings 設定 Set 1 セット 1 Set 2 セット 2 Set 3 セット 3 Set 4 セット 4 Set 5 セット 5 Set 6 セット 6 Set 7 セット 7 Set 8 セット 8 Stick/Pad Assign Controller Mapping Quick Set クイックセット Names Toggle button name displaying. Pref Change global profile settings. Reset リセット Revert changes to the configuration. Reload configuration file. Open Config Config Files (*.amgp *.xml) 構成ファイル (*.amgp *.xml) Config File (*.%1.amgp) 構成ファイル (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks スティック DPads 十字キー No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 セット %1: %2 Set %1 セット %1 Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Save Config Set セット Joystick Joystick ジョイスティック JoystickStatusWindow Properties プロパティ Details Name: 名前: %1 %1 Number: Axes: 軸: Buttons: ボタン: Hats: Battery: Unknown 不明 GUID: GUID: Game Controller: ゲームコントローラー: Axes Buttons ボタン Hats %1 (#%2) Properties Axis %1 軸 %1 Hat %1 No いいえ Yes はい MainSettingsDialog Edit Settings General 全般 Controller Mappings Language 言語 Auto Profile Mouse マウス Advanced 詳細設定 <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> Recent Profile Count: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Close To Tray Have Windows start AntiMicroX at system startup. Launch At Windows Startup Windows の起動と同時に開始 Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Single Profile List in Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimize to Taskbar タスクバーに入れる This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Hide Empty Buttons When the program is launched, open the last known profile that was opened during the previous session. Auto Load Last Opened Profile Only show the system tray icon when the program first launches. Launch in Tray Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles プロファイルを関連付け Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Active keys will be repeatedly pressed when this option is enabled. Enable 有効 Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Error Warning Info 情報 Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset リセット French フランス語 Russian ロシア語 Serbian セルビア語 Simplified Chinese 中国語 (簡体字) Ukrainian ウクライナ語 Class Title タイトル Program Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision Smoothing Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Screen: スクリーン: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: 0 0 Accel Denominator: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Delay: Pro&file Directory: ms Rate: times/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. GUID GUID Mapping String Disable? Delete 削除 Insert Default デフォルト Brazilian Portuguese ポルトガル語 (ブラジル) English 英語 German ドイツ語 Active Devices: デバイス: All Device デバイス Profile プロファイル Default? Add 追加 Edit 編集 Select Default Profile Directory Are you sure you want to delete the profile? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [割り当てなし] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu ジョイスティックが見つかりません。 ジョイスティックを接続し、メインメニューの「ジョイスティックを更新」を選択してください If events are not seen by a game, please click here to run this application as Administrator. &App &Options オプション(&O) &Help ヘルプ(&H) He&lp &Quit 終了(&Q) Ctrl+Q Ctrl+Q &Update Joysticks ジョイスティックを更新(&U) Ctrl+U Ctrl+U &Hide 隠す(&H) Ctrl+H Ctrl+H &About AntiMicroX について(&A) Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt Qt について Properties プロパティ Key Checker キーチェッカー Home Page ホームページ GitHub Page GitHub ページ Settings 設定 Could not find a proper controller identifier. Exiting. (%1) (%1) Open File %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore Calibration couldn't be opened You must connect at least one controller to open the window Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Set %1 セット %1 MouseButtonSettingsDialog Mouse Settings - Set %1 セット %1 MouseControlStickSettingsDialog Mouse Settings マウスの設定 Set %1 セット %1 MouseDPadSettingsDialog Mouse Settings マウスの設定 Set %1 セット %1 MouseSettingsDialog Mouse Settings マウスの設定 Mouse Mode: マウスモード: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor カーソル Spring Acceleration: 加速: Enhanced Precision Linear Quadratic Cubic Quadratic Extreme Power Function Easing Quadratic Easing Cubic Mouse Speed Settings Enable to change the horizontal and vertical speed boxes at the same time. Change Together Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: Horizontal Speed: 水平速度: 1 = 20 pps Vertical Speed: 垂直速度: Wheel Hori. Speed: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: s Highest value to accelerate mouse movement by x x Start %: Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Max Threshold: Maximum axis travel before acceleration has reached the multiplier value E&xtra Duration: Curve: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Mouse Status X: X: 0 (0 pps) Y: Y: 1 = 1 notch(es)/s 1 = 1 ノッチ/秒 Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Sensitivity: 感度: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Spring Width: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. %n notch(es)/s %n ノッチ/秒 ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel キャンセル OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker キーチェッカー <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: イベントハンドラ: Native Key Value: ネイティブキー値: 0x00000000 0x00000000 Qt Key Value: Qt キー値: antimicro Key Value: AntiMicroX Key Value: AntiMicroX キー値: QObject Pause Pause Home Home Media メディア Search 検索 Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Failed to launch daemon Launching daemon Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to change working directory to / Quitting Program # of joysticks found: %1 List Joysticks: --------------- Joystick %1: ジョイスティック %1: Index: %1 GUID: %1 GUID: %1 UniqueID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 名前: %1 Yes はい No いいえ Game Controller: %1 ゲームコントローラー: %1 # of Axes: %1 # of Buttons: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Profile location %1 does not exist. Controller identifier is not a valid value. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. No controller was specified. No display string was specified. An invalid event generator was specified. No event generator string was specified. No log file specified. Options オプション Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set クイックセット <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> Quick Set %1 クイックセット %1 SetAxisThrottleDialog Throttle Change The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? SetJoystick Set %1: %2 セット %1: %2 Set %1 セット %1 SetNamesDialog Set Name Settings Set 1 セット 1 Set 2 セット 2 Set 3 セット 3 Set 4 セット 4 Set 5 セット 5 Set 6 セット 6 Set 7 セット 7 Set 8 セット 8 Name SimpleKeyGrabberButton Mouse マウス SpringModeRegionPreview Spring Mode Preview UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Using uinput device file %1 UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z Esc Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock CapsLock ; ; ' ' Enter Enter Shift_L , , . . / / Ctrl_L Super_L Alt_L Space スペース Alt_R Menu Ctrl_R Shift_R Up Left Down Right PrtSc PrtSc Ins Del Del Home Home End End PgUp PgUp PgDn PgDn NumLock NumLock * * + + KP_Enter KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9 KP_0 SCLK Pause Pause Super_R Mute VolDn VolUp Play Stop Prev Next [NO KEY] [割り当てなし] UnixWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: タイトル: Path: Match By Properties Class Title タイトル Path VDPad VDPad VirtualKeyPushButton Space スペース Tab Tab Shift (L) Shift (左) Shift (R) Shift (右) Ctrl (L) Ctrl (左) Ctrl (R) Ctrl (右) Alt (L) Alt (左) Alt (R) Alt (右) Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC PRTSC SCLK INS PGUP DEL PGDN 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK * * + + Enter Enter Del Del < < : : Super (L) Menu Up Down Left Right VirtualKeyboardMouseWidget Keyboard キーボード Mouse マウス Mouse Settings マウスの設定 Left Mouse Up Mouse Left Button Mouse 左ボタン Middle Button Mouse 中ボタン Right Button Mouse 右ボタン Wheel Up Mouse Wheel Left Mouse Wheel Right Mouse Wheel Down Mouse Down Mouse Right Mouse Button 4 Mouse ボタン 4 Mouse 8 Mouse マウス 8 Button 5 Mouse ボタン 5 Mouse 9 Mouse マウス 9 NONE 割り当てなし [NO KEY] [割り当てなし] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Applications アプリケーション Browser Back ブラウザ: 戻る Browser Favorites ブラウザ: お気に入り Browser Forward ブラウザ: 進む Browser Home ブラウザ: ホーム Browser Refresh ブラウザ: 更新 Browser Search ブラウザ: 検索 Browser Stop Calc Email Eメール F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media メディア Media Next メディア: 次へ Media Play メディア: 再生 Media Previous メディア: 前へ Media Stop メディア: 停止 Search 検索 Volume Down 音量: 下げる Volume Mute 音量: ミュート Volume Up 音量: 上げる VirtualMousePushButton INVALID WinAppProfileTimerDialog Timer: タイマー: Seconds Cancel キャンセル WinExtras [NO KEY] [割り当てなし] AntiMicroX Profile AntiMicroX プロファイル X11Extras ESC Tab Tab Space スペース DEL Return KP_Enter Backspace Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Changing mouse acceleration for device with id=%1 XMLConfigReader Could not write updated profile XML to file %1. XMLConfigWriter Could not write to profile at %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_pl.ts000066400000000000000000020470761377703515000275230ustar00rootroot00000000000000 AboutDialog About O programie AntiMicroX AntiMicroX Version Wersja Credits Przypisy <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Stworzony przez Travis Nickles &lt;nickles.travis@gmail.com&gt;, następnie kontynuowany przez grupę AntiMicro na stronie https://github.com/AntiMicro, a teraz w formie forku przez juliagoda na stronie https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Aktualni programiści:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Poprzedni programiści:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Tłumaczenia:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - brazylijski portugalski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - chiński</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - francuski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - niemiecki</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - niemiecki</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - japoński</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - rosyjski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - serbski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - ukraiński</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - hiszpański</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - włoski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - polski</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Prawa autorskie: 2013 - 2020 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicroX group at https://github.com/AntiMicroX, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicroX group at https://github.com/AntiMicroX, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Początkowo rozwijane przez twórcę Travis Nickles'a &lt;nickles.travis@gmail.com&gt;, następnie prowadzone przez grupę AntiMicroX na stronie https://github.com/AntiMicroX, natomiast aktualnie jest rozwijane przez użytkownika juliagoda na stronie https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Deweloperzy:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Poprzedni deweloperzy:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Tłumacze:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - język portugalski (Brazylia)</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - język chiński</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - język francuski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - język niemiecki</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - język niemiecki</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - język japoński</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - język rosyjski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - język serbski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - język ukraiński</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - język hiszpański</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - język włoski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - język włoski</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - język polski</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> Info Info License Licencja <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> Changelog Dziennik zmian About Development O rozwoju "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicroX in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. "juliagoda" (od marca, 2018) Chcąc początkowo jedynie zagrać w ulubione stare gry, które nie posiadają wbudowanego wsparcia dla gamepad'ów, znalazłam ten projekt (który mapuje znaki z klawiszy klawiatury i przyciski myszy do podłączonych urządzeń pod systemem Linux) jako najaktualniejszego ze wszystkich dostępnych w sieci. Z powodu niedużego wyboru takiego rodzaju aplikacji w internecie, postanowiłam spróbować naprawić projekt. Po zakończeniu prac (na poziomie wystarczającym do zastosowania w grach) zdecydowałam się na opublikowanie kodu. Wszystkie informacje na temat poprzednich programistów zostaną zachowane. "Ryochan7" (od 30 grudnia, od 2012 do 2017), Pracowałem nad AntiMicro w swoim wolnym czasie. Pierwotnie pierwsze wersje programu były forkiem aplikacji QJoyPad, a okazja do nauki programowania kierowanego zdarzeniami przerodziła się w coś o wiele większego, niż początkowo planowałem. Pomimo tego, że spędziłem nad nauką nowych technik programowania sporo czasu, dowiedzenie się czegoś więcej o dziedzinie emulacji KB+M i spędzenie wyczerpujących piątkowych wieczorów przyniosły sporo frajdy i wzbogaciły moją wiedzę. Powodem powstania tego programu była chęć używania takich programów pod systemem Linux, które dostępne są szeroko na systemie Windows, by móc grać w gry niewspierające kontrolerów gier natywnie. Chociaż istniało kilka alternatyw, nie zawierały one wystarczającej funkcjonalności, która zapewniałaby choćby odpowiednią emulację KB+M. QJoyPad był głównym programem, którego używałem w przeszłości. Jednak z biegiem lat wraz z zaprzestaniem jego rozwoju, zabrakło potrzebnych funkcji, a które uważałem za niezbędne. Jako, że z czasem program przestał być rozwijany, postanowiłem więc stworzyć własny. Od tamtej pory próbowałem zrozumieć, w jaki sposób działały inne programy, a następnie poprawiałem ich funkcjonalność u siebie. Odkryłem także ciekawe metody w miarę realizacji projektu oraz nauczyłem się tego, w jaki sposób natywne kontrolery są implementowane w niektórych grach. Bardzo chciałem się tego nauczyć. Chociaż istnieją pewne miejsca w kodzie, gdzie program można by było poprawić, uważam, że aktualnie ten program oferuje najlepsze przeżycie doświadczeń podczas grania w gry starsze jak i te nowsze. Rozwój tego programu nie jest już dla mnie największym priorytetem. Jest to głównie spowodowane tym, że Kontroler Steam działa bardzo dobrze w sposób porównywalny do jakości działania kontrolera Xbox 360. Jednakże wygląda wciąż na to, że nadal istnieje powód dla istnienia tej aplikacji. --- Z dniem 24 maja, 2016, projekt został przeniesiony na stronę https://github.com/AntiMicro/antimicro. Poza tym, rozwój programu został przekazany grupie AntiMicro. Powodem przekazania projektu było zaprzestanie prac przez swojego twórcę. Copyright: 2013 - 2018 Prawa autorskie: 2013 - 2018 Program Version %1 Wersja programu %1 Program Compiled on %1 at %2 Program skompilowany na %1 z pomocą %2 Built Against SDL %1 Zbudowane z biblioteką SDL %1 Running With SDL %1 Uruchomione z biblioteką SDL %1 Using Qt %1 Z użyciem Qt %1 Using Event Handler: %1 Z użyciem procedury obsługi zdarzenia: %1 AddEditAutoProfileDialog Auto Profile Dialog Okno Autoprofilu Profile: Profil: Pro&file: Pro&fil: Browse Przeglądaj Window: Okno: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Zaznacz okno. Kliknij na odpowiednie okno aplikacji, a ścieżka aplikacji zostanie automatycznie dodana do rubryki. Detect Window Properties Wykryj właściwości okna &Class: &Klasa: T&itle: T&ytuł: Class: Klasa: Title: Tytuł: set partial title ustaw częściowy tytuł Application: Aplikacja: Select Zaznacz De&vices: Urz&ądzenia: Devices: Urządzenia: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Zaznacz ten profil, by go domyślnie załadować dla określonego urządzenia. Wybór zostanie użyty zamiast domyślnej opcji. Set as Default for Controller Ustaw jako domyślny dla kontrolera A different profile is already selected as the default for this device. Inny profil jest aktualnie zaznaczony jako domyślny dla tego urządzenia. Current (%1) Aktualny (%1) Open Config Otwórz konfigurację Select Program Zaznacz program Programs (*.exe) Programy (*.exe) Please use the main default profile selection. Zaleca się użycie wyboru głównego domyślnego profilu. Main Profile Główny profil Already selected Już zaznaczono Chosen Profile Wybrany profil The selection will be used instead of the all default profile option. Wybór zostanie użyty zamiast wszystkie opcje profilu domyślnego. Please select a window by using the mouse. Press Escape if you want to cancel. Zaznacz okno za pomocą myszki. Wciśnij Escape, jeśli chcesz anulować. Capture Application Window Przechwyć okno aplikacji Could not obtain information for the selected window. Nie można uzyskać informacji dla zaznaczonego okna. Application Capture Failed Przechwytywanie okna zostało zakończone niepowodzeniem Profile file path is invalid. Ścieżka profilu jest nieprawidłowa. No window matching property was specified. Nie została określona żadna pasująca właściwość dla okna. Program path is invalid or not executable. Ścieżka programu jest nieprawidłowa lub nie jest wykonywalna. File is not an .exe file. Plik nie jest plikiem .exe. No window matching property was selected. Nie została zaznaczona żadna pasująca właściwość dla okna. AdvanceButtonDialog Advanced Zaawansowane Assignments Przypisania Toggle Przycisk przełączania Turbo Przycisk turbo Set Selector Wybiesz selektor Blank or KB/M Pusty lub KB/M Cycle Cykl Delay Opóźnienie Distance Odległość Execute Wywołanie Hold Przytrzymanie Load Załadowanie Mouse Mod Moduł myszki Pause Przerwa Press Time Przytrzymanie okresowo Release Zwolnienie Set Change Zmiana ustawienia Text Entry Wprowadzenie tekstu Insert a new blank slot. Dodaj nowy pusty slot. Insert Dodaj Join Połącz Split Podziel Delete a slot. Usuń slot. Delete Usuń Clear all currently assigned slots. Wyczyść wszystkie aktualnie przypisane sloty. Clear All Wyczyść wszystko Placeholder Zastępstwo Specify the duration of an inserted Pause or Hold slot. Określ czas trwania wprowadzonego slotu "Przerwa" lub "Przytrzymanie". Time: Czas: 0.01s 0.01s 0m 0m 0 0 0s 0s &Mouse Speed Mod: &Moduł prędkości myszki: Set the percentage that mouse speeds will be modified by. Ustaw wartość w procentach, o którą prędkość myszki zostanie zmieniona. % % Specify the range past an axis dead zone in which a sequence of actions will execute. Określ przedział martwej strefy dla osi, w którym zostanie wywołana kolejność akcji. Distance: Odległość: Auto Reset Cycle After Automatycznie resetuj cykl po seconds sekundach Choose Profile Wybierz profil Executable: Wykonywalny: ... ... Arguments: Argumenty: Enabled Odblokowane Mode: Tryb: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Standardowo: Cyklicznie jest wciskany i zwalniany przycisk według wybranej prędkości.</p><p>Gradientowo: Zmienia opóźnienie wciśnięcia przycisku i jego zwolnienie według odległości pokonanej przez oś. Częstotliwość pozostaje niezmieniona.</p><p>Pulsowo: Zmienia częstotliwość naciskania i zwalniania przycisku na sekundę. Opoźnienie przycisku pozostaje niezmienione.</p></body></html> Normal Standardowo Gradient Gradientowo Pulse Pulsowo Delay: Opoźnienie: 0.10s 0.10s Rate: Tempo: 10.0/s 10.0/s Disabled Zablokowany Select Set 1 One Way Zaznacz zestawienie 1 jednokierunkowe Select Set 1 Two Way Zaznacz zestawienie 1 dwukierunkowe Select Set 1 While Held Zaznacz zestawienie 1 podczas trzymania Select Set 2 One Way Zaznacz zestawienie 2 jednokierunkowe Select Set 2 Two Way Zaznacz zestawienie 2 dwukierunkowe Select Set 2 While Held Zaznacz zestawienie 2 podczas trzymania Select Set 3 One Way Zaznacz zestawienie 3 jednokierunkowe Select Set 3 Two Way Zaznacz zestawienie 3 dwukierunkowe Select Set 3 While Held Zaznacz zestawienie 3 podczas trzymania Select Set 4 One Way Zaznacz zestawienie 4 jednokierunkowe Select Set 4 Two Way Zaznacz zestawienie 4 dwukierunkowe Select Set 4 While Held Zaznacz zestawienie 4 podczas trzymania Select Set 5 One Way Zaznacz zestawienie 5 jednokierunkowe Select Set 5 Two Way Zaznacz zestawienie 5 dwukierunkowe Select Set 5 While Held Zaznacz zestawienie 5 podczas trzymania Select Set 6 One Way Zaznacz zestawienie 6 jednokierunkowe Select Set 6 Two Way Zaznacz zestawienie 6 dwukierunkowe Select Set 6 While Held Zaznacz zestawienie 6 podczas trzymania Select Set 7 One Way Zaznacz zestawienie 6 jednokierunkowe Select Set 7 Two Way Zaznacz zestawienie 7 dwukierunkowe Select Set 7 While Held Zaznacz zestawienie 7 podczas trzymania Select Set 8 One Way Zaznacz zestawienie 8 jednokierunkowe Select Set 8 Two Way Zaznacz zestawienie 8 dwukierunkowe Select Set 8 While Held Zaznacz zestawienie 8 podczas trzymania [NO KEY] [BRAK] sec. sek. /sec. /sek. Not checked slots Niesprawdzone sloty To delete slots, you need to select at least one Aby usunąć sloty, należy wybrać co najmniej jeden z nich To insert slots, you need to select at least one Aby wstawić sloty, należy wybrać co najmniej jeden z nich Unknown current slot Nieznany aktualny slot Click on chosen slots before joining them Kliknij na wybrane sloty przed ich połączeniem Not enough slots Za mało slotów It's impossible to join slots. Add at least one other slot. Niemożliwe jest dołączenie do slotów. Dodaj co najmniej jeden inny slot. Not selected slots Niewybrane sloty It's impossible to join slots. Select at least two slots before joining them Niemożliwe jest dołączenie do slotów. Wybierz co najmniej dwa sloty przed ich połączeniem Only keyboard slots Tylko sloty klawiatury It's only possible to join simple and mix keyboard slots Możliwe jest tylko łączenie prostych slotów oraz slotów mieszanych (minislotów) It's impossible to split slots. Add at least one other slot. Nie da się rozdzielić slotów. Dodaj co najmniej jeden inny slot. Not selected slot Niewybrany slot Select your slot before splitting. Wybierz swój slot przed próbą podzielenia. Too many mix slots Zbyt wiele łączonych slotów Select one mix slot. Wybierz jeden łączony slot. Only mix slots Tylko łączone sloty It's only possible to split mix slot. Możliwe jest tylko dzielenie łączonych slotów (minislotów). Empty execution path Pusta ścieżka wykonania Line for execution file path is empty. Fill the first line before you are going to add a slot. Linia odpowiadająca za scieżkę do pliku wykonywalnego jest pusta. Uzupełnij rubrykę zanim dodasz slot. File doesn't exist Plik nie istnieje There is no such file locally, that could be executed. Check the file on your system Takiego pliku nie odnaleziono w podanej ścieżce. Sprawdź, czy pod tą ścieżką znajduje się taki plik Set %1 Zestawienie %1 Select Set %1 Wybierz zestawienie %1 One Way Jednokierunkowo Two Way Dwukierunkowo While Held Podczas trzymania Config Files (*.amgp *.xml) Pliki konfiguracyjne (*.amgp *.xml) Choose Executable Wybierz plik wykonywalny Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Sloty za cyklem zostaną wywołane przy kolejnym naciśnięciu przycisku. Wielokrotne cykle mogą być dodane w kolejności, by tworzyć podziały w sekwencji. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Opóźnia czas trwania wywołania następnego slotu według określonego czasu. Sloty aktywowane przed wystąpieniem opóźnienia pozostaną aktywne po przeminięciu określonego czasu dla opóźnienia. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Akcja odległości określa wywoływanie slotów, gdy oś jest przesuwana w określonym przedziale za wyznaczoną martwą strefą. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Wprowadź akcję przytrzymania. Sloty po tej akcji zostaną wywołane, jeśli przycisk ten został trzymany przez określoną umowną ilość czasu. Chose a profile to load when this slot is activated. Wybierz profil do załadowywania gdy slot jest aktywny. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Akcja modułu myszki zmieni wszystkie ustawienia prędkości myszki według określonej liczby procentowej, podczas gdy wykonywana jest akcja. Opcja ta moze być użyteczna dla zwolnienia prędkosci myszki podczas strzelania. Insert a pause that occurs in between key presses. Dodaj przerwę, która występuje pomiędzy naciskanymi klawiszami. Specify the time that keys past this slot should be held down. Określ czas, przez który klawisze z tego slotu powinny być przytrzymywane. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Wprowadź akcję zwalniania. Sloty po tej akcji zostaną wywołane po zwolnieniu przycisku, jeśli przycisk ten został trzymany przez określoną umowną ilość czasu. Change to selected set once slot is activated. Zmień zaznaczone zestawienie gdy slot jest aktywowany. Full string will be typed when a slot is activated. Pełna treść zostania wpisana gdy slot zostanie aktywowany. Execute program when slot is activated. Wykonaj program gdy slot jest aktywny. AdvanceStickAssignmentDialog Stick/Pad Assignment Przypisanie do Joysticka/Gamepada Sticks Joysticki DPads Pady kierunkowe Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Adnotacja: To okno zostało zachowane z myślą o kompatybilności wstecznej z profilami stworzonymi w wersji AntiMicroX starszej niż 2.0. Rekomendowane jednak jest używanie nowszej wersji okna do mapowania kontrolera. Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Uwaga: To okno jest przeznaczone do kompatybilności wstecznej z profilami przed Antimicro 2.0. Od wersji 2.0 preferowane jest korzystanie z okna mapowania kontrolera gry. %1 (Joystick %2) %1 (Joystick %2) Stick 1 Joystick 1 Enabled Odblokowany Assign Przypisz X Axis: Oś X: Y Axis: Oś Y: Stick 2 Joystick 2 Number of Physical DPads: %1 Liczba fizycznych padów kierunkowych: %1 Virtual DPad 1 Wirtualny pad kierunkowy 1 Down: Dół: Left: Lewo: Right: Prawo: Up: Góra: Axis %1 Oś %1 Axis %1 - Oś %1 - Axis %1 + Oś %1 + Button %1 Przycisk %1 Move stick 1 along the X axis Porusz gałką 1 wzdłuż osi X Move stick 1 along the Y axis Porusz gałką 1 wzdłuż osi Y Move stick 2 along the X axis Porusz gałką 2 wzdłuż osi X Move stick 2 along the Y axis Porusz gałką 2 wzdłuż osi Y Press a button or move an axis Wciśnij przycisk lub porusz gałką wzdłuż osi AxisEditDialog Axis Presets: Predefinicje: Mouse (Horizontal) Mysz (poziomo) Mouse (Inverted Horizontal) Mysz (w odwróconym poziomie) Mouse (Vertical) Mysz (pionowo) Mouse (Inverted Vertical) Mysz (w odwróconym pionie) Arrows: Up | Down Strzałki: Góra | Dół Arrows: Left | Right Strzałki: Lewo | Prawo Keys: W | S Klawisze: W | S Keys: A | D Klawisze: A | D NumPad: KP_8 | KP_2 Klawisze num: KP_8 | KP_2 NumPad: KP_4 | KP_6 Klawisze num: KP_4 | KP_6 None Brak Set the value to use as the limit for an axis. Useful for a worn out analog stick. Ustaw wartość limitu dla osi. Opcja jest przydatna dla zużytej gałki analogowej. Dead Zone: Martwa strefa: Set the value of the dead zone for an axis. Ustaw wartość martwej strefy dla osi. Max Zone: Maksymalna strefa: [NO KEY] [BRAK] Throttle setting that determines the behavior of how to interpret an axis hold or release. Ustawienia przepustnicy, które determinują zachowanie sposobu interpretacji trzymania osi i jej zwalniania. Negative Half Throttle Ujemny zakres ruchu osi do połowy Negative Throttle Ujemny zakres ruchu osi Normal Standardowy Positive Throttle Dodatni zakres ruchu osi Positive Half Throttle Dodatni zakres ruchu osi do połowy Current Value: Aktualna wartość: Name: Nazwa: Specify the name of an axis. Określ nazwę osi. Mouse Settings Ustawienia myszki Set Ustaw Set %1 Zestawienie %1 Left Mouse Button Lewy przycisk myszy Right Mouse Button Prawy przycisk myszy ButtonEditDialog Dialog Okno dialogowe To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Wciśnij dowolny klawisz lub kliknij na przycisk myszy, by stworzyć nowe przypisanie Placeholder Zastępstwo Enables a key press or release to only occur when a controller button is pressed. Odblokowuje naciśnięcie klawisza lub zwolnienie go, gdy przycisk kontrolera jest wciśnięty. Toggle Przycisk przełączania Enables rapid key presses and releases. Turbo controller. Odblokowuje szybsze naciskanie klawiszy i ch zwalnianie. Kontroler turbo. Turbo Przycisk turbo Last keyboard/mouse button: Ostatni przycisk klawiatury/myszy: Slots Sloty Na&me: Naz&wa: Specify the name of a button. Określ nazwę przycisku. Action: Akcja: Specify the action that will be performed in game while this button is being used. Określ akcję, która będzie się wykonywała w grze, podczas gdy przycisk jest wciśnięty. Advanced Zaawansowany Choose your keyboard key Naciśnij dowolny klawisz No button Brak przycisku Last button Ostatni przycisk To change settings for last button, it must be at least one assignment from keyboard to gamepad Musi istnieć co najmniej jedno przypisanie z klawiatury do gamepad'a, by zmienić ustawienia dla ostatniego przycisku To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad Musi istnieć co najmniej jedno przypisanie z klawiatury do gamepad'a, by zmienić ustawienia turbo dla ostatniego przycisku No choice Brak wyboru Before you open window with advanced settins, you have to choice a key Zanim otworzysz okno z zaawansowanymi ustawieniami, musisz wybrać klawisz To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Potrzebne jest co najmniej jedno mapowanie z klawiatury do gamepad'a, by móc otworzyć okno z zaawansowanymi ustawieniami Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Sloty dla wprowadzonych przycisków nie mogły zostać usunięte, ponieważ żadne dane nie zostały dotychczas wprowadzone z układu klawiatury do układu gamepad'a. Stwórz mapowanie co najmniej jednego przycisku dla gamepad'a As last gamepad button has been set Został ustawiony ostatni przycisk gamepad'a Index %1 Indeks %1 [NO KEY] [BRAK] Calibration Form Okno Start calibration Rozpocznij kalibrację Controller: Kontroler: Sticks: Joysticki: Use settings from jstest-gtk Zastosuj ustawienia z jstest-gtk Reset settings Resetuj ustawienia Cancel Anuluj Save Zapisz Calibration Kalibracja Do you really want to reset settings of current axes? Czy chcesz zresetować ustawienia aktualnych osi? Do you really want to reset settings of current axis? Czy na pewno chcesz zresetować ustawienia dla aktualnych osi? Calibration was saved for the preset. Do you really want to reset settings? Wartości kalibracji były zapisywane dla przycisku. Czy aby napewno zresetować ustawienia? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Nakieruj oś na środkową pozycję. To jest ta część, gdzie często nie ma potrzeby ruszania osią. W takiej sytuacji wystarczy jedynie przejść do następnego kroku. Calibrating center Kalibrowanie środka Start second step Rozpocznij drugi krok Center X: %1 Środek X: %1 Center Y: %1 Środek Y: %1 Place the joystick in the top-left corner many times Nakieruj oś w stronę górnego lewego rogu wiele razy Calibrating position Kalibrowanie pozycji X: %1 X: %1 Y: %1 Y: %1 Place the joystick in the bottom-right corner Nakieruj oś w stronę dolnego prawego rogu Start final step Rozpocznij ostatni krok range X: %1 - %2 przedział dla X: %1 - %2 range Y: %1 - %2 przedział dla Y: %1 - %2 deadzone X: %1 martwa strefa X: %1 deadzone Y: %1 martwa strefa Y: %1 ---Calibration done!--- ---Kalibracja zakończona!--- Calibration values have been saved Wartości kalibracji zostały zapisane Dead zone calibration kalibracja martwej strefy You have to move axes to the top-left corner at least five times. Nakieruj oś w lewy górny róg co najmniej pięć razy. You have to move axes to the bottom-right corner at least five times. Nakieruj oś w prawy dolny róg co najmniej pięć razy. Do you want to save calibration of current axis? Czy chcesz zapisać zmiany dla aktualnych osi? You must move X axis to the right at least five times! Keep moving! Nakieruj oś X w prawą stronę co najmniej pięć razy! You must move X axis to the left at least five times! Keep moving! Nakieruj oś X w lewą stronę co najmniej pięć razy! Axis %1 Oś %1 CapturedWindowInfoDialog Captured Window Properties Uchwycone właściwości okna Information About Window Informacje o oknie Class: Klasa: TextLabel Etykieta Title: Tytuł: Path: Ścieżka: Match By Properties Dopasowanie według właściwości Class Klasa Title Tytuł Path Ścieżka Full Path Pełna ścieżka File Name Nazwa pliku DPadContextMenu Mouse (Normal) Mysz (standardowo) Mouse (Inverted Horizontal) Mysz (w odwróconym poziomie) Mouse (Inverted Vertical) Mysz (w odwróconym pionie) Mouse (Inverted Horizontal + Vertical) Mysz (w odwróconym poziomie + pionie) Arrows Strzałki Keys: W | A | S | D Klawisze: W | A | S | D NumPad Klawisze numeryczne None Brak Standard Standard Eight Way Ośmioosiowo 4 Way Cardinal w 4 głównych kierunkach 4 Way Diagonal w 4 głównych przekątnych Mouse Settings Ustawienia myszki DPadEditDialog Dialog Okno dialogowe Presets: Predefinicje: Mouse (Normal) Mysz (standardowo) Mouse (Inverted Horizontal) Mysz (w odwróconym poziomie) Mouse (Inverted Vertical) Mysz (w odwróconym pionie) Mouse (Inverted Horizontal + Vertical) Mysz (w odwróconym poziomie + pionie) Arrows Strzałki Keys: W | A | S | D Klawisze: W | A | S | D NumPad Klawiatura numeryczna None Brak Dpad Mode: Tryb pada kierunkowego: Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Standardowo: Ośmiokierunkowy analog z dwoma aktywnymi przyciskami nakierowującymi, gdy analog jest zwrócony w kierunku ukośnym. Ośmioosiowo: Ośmiokierunkowy analog z ośmioma przyciskami. Tylko jeden przycisk jest aktywny w tym samym czasie. Opcja jest przydatna w przypadku gier podobnych do Rogue. W 4 głównych kierunkach: Czterokierunkowy analog z kierunkami odwołującymi się do głównych kierunków świata. Opcja jest przydatna w przypadku menu W 4 głównych przekątnych: Czterokierunkowy analog z kierunkami odwołującymi się do stref przekątnych analogu. Standard Standardowo Eight Way Ośmioosiowo 4 Way Cardinal W 4 głównych kierunkach 4 Way Diagonal W 4 głównych przekątnych DPad Delay: Opóźnienie pada kierunkowego: Time lapsed before a direction change is taken into effect. Czas, który upłynął przed wykryciem zmiany kierunku. s s &Name: &Nazwa: Specify the name of a dpad. Określ nazwę pada kierunkowego. Mouse Settings Ustawienia myszki Set Ustaw Set %1 Zestawienie %1 EditAllDefaultAutoProfileDialog Default Profile Domyślny profil Profile: Profil: Browse Przeglądaj Open Config Otwórz konfigurację Profile file path is invalid. Ścieżka dla plik jest nieprawidłowa. ExtraProfileSettingsDialog Extra Profile Settings Dodatkowe ustawienia profilu Key Press Time: Czas wciśniętego klawisza: 0.00 ms 0.00 ms Profile Name: Nazwa profilu: s s GameController Game Controller Kontroler GameControllerDPad DPad Pad kierunkowy GameControllerMappingDialog Game Controller Mapping Mapowanie kontrolera <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> <html><head/><body><p>AntiMicroX używa dla działania tego <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;"> interfejsu kontrolerów gier</span></a> świadczonego przez bibliotekę SDL 2 w celu dopasowania przeróżnych gamepad'ów do jednolitego stworzonego standardu. Podświetl komórkę tabelki dla odpowiedniego przycisku, aby go przypisać. Możesz nacisnąć przycisk lub poruszyć osią na gamepad'zie, a wtedy w wybranej komórce zaktualizują się informacje według wciśniętego przycisku lub poruszonej osi. Pamiętaj, że narzucając wykrycie osi, musisz poruszyć nią w dół lub w prawo, gdyż pod nimi kryją się wartości dodatnie. </p><p>AntiMicroX użyje mapowania, które określisz podczas zapisywania mapowania tekstowego w postaci odczytywanej przez bibliotekę SDL.</p></body></html> A A B B X X Y Y Back Back Start Start Guide Guide Left Shoulder Left Shoulder Right Shoulder Right Shoulder Left Stick Click Left Stick Click Right Stick Click Right Stick Click Left Stick X Left Stick X Left Stick Y Left Stick Y Right Stick X Right Stick X Right Stick Y Right Stick Y Left Trigger Left Trigger Right Trigger Right Trigger DPad Up DPad Up DPad Left DPad Left DPad Down DPad Down DPad Right DPad Right Mapping Mapowanie SDL 2 Game Controller Mapping String Treść mapowania kontrolera według SDL 2 Last Axis Event: Ostatnie zdarzenie dla osi: Current Axis Detection Dead Zone: Aktualna martwa strefa podczas wykrywania ruchu osią: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Mapowanie kontrolera (%1) (#%2) Discard Controller Mapping? Usunąć mapowanie kontrolera? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Usunąć mapowanie dla tego kontrolera? Jeśli zostanie usunięte, kontroler zostanie przywrócony do joysticka, gdy tylko zaktualizujesz wszystkie joysticki. GameControllerSet Back Back Guide Guide Start Start LS Click LS Click RS Click RS Click L Shoulder L Shoulder R Shoulder R Shoulder L Trigger L Trigger R Trigger R Trigger GameControllerTrigger Trigger Przyciski Trigger JoyAxis Axis JoyAxisButton Button Przycisk Negative Ujemny Positive Dodatni Unknown Nieznany JoyAxisContextMenu Mouse (Horizontal) Mysz (poziomo) Mouse (Inverted Horizontal) Mysz (w odwróconym poziomie) Mouse (Vertical) Mysz (pionowo) Mouse (Inverted Vertical) Mysz (w odwróconym pionie) Arrows: Up | Down Strzałki: Góra | Dół Arrows: Left | Right Strzałki: Lewo | Prawo Keys: W | S Klawisze: W | S Keys: A | D Klawisze: A | D NumPad: KP_8 | KP_2 Klawiatura num: KP_8 | KP_2 NumPad: KP_4 | KP_6 Klawiatura num: KP_4 | KP_6 None Brak Mouse Settings Ustawienia myszki Left Mouse Button Lewy przycisk myszy Right Mouse Button Prawy przycisk myszy JoyButton Processing turbo for #%1 - %2 Przetwarzanie trybu turbo dla #%1 - %2 Finishing turbo for button #%1 - %2 Finalizacja trybu turbo dla przycisku #%1 - %2 Processing press for button #%1 - %2 Przetwarzanie naciśnięcia dla przycisku #%1 - %2 Processing release for button #%1 - %2 Przetwarzanie zwalniania dla przycisku #%1 - %2 Distance change for button #%1 - %2 Zmiana odległości dla przycisku #%1 - %2 Button Przycisk [NO KEY] [BRAK] [Set %1 1W] [Zestawienie %1 1W] [Set %1 2W] [Zestawienie %1 2W] [Set %1 WH] [Zestawienie %1 WH] JoyButtonContextMenu Toggle Przycisk przełączania Turbo Przycisk turbo Clear Wyczyść Set Select Wybór ustawienia Disabled Zablokowane Set %1 Zestawienie %1 Set %1 1W Zestawienie %1 1W Set %1 2W Zestawienie %1 2W Set %1 WH Zestawienie %1 WH JoyButtonSlot Mouse Mysz Up Góra Down Dół Left Lewo Right Prawo LB LB MB MB RB RB B4 B4 B5 B5 Pause Przerwa Hold Przytrzymanie Cycle Cykl Distance Odległość Release Zwolnienie Mouse Mod Tryb myszki Press Time Przytrzymanie okresowo Delay Opóźnienie Load %1 Załadowanie %1 Set Change %1 Zmiana ustawienia %1 [Text] %1 [Text] %1 [Exec] %1 [Exec] %1 [NO KEY] [BRAK] JoyControlStick Stick Joystick analogowy JoyControlStickButton Up Góra Down Dół Left Lewo Right Prawo Button Przycisk JoyControlStickContextMenu Mouse (Normal) Mysz (standardowo) Mouse (Inverted Horizontal) Mysz (w odwróconym poziomie) Mouse (Inverted Vertical) Mysz (w odwróconym pionie) Mouse (Inverted Horizontal + Vertical) Mysz (w odwróconym poziomie + pionie) Arrows Strzałki Keys: W | A | S | D Klawisze: W | A | S | D NumPad Klawisze numeryczne None Brak Standard Standard Eight Way Ośmioosiowo 4 Way Cardinal w 4 głównych kierunkach 4 Way Diagonal w 4 głównych przekątnych Mouse Settings Ustawienia myszki JoyControlStickEditDialog Dialog Okno dialogowe X: X: 0 0 Y: Y: Distance: Odległość: Bearing: Łożysko: % Safe Zone: % strefa bezpieczna: Presets: Predefinicje: Mouse (Normal) Mysz (standardowo) Mouse (Inverted Horizontal) Mysz (w odwróconym poziomie) Mouse (Inverted Vertical) Mysz (w odwróconym pionie) Mouse (Inverted Horizontal + Vertical) Mysz (w odwróconym poziomie + pionie) Arrows Strzałki Keys: W | A | S | D Klawisze: W | A | S | D NumPad Klawisze numeryczne None Brak Stick Mode: Tryb joysticka analogowego: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Standardowo: Ośmiokierunkowy analog z dwoma aktywnymi przyciskami nakierowującymi, gdy analog jest zwrócony w kierunku ukośnym. Ośmioosiowo: Ośmiokierunkowy analog z ośmioma przyciskami. Tylko jeden przycisk jest aktywny w tym samym czasie. Opcja jest przydatna w przypadku gier podobnych do Rogue. W 4 głównych kierunkach: Czterokierunkowy analog z kierunkami odwołującymi się do głównych kierunków świata. Opcja jest przydatna w przypadku menu W 4 głównych przekątnych: Czterokierunkowy analog z kierunkami odwołującymi się do stref przekątnych analogu. Standard Standardowo Eight Way Ośmioosiowo 4 Way Cardinal W 4 głównych kierunkach 4 Way Diagonal W 4 głównych przekątnych Dead Zone: Martwa strefa: Dead zone value to use for an analog stick. Wartość martwej strefy dla zastosowania w joysticku analogowym. Max Zone: Maksymalna strefa: Value when an analog stick is considered moved 100%. Wartość określająca analog, którego kursor przekroczył 100%. Diagonal Range: Zakres przekątnej: The area (in degrees) that each diagonal region occupies. Powierzchnia (w stopniach), która zajmuje każdy przekątny kierunek. Square Stick: Czterokierunkowy analog: Percentage to modify a square stick coordinates to confine values to a circle Zmiana współrzędnych czterokierunkowego analogu dla ograniczenia wartości do koła, określona w procentach % % Stick Delay: Opóźnienie drążka: Time lapsed before a direction change is taken into effect. Czas, który upłynął przed wykryciem zmiany kierunku. s s Modifier: Modyfikator: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. Przycisk edycji, który jest aktywny w trakcie, gdy i drążek jest aktywny. Ten przycisk jest przydatny dla przypisywania stref z klawiszami modyfikatora, które mogą być użyte do przypisania funkcji chodzenia/biegania do drążka analogowego. PushButton Przycisk Na&me: Name: Na&zwa: Specify the name of an analog stick. Określ nazwę joysticka analogowego. Mouse Settings Ustawienia myszki Set Ustaw Set %1 Zestawienie %1 JoyControlStickModifierButton Modifier Modyfikator JoyDPad DPad Pad kierunkowy JoyDPadButton Up Góra Down Dół Left Lewo Right Prawo Button Przycisk JoyTabWidget <New> <Nowy> Remove Usuń Remove configuration from recent list. Usuń konfigurację z ostatniej listy. Load Załaduj Load configuration file. Załaduj plik konfiguracyjny. Save Zapisz Save changes to configuration file. Zapisz zmiany do pliku konfiguracyjnego. Save As Zapisz jako Save changes to a new configuration file. Zapisz zmiany do nowego pliku konfiguracyjnego. Sets Zestawienia Copy from Set Kopiuj z zestawienia Settings Ustawienia Set 1 Zestawienie 1 Set 2 Zestawienie 2 Set 3 Zestawienie 3 Set 4 Zestawienie 4 Set 5 Zestawienie 5 Set 6 Zestawienie 6 Set 7 Zestawienie 7 Set 8 Zestawienie 8 Stick/Pad Assign Przypisywanie do Joysticka/Gamepada Controller Mapping Mapowanie kontrolera Quick Set Szybkie ustawienie Names Nazwy Toggle button name displaying. Przełącz wyświetlanie nazwy przycisku. Pref Pref Change global profile settings. Zmień globalne ustawienia dla profilu. Reset Reset Revert changes to the configuration. Reload configuration file. Przwróć zmiany w konfiguracji. Przeładuj plik konfiguracyjny. Open Config Otwórz konfigurację Config Files (*.amgp *.xml) Pliki konfiguracyjne (*.amgp *.xml) Save Config Zapisz konfigurację Config File (*.%1.amgp) Plik konfiguracyjny (*.%1.amgp) Do you really want to reset buttons settings for joystick? Czy na pewno chcesz zresetować ustawienia dla przycisków joystick'a? Set Ustaw Save Profile Changes? Zapisać zmiany dla profilu? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Zmiany dla nowego profilu nie zostały zapisane. Czy chcesz, aby aktualny profil został zapisany lub usunięty? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Zmiany dla profilu "%1" nie zostały zapisane. Czy chcesz, aby zmiany dla aktualnego profilu zostały zapisane lub usunięte? Sticks Joysticki analogowe DPads Pady kierunkowe No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Nie wykryto żadnych przypisywanych przycisków. Użyj okna szybkiego ustawiania, by przypisać znaki klawiszy do przycisków lub zablokuj ukrywanie pustych przycisków. Set %1: %2 Zestawienie %1: %2 Set %1 Zestawienie %1 Copy Set Assignments Skopiuj zestawienie przypisań Are you sure you want to copy the assignments and device properties from %1? Czy na pewno chcesz skopiować przypisania i właściwości urządzenia z %1? Joystick Joystick Joystick JoystickStatusWindow Properties Właściwości Details Szczegóły Name: Nazwa: %1 %1 Number: Numer: Axes: Osie: Buttons: Przyciski: Hats: Przyciski POV: Battery: Bateria: Unknown Nieznany GUID: GUID: Game Controller: Kontroler: Axes Osie Buttons Przyciski Hats Przyciski POV %1 (#%2) Properties %1 (#%2) Właściwości Axis %1 Oś %1 Hat %1 Przycisk POV %1 No Nie Yes Tak MainSettingsDialog Edit Settings Zmień ustawienia General Ogólnie Controller Mappings Mapowania kontrolera Language Język Auto Profile Profil automatyczny Mouse Mysz Advanced Zaawansowany Profi&le Directory: Ścieżka profi&lu: Profile Direc&tory: Ścieżka profi&lu: Pro&file Directory: Kat&alog profilu: <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Określ domyślną ścieżkę, aby program mógł go użyć w innych oknach podczas ładowania profilu lub zapisywania nowego.</p></body></html> Recent Profile Count: Liczba ostatnich profili: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Liczba profili, które mogą być umieszczone na liście ostatnich profili. 0 będzie skutkowało tym, że limit dla liczby wyświetlanych profili nie będzie w ogóle narzucany.</p></body></html> Gamepad Poll Rate: Szybkość wysyłania sygnałów gamepada: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Zmień szybkość wysyłania sygnałów, które program używa, by przechwytywać nowe zdarzenia z gamepada. Domyślnie wartość wynosi 10 ms. Zmniejszenie szybkośći wysyłania sygnałów mogłoby spowodować większe zużycie mocy procesora. Wysoce rekomendowane jest przeprowadzenie testów ustawień przed użyciem AntiMicroX. Hide main window when the main window close button is clicked instead of quitting the program. Ukryj główne okno, a nie zamykaj, gdy wybierany jest przycisk zamykania okna. Close To Tray Zamknij w tacce systemowej Have Windows start AntiMicroX at system startup. Uruchom AntiMicroX przy uruchomieniu systemu. Launch At Windows Startup Uruchom przy starcie Windows Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Wyświetl ostatnie profile dla wszystkich kontrolerów w postaci pojedynczej listy w menu zasobnika systemowego. Domyślnie dla użycia podmenu. Single Profile List in Tray Pojedyncza lista profilu w tacce systemowej Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Zminimalizuj program do paska zadań. Domyślnie program jest minimalizowany do tacki systemowej jeśli jest to możliwe. Minimize to Taskbar Zminimalizuj do paska zadań This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Ta opcja spowoduje schowanie wszystkich nieprzypisanych przycisków w aplikacji. Zajdzie potrzeba użycia okna szybkiego ustawiania, by pojawiło się okno edytowania dla przycisków gamepada. Hide Empty Buttons Ukryj puste przyciski When the program is launched, open the last known profile that was opened during the previous session. Gdy program jest już uruchomiony, otwórz ostatni znany profil, który był otwierany podczas poprzedniej sesji. Auto Load Last Opened Profile Automatycznie ładuj ostatni otwarty profil Only show the system tray icon when the program first launches. Pokazuj jedynie ikonę w tacce systemowej, gdy program się uruchamia. Launch in Tray Uruchom w tacce systemowej Associate .amgp files with AntiMicroX in Windows Explorer. Skojarz pliki .amgp z AntiMicroX w eksploratorze Windows. Associate Profiles Skojarz profile Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Pamiętaj, że nie będzie działać, jeśli nie masz takiej klawiatury podłączonej do komputera lub jeśli nie jest ona wbudowana jak w komputerach stacjonarnych Attach the numeric keypad Podłącz klawiaturę numeryczną Combination of keys for quitting app Kombinacja klawiszy do zamykania aplikacji Choose keys combination Wybierz kombinację klawiszy ! restart is needed after choice of combination ! restart jest niezbędny po wybraniu kombinacji Key Repeat Powtarzanie klawisza Active keys will be repeatedly pressed when this option is enabled. Aktywne klawisze będą wielokrotnie naciskane gdy ta opcja zostanie zaznaczona. Enable Odblokuj Delay: Opóźnienie: Specifies how much time should elapse before key repeating begins. Określa, ile czasu musi upłynąć, zanim nastąpi powtarzanie przycisku klawisza. ms ms Rate: Tempo: Specifies how many times key presses will be performed per seconds. Określa, ile razy na sekundę klawisz będzie naciskany automatycznie. times/s raz/y Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Poniżej znajduje się lista zapisanych mapowań. Możesz użyć podanej tabeli, by usunąć mapowania lub je tymczasowo zablokować. Możesz także zablokować mapowania, które są zawarte z biblioteką SDL; wystarczy wprowadzenie nowego rzędu z odpowiednim GUID joysticka i zaznaczenie blokady. Ustawienia nie będą miały wpływu o ile nie zostaną odświeżone wszystkie joysticki lub nie zostanie odpięty konkretny joystick. GUID GUID Mapping String Mapowanie tekstowe Disable? Zablokować? Delete Usuń Insert Dodaj <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntiMicroX został przetłumaczony na wiele innych języków przez kilku woluntariuszy. Domyślnie program wybierze odpowiednie tłumaczenie oparte na ustawieniach lokalnych systemu. Jednakże możliwy jest wybór innego języka, który znajduje się na liście poniżej.</p></body></html> Default Domyślny Português do Brasil Português do Brasil English English Français Français Deutsch Deutsch Italiano Italiano 日本語 日本語 Русский Русский српски / srpski српски / srpski 简体中文 简体中文 Español Español українська українська Polski Polski Active Aktywny Devices: Urządzenia: All Wszystko Device Urządzenie Profile Profil Class Klasa Title Tytuł Program Program Default? Domyślnie? Add Dodaj Edit Edytuj Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Zablokuj ustawienie "Rozszerzona precyzja kursora", podczas gdy AntiMicroX jest uruchomiony. Zablokowanie opcji "Rozszerzona precyzja kursora" pozwoli na bardziej precyzyjny ruch myszki wewnątrz AntiMicroX. Disable Enhance Pointer Precision Zablokuj rozszerzoną precyzję myszki Smoothing Wygładzanie History Si&ze: Rozmia&r historii: Weight Modi&fier: Mody&fikator wagowy: Note: To see the change of log level in console output (not in log file), application restart is required Uwaga: Aby zobaczyć logi w konsoli (nie w wybranym pliku), wymagany jest restart aplikacji Reset Reset Histor&y Size: Rozmia&r historii: Weight &Modifier: Modyfikator &wagi: Refresh Rate: Częstotliwość odświeżania: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Częstotliwość odświeżania jest ilością czasu, jaka upłynie pomiędzy występowaniem zdarzeń myszki. Zaleca się ostrożnie stosować tę opcję, ponieważ może spowodować większe zużycie mocy procesora. Ustawienie wartości zbyt niskiej wywoła destabilizację systemu. Silnie zaleca się przetestowanie ustawienia przed jego użyciem. Spring Tekst Screen: Ekran: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Wykorzystaj określony wyświetlacz dla trybu tekstowego. Na Linux, domyślnie używany jest główny ekran. Na Windows, domyślnie używane są wszystkie dostępne ekrany. Accel Numerator: Licznik przyspieszenia: 0 0 Accel Denominator: Mianownik przyspieszenia: Accel Threshold: Granica przyspieszenia: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Jeżeli wartości przyspieszenia dla wirtualnej myszki nie zostały zmienione przez odmienny proces, szczególnie w trakcie wyłącznia starszej gry, to możesz chcieć zresetować wartości przyspieszenia stosowane przez wirtualną myszkę. Reset Acceleration Resetuj przyspieszenie Log File: Plik z logami: Log Level: Poziom logów: None Brak Error Błąd Warning Ostrzeżenie Info Informacja Debug Debugowanie Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Również użytkownicy systemu Windows, którzy chcą zastosować niską wartość, powinni także sprawdzić opcję "Zablokuj rozszerzoną precyzję myszki", jeżeli nie chcą mieć zablokowanej tej opcji w Windows. Select Default Profile Directory Zaznacz domyślny katalog profilu Are you sure you want to delete the profile? Czy na pewno usunąć ten profil? Save Log File As Zapisz plik z logami jako Log Files (*.log) Pliki z logami (*.log) Do you really want to reset setting? Czy na pewno chcesz zresetować ustawienia? Would you like to reset mappings too? Czy chcesz także zresetować ustawienia mapowania? [NO KEY] [BRAK] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Nie znaleziono żadnego joysticka. Podłącz joystick a następnie wybierz opcję "Zaktualizuj joysticki" w głównym menu If events are not seen by a game, please click here to run this application as Administrator. Jeśli zdarzenia nie są wykrywane przez grę, kliknij tutaj, by uruchomić aplikację w trybie administratora. &App &Aplikacja &Options &Opcje &Help &Pomoc He&lp Po&moc &Quit &Zakończ Ctrl+Q Ctrl+Q &Update Joysticks &Zaktualizuj joysticki Ctrl+U Ctrl+U &Hide &Ukryj Ctrl+H Ctrl+H &About &O programie Ctrl+A Ctrl+A About &Qt O &Qt Ctrl+T Ctrl+T &Properties &Właściwości Ctrl+P Ctrl+P &Key Checker &Sprawdzanie klawiszy Ctrl+K Ctrl+K Home Page Strona domowa &GitHub Page &Strona na Github Ctrl+G Ctrl+G &Game Controller Mapping &Mapowanie kontrolera Ctrl+M Ctrl+M S&ettings U&stawienia Ctrl+S Ctrl+S &Stick/Pad Assign &Przypisywanie do Joysticka/Gamepada Ctrl+X Ctrl+X &Wiki &Wiki Ctrl+W Ctrl+W &Issues &Błędy Ctrl+I Ctrl+I &Calibration &Kalibracja Ctrl+C Ctrl+C Issues Błędy Could not find a proper controller identifier. Exiting. Nie można znaleźć odpowiedniego identyfikatora dla kontrolera. Wychodzę. (%1) (%1) Open File Otwórz plik %1 battery %1 bateria Battery level is less than %1 Poziom baterii jest niższy niż %1 Device number: %1 Device name: %2 Numer urządzenia: %1 Nazwa urządzenia: %2 Reading old profile Odczyt starego profilu This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 Ten profil wykorzystuje numery GUID kontrolerów. Czy chciałbyś zmienić numery GUID na UniqueID w tym pliku do użytku w identycznych urządzeniach? Taki stary plik nie może być załadowany w AntimicroX od wersji 2.25 wzwyż &Restore &Przywracanie Calibration couldn't be opened Okno kalibracji nie mogło zostać otwarte You must connect at least one controller to open the window Wymagane jest podłączenie co najmniej jednego kontrolera przed próbą otworzenia okna Run as Administrator? Uruchomić jako administrator? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Czy na pewno uruchomić program w trybie administratora? Niektóre gry wymagają uruchamiania w trybie administratora, który pozwala na wychwytywanie zdarzeń, generowanych przez AntiMicroX tak, aby nie były używane przez te gry, o ile AntiMicroX jest również uruchomiony w trybie administratora. Sposób ten powstał z powodu problemów uprawnień, wywoływanych przez opcje Kontroli Konta Użytkownika w wersjach Windows'a, poczynając od wersji Windows Vista. Failed to elevate program Podniesienie programu zakończyło się niepowodzeniem Failed to restart this program as the Administrator Ponowne uruchomienie programu w trybie administratora zakończyło się niepowodzeniem Could not find controller. Exiting. Nie można znaleźć kontrolera. Wychodzę. MouseAxisSettingsDialog Mouse Settings - Ustawienia Myszki - Set %1 Zestawienie %1 MouseButtonSettingsDialog Mouse Settings - Ustawienia msyzki - Set %1 Zestawienie %1 MouseControlStickSettingsDialog Mouse Settings Ustawienia myszki Set %1 Zestawienie %1 MouseDPadSettingsDialog Mouse Settings Ustawienia myszki Set %1 Zestawienie %1 MouseSettingsDialog Mouse Settings Ustawienia myszki Mouse Mode: Tryb myszki: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Tryb kursora jest używany do poruszania kursorem myszki po ekranie w odniesieniu do jego aktualnej pozycji w zależności jak intensywnie poruszasz się po osi lub jak intensywnie naciskany jest przycisk. Tryb tekstowy jest używany do poruszania kursorem myszki od środka ekranu w zależności jak bardzo poruszasz nią wzdłuż osi. Kursor myszki będzie wracał na środek ekranu za każdym razem, gdy odległość wzdłuż osi, którą pokonałeś ruchem myszki przekroczy ustaloną granicę. Cursor Kursor Spring Tekst Acceleration: Akceleracja: Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Rozszerzony: Trzeci stopień krzywej, który sprawia, że ruch myszki zwalnia przy początku osi i przyspiesza przy jego końcu. Liniowy: Kursor myszki porusza się proporcjonalnie do osi. Kwadratowy: Kursor myszki przyspiesza wolno na początku osi. Sześcienny: Ruch myszki przyspiesza wolniej niż w trybie kwadratowym (czyli krzywej drugiego stopnia). Skrajnie kwadratowy: Zwiększa prędkość ruchu myszki 1.5 razy dopóki nie osiągnie 95% zamierzonego odcinka Funkcja mocy: Pozwala na użycie bardziej tradycyjnej opcji krzywej. Łagodnie kwadratowy: Poziom końcowy osi przyspiesza stopniowo przez określony czas z zastosowaniem krzywej drugiego stopnia. Łagodnie sześcienny: Poziom końcowy osi przyspiesza stopniowo przez określony czas z zastosowaniem krzywej trzeciego stopnia. Enhanced Precision Rozszerzona precyzja Linear Liniowa (krzywa I stopnia) Quadratic Kwadratowa (krzywa II stopnia) Cubic Sześcienna (krzywa III stopnia) Quadratic Extreme Skrajnie kwadratowa Power Function Funkcja mocy Easing Quadratic Łagodnie kwadratowa Easing Cubic Łagodnie sześcienna Mouse Speed Settings Ustawienia prędkości myszki Enable to change the horizontal and vertical speed boxes at the same time. Możliwa zmiana prędkości poziomej i pionowej skrzyń w tym samym czasie. Change Together Zmiany całościowe Hori&zontal Speed: Prę&dkość pozioma: 1 = 20 pps 1 = 20 pps &Vertical Speed: &Prędkość pionowa: Wheel Hori. Speed: Kierownica Hori. Prędkość: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Ustawia prędkość poziomego ruchu rolki myszki według liczby symulowanych kroków na sekundę. 1 = 1 notch(es)/s 1 = 1 obrót(y)/ów Wheel Vert. Speed: Kierownica pionowa. Prędkość: Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Ustawia prędkość pionowego ruchu rolki myszki według liczby symulowanych kroków na sekundę. Sensitivit&y: Czułoś&ć: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Przeznaczone dla funkcji mocy. Określa czynnik dla zastosowania czułości krzywej. Gdy wartość przekracza 1.0, ruch myszki ulegnie większemu przyspieszeniu na niskim poziomie osi. Easing Duration: Zmniejszenie trwania: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. Określa ilość czasu (w sekundach) wymaganą przed pełnym przyspieszeniem myszy i po osiągnięciu końcowego odcinka osi. s s Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Opcje dodania lepszego przyspieszenia ruchu myszki poza tym, co krzywa przespieszenia mogłaby wyprodukować. Przyspieszenie jest dodawane na podstawie tego, jak szybko następuje ruch osi. Opcja została stworzona w celu wyeliminowania pewnych błędów związanych z bardzo ograniczoną dostępnością do przedziału wartości, używając standardowych przycisków analogowych. Delta Acceleration Przyspieszenie delta &Multiplier: &Mnożnik: Highest value to accelerate mouse movement by Największa wartość przyspieszenia ruchu myszki x x Start %: Start %: Acceleration begins at this percentage of the base multiplier Przyspiesznie rozpoczyna się na tym poziomie procentowym głównego mnożnika % % Mi&n Threshold: Mi&nimalna granica: Minimum amount of axis travel required for acceleration to begin Minimum dla ilości przesuwu osi, wymaganej do rozpoczęcia przyspieszenia Max Threshold: Maksymalna granica: Maximum axis travel before acceleration has reached the multiplier value Maksimum dla przesuwu osi, potrzebnego dla momentu, zanim przyspiesznie osiągnie wartość mnożnika E&xtra Duration: Do&datkowy czas trwania: Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Rozszerzenie przedziału czasowego dla dodania dodatkowego przyspieszenia. Przesuw osi zostanie przeniesiony do konta. Wolniejszy ruch zmniejszy aktualny czas, by mogło zostać dodane dodatkowe przyspieszenie. Curve: Krzywa: Ease Out Sine Zwalnianie pod koniec Ease Out Quad Większe zwalnianie pod koniec Ease Out Cubic Zwalnianie pod koniec plus większe przyspieszenie Spring Settings Ustawienia tekstu Spring Width: Szerokość tekstu: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Zmienia szerokość regionu tak, aby kursor mógł poruszać się w trybie tekstowym. 0 będzie używało całej szerokości twojego ekranu. Spring Height: Wysokość tekstu: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Zmienia wysokość regionu tak, aby kursors mógł poruszać się w trybie sprężyny. 0 będzie używało całej szerokości twojego ekranu. Release Radius: Zwalnianie zasięgu: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Określa, czy pole tekstowe będzie zależne od pozycji kursora myszki, ustawionej przez niezależny tekst. Relative Względny Mouse Status Status myszki X: X: 0 (0 pps) 0 (0 pps) Y: Y: %n notch(es)/s %n obrót %n obroty %n obrotów ProfileImporter Form Okno Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Anuluj OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Detekcja klawiszy <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Naciśnij dowolny klawisz na klawiaturze, aby sprawdzić, w jakiej postaci jest wykrywany przez aplikację. W oknie pojawią się wartości pod trzema postaciami: systemową natywną, oryginalną stosowaną przez bibliotekę Qt oraz w postaci standardowej używanej przez AntiMicroX.</p><p>Wartość znaku w AntiMicroX oraz wartość znaku stosowanego w Qt będą zazwyczaj takie same, ponieważ aplikacja stara się używać wartości zdefiniowanej przez Qt, o ile jest to możliwe. Odwiedź stronę <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> aby zapoznać się z aktualną listą znaków. Jeśli zauważysz, że wybrany znak nie jest natywnie wspierany przez program, możesz to zgłosić na stronie <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">strona GitHub</span></a> by można było odpowiednio uaktualnić program. Tak jak jest aktualnie, prefiks jest dodawany do nieznanych wartości, aby mogły być nadal używane. Jednak problemem staje się brak przenośności danego profilu.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Naciśnij dowolny klawisz na klawiaturze, aby sprawdzić, w jakiej postaci jest wykrywany przez aplikację. W oknie pojawią się wartości pod trzema postaciami: systemową natywną, oryginalną stosowaną przez bibliotekę Qt oraz w postaci standardowej używanej przez AntiMicroX.</p><p>Wartość znaku w AntiMicroX oraz wartość znaku stosowanego w Qt będą zazwyczaj takie same, ponieważ aplikacja stara się używać wartości zdefiniowanej przez Qt, o ile jest to możliwe. Odwiedź stronę <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> aby zapoznać się z aktualną listą znaków. Jeśli zauważysz, że wybrany znak nie jest natywnie wspierany przez program, możesz to zgłosić na stronie <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">strona GitHub</span></a> by można było odpowiednio uaktualnić program. Tak jak jest aktualnie, prefiks jest dodawany do nieznanych wartości, aby mogły być nadal używane. Jednak problemem staje się brak przenośności danego profilu.</p></body></html> Event Handler: Procedura obsługi zdarzenia: Native Key Value: Wartość klawisza natywnego: 0x00000000 0x00000000 Qt Key Value: Wartość klawisza Qt: antimicro Key Value: Wartość klawisza AntiMicroX: AntiMicroX Key Value: Wartość klawisza AntiMicroX: QObject Last button Ostatni przycisk There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Program nie wykrywa ostatniego przypisanego przycisku. Czy co najmniej jeden przycisk został zmapowany z klawiatury do gamepad'a? # of joysticks found: %1 # joystick'ów zostało znalezionych: %1 List Joysticks: Lista joystick'ów: --------------- --------------- Joystick %1: Joystick %1: Index: %1 Indeks: %1 GUID: %1 GUID: %1 UniqueID: %1 UniqueID: %1 VendorID: %1 VendorID: %1 ProductID: %1 ProductID: %1 Product Version: %1 Wersja produktu: %1 Name: %1 Nazwa: %1 Yes Tak No Nie Game Controller: %1 Kontroler do gier: %1 # of Axes: %1 # osi: %1 # of Buttons: %1 # przycisków: %1 # of Hats: %1 # przycisków POV: %1 Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Aktywne okno zostało zmienione: Tytuł = "%1", Klasa = "%2", Program = "%3" lub "%4". Profile location %1 is not an XML file. Lokalizacja profilu %1 nie wskazuje na plik typu XML. Profile location %1 does not exist. Profil %1 nie istnieje. Controller identifier is not a valid value. Identyfikator kontrolera nie należy do wartości prawidłowych. An invalid set number '%1' was specified. Została określona nieprawidłowa liczba '%1". Controller identifier '%s'' is not a valid value. Identyfikator kontrolera '%s'' nie jest wartością prawidłową. No set number was specified. Nie została określona ustalona liczba. No controller was specified. Kontroler nie został określony. No display string was specified. Tekst dla wyświetlenia nie został określony. An invalid event generator was specified. Został określony nieprawidłowy generator zdarzeń. No event generator string was specified. Nie został określony generator zdarzeń. Qt style flag was detected but no style was specified. Flaga dla stylu Qt została wykryta lecz sam styl nie został uwzględniony. No log file specified. Nie został określony plik z logami programu. AntiMicroX version wersja AntiMicroX Usage: AntiMicroX [options...] [profile] Użycie: AntiMicroX [opcje...] [profil] Options Opcje Print help text. Wyświetl pomoc. Print version information. Wyświetl informacje o wersji. Launch program in system tray only. Uruchom program w tacce systemowej. Logging started Rozpoczęto generowanie logów Launch program with the tray menu disabled Uruchom program bez udziału tacki systemowej Launch program without the main window displayed Uruchom program pomijając wyświetlenie głównego okna Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Uruchom program ze wskazanym plikiem konfiguracyjnym jako domyślnym dla wskazanych kontrolerów location lokalizacja Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Wybierz plik konfiguracyjny dla wskazanego kontrolera. Wartością może być indeks kontrolera, nazwa lub GUID value wartość Unload currently enabled profile(s) Odłącz aktualnie odblokowany profil(e) value(s) wartość(i) Start joysticks on a specific set. Value can be a controller index, name, or GUID Uruchom joystick(i) z numerem ustawienia. Wartością może być indeks kontrolera, nazwa lub GUID number value numer wartość Launch program as a daemon. Use only on Linux. Uruchom program jako usługę w tle. Wyłącznie pod Linux. Enable logging Odblokuj generowanie logów log-type typ-logów Choose a file for logs writing Wybierz plik dla zapisywania logów filename nazwaPliku Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Wybierz między wsparciem xtest a wsparciem uinput dla generatora zdarzeń. Do zastosowania wyłącznie w przypadku wykrywania przez program xtest oraz uinput pod Linux oraz w przypadku wykrywania opcji vmulti pod Windows. Domyślnie: xtest. event-generation-type typ-generatora-zdarzeń Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Wyświetl informacje o wykrytych joystick'ach przez bibliotekę SDL. Zastosowanie wyłącznie z dostępną i odblokowaną biblioteką sdl. Wyświetlane informacje dotyczą indeksu kontrolerów, nazw i GUID. Daemon launched Usługa została uruchomiona Failed to launch daemon Uruchomienie usługi zostało zakończone niepowodzeniem Launching daemon Uruchamianie usługi Display string "%1" is not valid. Treść dla wyświetlenia "%1" jest nieprawidłowa. Failed to set a signature id for the daemon Ustawienie sygnatury id dla usługi została zakończona niepowodzeniem Failed to change working directory to / Zmiana katalogu roboczego została zakończona niepowodzeniem / Attempting to use fallback option %1 for event generation. Próba użycia awaryjnej opcji %1 dla generatora zdarzeń. Failed to open event generator. Exiting. Uruchomienie generatora zdarzeń zostało zakończone niepowodzeniem. Koniec. Using %1 as the event generator. Zastosowanie %1 jako generatora zdarzeń. Could not raise process priority. Nie można nadać procesowi większego priorytetu. Quitting Program Zamykanie aplikacji Auto-switching to profile "%1". Autoprzełączanie do profilu "%1". Auto-switching to nullptr profile! Autoprzełączanie do profilu nullptr! Super Super Menu Menu Mute Mute Vol+ Vol+ Vol- Vol- Play/Pause Play/Pause Play Play Pause Pause Prev Prev Next Next Mail Mail Home Home Media Media Search Search xinput version must be at least 2.0. No mouse acceleration changes will occur. wersja rozszerzenia xinput nie może być mniejsza od 2.0. Zmiany przy akceleracji myszki nie zostaną uwzględnione. QuickSetDialog Quick Set Szybkie ustawienie <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Naciśnij przycisk lub wykonaj ruch w kierunku osi %1 (<span style=" font-weight:600;">%2</span>).<br/>Pojawi się okno dialogowe<br/>które odblokuje możliwość tworzenia zadań.</p></body></html> Quick Set %1 Szybkie ustawienie %1 SetAxisThrottleDialog Throttle Change Zmiana przepustnicy analogowej The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? Ustawienie przepustnicy dla osi %1 zostało zmienione. Czy nowe ustawienia przepustnicy mają zostać uwzględnione we wszystkich zestawieniach? SetJoystick Set %1: %2 Zestawienie %1: %2 Set %1 Zestawienie %1 SetNamesDialog Set Name Settings Ustawienia nazw zestawień Set 1 Zestawienie 1 Set 2 Zestawienie 2 Set 3 Zestawienie 3 Set 4 Zestawienie 4 Set 5 Zestawienie 5 Set 6 Zestawienie 6 Set 7 Zestawienie 7 Set 8 Zestawienie 8 Name Nazwa SimpleKeyGrabberButton Mouse Mysz SpringModeRegionPreview Spring Mode Preview Podgląd trybu tekstowego UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Nie można odnaleźć poprawnego pliku dla uinput. Sprawdź, czy moduł uinput został odpowiednio wczytany. Przykładowe polecenie sprawdzające: lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Nie można otworzyć pliku dla uinput. Sprawdź uprawnienia zapisu dla pliku Using uinput device file %1 Zastosowanie pliku %1 dla uinput UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z Esc Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock CapsLock ; ; ' ' Enter Enter Shift_L Shift_L , , . . / / Ctrl_L Ctrl_L Super_L Super_L Alt_L Alt_L Space Space Alt_R Alt_R Menu Menu Ctrl_R Ctrl_R Shift_R Shift_R Up Góra Left Lewo Down Dół Right Prawo PrtSc PrtSc Ins Ins Del Del Home Home End End PgUp PgUp PgDn PgDn NumLock NumLock * * + + KP_Enter KP_Enter KP_1 KP_1 KP_2 KP_2 KP_3 KP_3 KP_4 KP_4 KP_5 KP_5 KP_6 KP_6 KP_7 KP_7 KP_8 KP_8 KP_9 KP_9 KP_0 KP_0 SCLK SCLK Pause Pause Super_R Super_R Mute Mute VolDn VolDn VolUp VolUp Play Play Stop Stop Prev Prev Next Next [NO KEY] [BRAK] UnixWindowInfoDialog Captured Window Properties Uchwycone właściwości okna Information About Window Informacje o oknie Class: Klasa: TextLabel Etykieta Title: Tytuł: Path: Ścieżka: Match By Properties Dopasowanie według właściwości Class Klasa Title Tytuł Path Ścieżka VDPad VDPad VDPad VirtualKeyPushButton Space Space Tab Tab Shift (L) Shift (L) Shift (R) Shift(R) Ctrl (L) Ctrl (L) Ctrl (R) Ctrl (R) Alt (L) Alt (L) Alt (R) Alt (R) Alt Gr Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP PGUP DEL DEL PGDN PGDN 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK NUM LK * * + + Enter Enter Del Del < < : : Super (L) Super (L) Menu Menu Up Góra Down Dół Left Lewo Right Prawo VirtualKeyboardMouseWidget Keyboard Klawiatura Mouse Mysz Left Mouse Myszki Lewo Up Mouse Myszki Góra Left Button Mouse Myszki Lewy przycisk Middle Button Mouse Myszki Środkowy przycisk Right Button Mouse Myszki Prawy przycisk Wheel Up Mouse Rolką w górę Wheel Left Mouse Rolką w lewo Wheel Right Mouse Rolką w prawo Wheel Down Mouse Rolką w dół Down Mouse Myszki Dół Right Mouse Myszki Prawo Button 4 Mouse Przycisk 4 Mouse 8 Mouse Przycisk myszy 8 Button 5 Mouse Przycisk 5 Mouse 9 Mouse Przycisk myszy 9 Mouse Settings Ustawienia myszki NONE BRAK [NO KEY] [BRAK] Last button Ostatni przycisk Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Sloty dla wprowadzonych przycisków nie mogły zostać usunięte, ponieważ żadne dane nie zostały dotychczas wprowadzone z układu klawiatury do układu gamepad'a. Stwórz mapowanie co najmniej jednego przycisku dla gamepad'a Others Inne Applications Aplikacje Browser Back Browser Back Browser Favorites Browser Favorites Browser Forward Browser Forward Browser Home Browser Home Browser Refresh Browser Refresh Browser Search Browser Search Browser Stop Browser Stop Calc Calc Email Email F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media Media Media Next Media Next Media Play Media Play Media Previous Media Previous Media Stop Media Stop Search Search Volume Down Volume Down Volume Mute Volume Mute Volume Up Volume Up VirtualMousePushButton INVALID NIEPRAWIDŁOWY WinAppProfileTimerDialog Capture Application Zrzut aplikacji After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Jeśli wybrałeś "Zrzut aplikacji", kliknij na okno dowolnej otwartej aplikacji, aby twój profil został z nim powiązany. Otwarta aplikacja zostanie uchwycona po podanym czasie. Timer: Licznik: Seconds Sekund Cancel Anuluj WinExtras [NO KEY] [BRAK] AntiMicroX Profile Profil AntiMicroX X11Extras ESC ESC Tab Tab Space Space DEL DEL Return Return KP_Enter KP_Enter Backspace Backspace Alt Gr Alt Gr xinput extension was not found. No mouse acceleration changes will occur. rozszerzenie xinput nie zostało znalezione. Zmiany przy akceleracji myszki nie zostaną uwzględnione. xinput version must be at least 2.0. No mouse acceleration changes will occur. wersja rozszerzenia xinput nie może być mniejsza od 2.0. Zmiany przy akceleracji myszki nie zostaną uwzględnione. Virtual pointer found with id=%1. Został znaleziony wirtualny wskaźnik dla urządzenia o id=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 PtrFeedbackClass nie została znaleziona dla wskażnika wirtualnego. Zmiany akceleracji myszki nie zostaną uwzględnione dla urządzenia o id=%1 Changing mouse acceleration for device with id=%1 Zmiana akceleracji myszki dla urządzenia o numerze id=%1 XMLConfigReader Could not write updated profile XML to file %1. Zapis zaktualizowanego profilu XML do pliku %1 jest niemożliwy. XMLConfigWriter Could not write to profile at %1. Zapis do profilu %1 był niemożliwy. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. Aplikacja z nakładką graficzną do importowania ustawień przycisków klawiatury i myszki do gamepad'a. Program jest szczególnie przydatny dla gier bez wbudowanego wsparcia dla gamepad'ów. main Launch program in system tray only. Uruchom program w tacce systemowej. Launch program with the tray menu disabled Uruchom program bez udziału tacki systemowej Launch program without the main window displayed Uruchom program pomijając wyświetlenie głównego okna Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers Uruchom program ze wskazanym plikiem konfiguracyjnym jako domyślnym dla wskazanych kontrolerów location lokalizacja Apply configuration file to a specific controller. Value can be a controller index, name, or GUID Wybierz plik konfiguracyjny dla wskazanego kontrolera. Wartością może być indeks kontrolera, nazwa lub GUID value wartość Unload currently enabled profile(s) Odłącz aktualnie odblokowany profil(e) value(s) wartość(i) Start joysticks on a specific set. Value can be a controller index, name, or GUID Uruchom joystick(i) z numerem ustawienia. Wartością może być indeks kontrolera, nazwa lub GUID number value numer wartość Launch program as a daemon. Use only on Linux. Launch program as a daemon Uruchom program jako usługę w tle. Wyłącznie pod Linux. Enable logging Odblokuj generowanie logów log-type typ-logów Choose a file for logs writing Wybierz plik dla zapisywania logów filename nazwaPliku Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. Choose between using XTest support and uinput support for event generation. Default: xtest. Wybierz między wsparciem xtest a wsparciem uinput dla generatora zdarzeń. Do zastosowania wyłącznie w przypadku wykrywania przez program xtest oraz uinput pod Linux oraz w przypadku wykrywania opcji vmulti pod Windows. Domyślnie: xtest. event-generation-type typ-generatora-zdarzeń Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Wyświetl informacje o wykrytych joystick'ach przez bibliotekę SDL. Zastosowanie wyłącznie z dostępną i odblokowaną biblioteką sdl. Wyświetlane informacje dotyczą indeksu kontrolerów, nazw i GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_pt.ts000066400000000000000000013631111377703515000275210ustar00rootroot00000000000000 AboutDialog About sobre Version versión <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Copyright: 2013 - 2016 {2013 ?} {2013 ?} {2020?} Copyright: 2013 - 2018 Copyright: 2013 - 2016 {2013 ?} {2013 ?} {2018?} Info info Changelog Changelog Copyright: 2013 - 2016 Copyright: 2013 - 2016 {2013 ?} Since December 30, 2012, I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Once the Steam controller is finally released to the public, the need for this program might not exist anymore. Just based on the concept of the controller alone, the Steam controller would have so many advantages over using a program like this to provide KB+M emulation. Desde el 30 de diciembre de 2012, he estado trabajando en AntimicroX en mi tiempo libre. Lo que originalmente comenzó como un fork de QJoyPad y una manera de aprender programación orientada a eventos adecuado se ha convertido en algo mucho más grande de lo que originalmente pretendía. Aunque he pasado mucho tiempo aprendiendo nuevas técnicas, saber más sobre el dominio de la emulación KB + M, y pasar las noches de viernes golpeando la cabeza contra mi teclado, ha sido una experiencia divertida y enriquecedora en general. La necesidad de este programa vino de mí usando programas similares en Windows para jugar varios juegos que no proporcionan soporte para el controlador nativo. Aunque existían algunas alternativas en Linux, no había realmente nada de lo que me pareció que era lo suficientemente bueno en términos de funcionalidad o controles en el juego con el fin de disfrutar realmente de juegos que quería jugar con el uso de la emulación KB + M. QJoyPad fue el programa principal que había utilizado en el pasado a pesar de que había envejecido mucho y no proporcionar alguna funcionalidad básica que yo pensaba que era esencial. El proyecto estaba muerto, ya que no había sido actualizado en varios años, así que decidí hacer mi propia. Desde entonces, he tratado de averiguar lo que los otros programas hacen la derecha y luego mejorarlo. También he descubierto algunos truquitos en el camino y he aprendido más acerca de cómo los controles del gamepad nativas se implementan en algunos juegos de lo que nunca realmente quería saber. Aunque sin duda hay áreas en las que este programa podría mejorar, me parece que este programa ofrece la mejor experiencia de control en el juego para jugar más, y algunos nuevos, juegos que no proporcionan soporte para el controlador nativo. Una vez que el control de Steam finalmente se lanzó al público, la necesidad de este programa no podría existir más. Sólo se basa en el concepto del controlador solamete, el controlador de Steam tendría tantas ventajas sobre el uso de un programa como este para proporcionar la emulación KB + M. Credits Créditos AntiMicroX AntiMicroX <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Travis Nickles &lt;nickles.travis@gmail.com&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"><br /></span>Zerro Alvein</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">aybe</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx - Chinese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">phob - German</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tou omiya - Japanese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">burunduk - Ukrainian</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Travis Nickles &lt;nickles.travis@gmail.com&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"><br /></span>Zerro Alvein</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">aybe</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx - Chinese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Español</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">phob - German</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tou omiya - Japanese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">burunduk - Ukrainian</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> About Development Sobre el desenvolvimiento License Licencia Program Version %1 Versión del programa %1 Program Compiled on %1 at %2 Programa compilado en %1 a %2 Built Against SDL %1 Running With SDL %1 Using Qt %1 Usando Qt %1 Using Event Handler: %1 Usando Gestor de Eventos: %1 AddEditAutoProfileDialog Auto Profile Dialog Profile: Perfil: Pro&file: Browse Navegar Window: ventana: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties &Class: T&itle: Class: Clase: Title: Título: set partial title Application: Aplicación: Select seleccione De&vices: Devices: Dispositivos: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller A different profile is already selected as the default for this device. Current (%1) Open Config Abrir Config Select Program Seleccionar Programa Programs (*.exe) Programas (*.exe) Please use the main default profile selection. Por favor, utilice la selección principal perfil predeterminado. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Por favor, seleccione una ventana utilizando el ratón. Presione Escape si desea cancelar. Capture Application Window Could not obtain information for the selected window. Application Capture Failed Profile file path is invalid. La ruta de archivo de perfil es invalido. No window matching property was specified. Program path is invalid or not executable. File is not an .exe file. El Archivo no es un .exe. No window matching property was selected. AdvanceButtonDialog Advanced Avanzado Assignments Asignamientos Toggle Alternar Turbo Turbo Set Selector Selector de Set Blank or KB/M Vacio o KB/M Hold Mantener Pause Pausa Cycle Ciclo Distance Distancia Insert Inserir Delete Borrar Clear All Limpiar todo Time: Tiempo: 0.01s 0.01s 0s 0s Insert a pause that occurs in between key presses. Insertar una pausa que se produce en la introducción de la tecla. Release Soltar Insert a new blank slot. Inserte una nueva ranura en blanco. Join Split Delete a slot. Borrar ranura. Clear all currently assigned slots. Limpiar todos los slots asignados actualmente. Specify the duration of an inserted Pause or Hold slot. Especificar la duración de una ranura de pausa o de retención insertado. 0m 0m &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Especificar el rango más allá de una zona muerta eje en el que una secuencia de acciones se ejecutará. Distance: Distancia: % % Mouse Mod Raton Mod Press Time Tiempo de presionado Delay Retraso Execute Ejecutar Load Cargar Set Change Definir Cambio Text Entry Entrada de texto Placeholder marcador de posición 0 0 Mouse Speed Mod: Velovidad de Ratón Mod: Set the percentage that mouse speeds will be modified by. Establecer el porcentaje que las velocidades de ratón serán modificadas por. Auto Reset Cycle After Auto Resetear Ciclos Después seconds segundos Executable: ... ... Arguments: Enabled Habilitado Mode: Modo: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Normal:. Pulse y suelte repetidamente un botón por la tasa elegido </p><p> Gradiente: Modificar el retraso y liberación de un botón de acuerdo con la distancia de un eje se ha movido. La tasa seguirá siendo el mismo </p><p>Pulso:. Modifica como muchas veces un botón es presionado y liberado por segundo. El retraso botón seguirá siendo el mismo.</p></body></html> Normal Normal Gradient Gradiente Pulse Pulso Delay: Retraso: 0.10s 0.10s Rate: Taza: 10.0/s 10.0/s Disabled Inhabilitado Select Set 1 One Way Seleccione Set 1 Unidireccional Select Set 1 Two Way Seleccione Set 1 Bidireccional Select Set 1 While Held Seleccione Set 1 Mientras se Mantiene Select Set 2 One Way Seleccionar Set 2 Unidireccional Select Set 2 Two Way Seleccionar Set 2 Bidireccional Select Set 2 While Held Seleccionar Set 2 Mientras se Mantiene Select Set 3 One Way Seleccionar Set 3 Unidireccional Select Set 3 Two Way Seleccionar Set 3 Bidireccional Select Set 3 While Held Seleccionar Set 3 Mientras se Mantiene Select Set 4 One Way Seleccionar Set 4 Unidireccional Select Set 4 Two Way Seleccionar Set 4 Bidireccional Select Set 4 While Held Seleccionar Set 4 Mientras se Mantiene Select Set 5 One Way Seleccionar Set 5 Unidireccional Select Set 5 Two Way Seleccionar Set 5 Bidireccional Select Set 5 While Held Seleccionar Set 5 Mientras se Mantiene Select Set 6 One Way Seleccionar Set 6 Unidireccional Select Set 6 Two Way Seleccionar Set 6 Bidireccional Select Set 6 While Held Seleccionar Set 6 Mientras se Mantiene Select Set 7 One Way Seleccionar Set 7 Unidireccional Select Set 7 Two Way Seleccionar Set 7 Bidireccional Select Set 7 While Held Seleccionar Set 7 Mientras se Mantiene Select Set 8 One Way Seleccionar Set 8 Unidireccional Select Set 8 Two Way Seleccionar Set 8 Bidireccional Select Set 8 While Held Seleccionar Set 8 Mientras se Mantiene [NO KEY] [SIN TECLA] sec. Seg. /sec. /seg. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Set %1 Select Set %1 Seleccionar Set %1 One Way Unidireccional Two Way Bidireccional While Held Mientras se Mantiene Choose Executable Escojer Ejecutable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Las ranuras mas allá de un Ciclo de acción podrán ser ejecutados en la proxima vez que se presione el botón. ciclos múltiples se pueden agregar con el fin de crear particiones en una secuencia. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Retrasa el momento en que la siguiente ranura es activado por el tiempo especificado. Las ranuras activadas antes de que el retraso se mantendrá activa una vez transcurrido el tiempo de retardo. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Distancia acción especifica que las ranuras después sólo se ejecutan cuando un eje se mueve de un cierto rango más allá de la zona muerta designada. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Inserte una acción de retención. Las ranuras después de la acción sólo se ejecutarán si el botón se mantiene más allá del intervalo especificado. Chose a profile to load when this slot is activated. Elija un perfil para cargar cuando se activa esta ranura. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. El Mod de acción del ratón va a modificar todos los ajustes de velocidad del ratón en un porcentaje especificado, mientras que la acción se está procesando. Esto puede ser útil para ralentizar el ratón para francotiradores. Specify the time that keys past this slot should be held down. Especificar el tiempo que las teclas pasan en esta ranura deben mantenerse presionadas. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Insertar una acción de liberación. Las ranuras después de la acción sólo se ejecutarán después de la liberación del botón si este fue presionado más allá del intervalo especificado. Change to selected set once slot is activated. Cambiar al set seleccionado una vez que se activa la ranura. Full string will be typed when a slot is activated. La cadena completa se tecleará cuando se activa una ranura. Execute program when slot is activated. Ejecutar el programa cuando se activa la ranura. Choose Profile Elegir Perfil Config Files (*.amgp *.xml) Archivos de Config (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Asignamiento de Palanca/Pad Sticks Palancas DPads DPads Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Mando %2) Stick 1 Palanca 1 Enabled Habilitar Assign Asignar X Axis: Eje X: Y Axis: Eje Y: Stick 2 Palanca 2 Number of Physical DPads: %1 Numero de DPads físicos: %1 Virtual DPad 1 DPad 1 Virtual Up: Arriba: Down: Abajo: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Nota: Esta ventana es para la retrocompatibilidad con los perfiles realizados antes AntimicroX 2.0. Desde la versión 2.0, se prefiere el uso de la ventana de juego Mapeo controlador. Left: Izquierda: Right: Derecha: Axis %1 Ejes %1 Axis %1 - Ejes %1 - Axis %1 + Ejes %1 + Button %1 Botón %1 Move stick 1 along the X axis Mueva la palanca 1 a lo largo del eje X Move stick 1 along the Y axis Mueva la palanca 1 a lo largo del eje Y Move stick 2 along the X axis Mueva la palanca 2 a lo largo del eje X Move stick 2 along the Y axis Mueva la palanca 2 a lo largo del eje Y Press a button or move an axis Presione un botón o mueva un eje AxisEditDialog Axis Ejes Mouse (Horizontal) Ratón (Horizontal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Vertical) Ratón (Vertical) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Arrows: Up | Down Direccionales: Arriba | Abajo Arrows: Left | Right Direccionales: Izquierda | Derecha Keys: W | S Teclas: W | S Keys: A | D Teclas: A | D NumPad: KP_8 | KP_2 Teclado Num: 8 | 2 NumPad: KP_4 | KP_6 Teclado Num: 4 | 6 None Nada Set the value to use as the limit for an axis. Useful for a worn out analog stick. Establecer el valor a utilizar como límite para un eje. Útil para una palancas analógicas desgastadas. Negative Half Throttle Mitad de Acelerador Negativo Positive Half Throttle Mitad de Acelerador Positivo Name: Nombre: Specify the name of an axis. Especificar un nombre para un eje. Mouse Settings Configuraciones de Ratón Set the value of the dead zone for an axis. Establecer el valor de la zona muerta para un eje. Presets: Presets: Dead Zone: Zona Muerta: Max Zone: Zona Maxima: [NO KEY] [SIN TECLA] Throttle setting that determines the behavior of how to interpret an axis hold or release. Ajuste del acelerador la que determina el comportamiento de la forma de interpretar un eje de retención o liberación. Negative Throttle Acelerador Negativo Normal Normal Positive Throttle Acelerador Positivo Current Value: Valor Actual: Set Set %1 Left Mouse Button Botón Izquierdo del Ratón Right Mouse Button Botón Derecho del Ratón ButtonEditDialog Dialog Dialogo To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Para realizar una nueva asignación, pulse cualquier tecla del teclado o haga clic en un botón en el teclado o en la pestaña ratón Placeholder marcador de posición Toggle Alternar Enables a key press or release to only occur when a controller button is pressed. Habilita la pulsación de una tecla o la liberación que sólo ocurren cuando se pulsa un botón del mando. Enables rapid key presses and releases. Turbo controller. Permite a las pulsaciones de teclas rápidas y liberaciones. Controlador Turbo. Turbo Turbo Current: Presente: Last keyboard/mouse button: Slots Ranuras Na&me: No&mbre: Specify the name of a button. Especifique el nombre de un botón. Action: Acción: Specify the action that will be performed in game while this button is being used. Especificar la acción que se llevará a cabo en juego, mientras se está utilizando este botón. Advanced Avanzado Set Set Set %1 Set %1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [SIN TECLA] Calibration Form Start calibration Sticks: Reset settings Cancel Cancelar Save Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 Ejes %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: Clase: TextLabel Title: Titulo: Path: Camino: Match By Properties Class Clase Title Titulo Path Camino Full Path File Name CommandLineUtility Profile location %1 is not an XML file. Localización de Perfil %1 no es un archivo XML válido. Profile location %1 does not exist. Localización de Perfil %1 No existe. An invalid set number '%1' was specified. Un numero de Set inválido '%1' fué especificado. Controller identifier '%s'' is not a valid value. Controlador idendificado '%s'' no es un valor válido (valga la redundancia). No display string was specified. Ninguna cadena de exibición fué especificado. DPadContextMenu Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad Teclado Num None Nada Standard Estándar Eight Way Ocho Vías 4 Way Cardinal 4 Vias Cardinal 4 Way Diagonal 4 Vias Diagonal Mouse Settings Configuracion de Ratón DPadEditDialog Dialog Dialogo Presets: Presets: Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad Teclado Num None Nada Dpad Mode: Modo Dpad: &Name: &Nombre: 4 Way Cardinal 4 Vias Cardinal 4 Way Diagonal 4 Vias Diagonal DPad Delay: Retraso de Dpad: Time lapsed before a direction change is taken into effect. Tiempo transcurrido antes de un cambio de dirección se tenga en efecto. s s Specify the name of a dpad. Especificar un nombre para Dpad. Mouse Settings Configuracion de Ratón Standard Estándar Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Estándar: Dpad de 8 regiones con dos botones de dirección activa cuando el dpad está en una región diagonal. Ocho manera: Dpad de 8 regiones con cada dirección que tiene su botón dedicado propio. Sólo un botón está siempre activo en en el momento. Útil para los juegos rougelike. 4 Way cardenal: Dpad de 4 regiones con las regiones correspondientes a los puntos cardinales de la DPAD. Útil para los menús. 4 Way Diagonal: Dpad de 4 regiones con cada región que corresponde a una zona de diagonal. Eight Way Ocho Vías Set Set Set %1 Set %1 EditAllDefaultAutoProfileDialog Default Profile Perfil por Defecto Profile: Perfil: Browse Navegar Open Config Abrir Config Profile file path is invalid. La ruta de archivo de perfil es invalido. ExtraProfileSettingsDialog Extra Profile Settings Configuraciones Extra de Perfil Key Press Time: Tiempo de presionado de Tecla: 0.00 ms 0.00 ms Profile Name: Nombre del Perfil: s s GameController Game Controller Controlador de juego GameControllerDPad DPad DPad GameControllerMappingDialog Game Controller Mapping Mapeo de Controles de Juego <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A B X Y Back Start Guide Left Shoulder Right Shoulder Left Stick Click Right Stick Click Left Stick X Left Stick Y Right Stick X Right Stick Y Left Trigger Right Trigger DPad Up DPad Left DPad Down DPad Right Mapping SDL 2 Game Controller Mapping String Last Axis Event: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Mapeo de Controles de Juego (%1) (#%2) Discard Controller Mapping? ¿Descartar Mapeo de Controlador? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. ¿Descartar Mapeo para este controlador? Si lo descarta, el controlador podrá revertirse a un mando una vez que se actualicen todos los mandos. GameControllerSet Back Guide Start LS Click RS Click L Shoulder R Shoulder L Trigger R Trigger GameControllerTrigger Trigger Gatillo JoyAxis Axis Ejes JoyAxisButton Negative Negativo Positive Positivo Unknown Desconocido Button Botón JoyAxisContextMenu Mouse (Horizontal) Ratón (Horizontal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Vertical) Ratón (Vertical) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Arrows: Up | Down Direccionales: Arriba | Abajo Arrows: Left | Right Direccionales: Izquierda | Derecha Keys: W | S Teclas: W | S Keys: A | D Teclas: A | D NumPad: KP_8 | KP_2 Teclado Num: 8 | 2 NumPad: KP_4 | KP_6 Teclado Num: 4 | 6 None Nada Mouse Settings Configuracion de Ratón Left Mouse Button Botón Izquierdo del Ratón Right Mouse Button Botón Derecho del Ratón JoyButton Processing turbo for #%1 - %2 Procesando turbo para #%1 - %2 Finishing turbo for button #%1 - %2 Finalizando turbo para botón #%1 - %2 Processing press for button #%1 - %2 Procesando de presionado para botón #%1 - %2 Processing release for button #%1 - %2 Procesando de liberacion de botón #%1 - %2 Distance change for button #%1 - %2 Distancia de cambio para botón #%1 - %2 Button Botón [NO KEY] [SIN TECLA] [Set %1 1W] [Set %1 1W] [Set %1 2W] [Set %1 2W] [Set %1 WH] [Set %1 WH] JoyButtonContextMenu Toggle Alternar Turbo Turbo Clear Limpiar Set Select Seleccionar Set Disabled Inhabilitado Set %1 Set %1 Set %1 1W Set %1 1W Set %1 2W Set %1 2W Set %1 WH Set %1 WH JoyButtonSlot Mouse Ratón Up Arriba Down Abajo Left Izquierda Right Derecha LB BI MB BM RB BD B4 B4 B5 B5 Pause Pausa Hold Mantener Cycle Ciclo Distance Distancia Release Soltar Mouse Mod Raton Mod Press Time Tiempo de presionado Delay Retraso Load %1 Cargar %1 Set Change %1 Cambiar Set %1 [Text] %1 [Texto] %1 [Exec] %1 [Ejec] %1 [NO KEY] [SIN TECLA] JoyControlStick Stick Palanca JoyControlStickButton Up Arriba Down Abajo Left Izquierda Right Derecha Button Botón JoyControlStickContextMenu Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad Teclado Num None Nada Standard Estándar Eight Way Ocho Vías 4 Way Cardinal 4 Vias Cardinal 4 Way Diagonal 4 Vias Diagonal Mouse Settings Configuracion de Ratón JoyControlStickEditDialog Dialog X: 0 Y: Distance: Presets: Presets: Mouse (Normal) Ratón (Normal) Mouse (Inverted Horizontal) Ratón (Horizontal Invertido) Mouse (Inverted Vertical) Ratón (Vertical Invertido) Mouse (Inverted Horizontal + Vertical) Ratón (Horizontal+Vertical Invertido) Arrows Direccionales Keys: W | A | S | D Teclas: W | A | S | D NumPad None Stick Mode: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4 Way Diagonal Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. Square Stick: Percentage to modify a square stick coordinates to confine values to a circle % Stick Delay: Time lapsed before a direction change is taken into effect. s Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Na&me: Name: Specify the name of an analog stick. Mouse Settings Standard Bearing: % Safe Zone: Eight Way Dead Zone: Max Zone: Diagonal Range: Set Set %1 JoyControlStickModifierButton Modifier JoyDPad DPad JoyDPadButton Up Down Left Right Button JoyTabWidget <New> Remove Remove configuration from recent list. Load Cargar Load configuration file. Save Save changes to configuration file. Save As Save changes to a new configuration file. Sets Copy from Set Settings Configuraciones Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Stick/Pad Assign Asignación de Palanca/Pad Controller Mapping Quick Set Configuración rápida Names Toggle button name displaying. Pref Change global profile settings. Reset Revert changes to the configuration. Reload configuration file. Open Config Abrir Config Config Files (*.amgp *.xml) Archivos de Config (*.amgp *.xml) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Sticks Palancas DPads DPads No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Set %1: %2 Set %1: %2 Set %1 Set %1 Copy Set Assignments Are you sure you want to copy the assignments and device properties from %1? Save Config Set Set Joystick Joystick JoystickStatusWindow Properties Propiedades Details Detalles Name: Nombre: %1 %1 Number: Numero: Axes: Ejes: Buttons: Botones: Hats: Hats: Battery: Unknown Desconocido GUID: GUID: Game Controller: Controlador de Juego: Axes Ejes Buttons Botones Hats Hats %1 (#%2) Properties %1 (#%2) Propiedades Axis %1 Ejes %1 Hat %1 Hat %1 No No Yes Si MainSettingsDialog Edit Settings Editar Configuraciones General General Controller Mappings Mapeo de controles Language Lenguaje Auto Profile Auto Perfil Mouse Ratón Advanced Avanzado Pro&file Directory: <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Especificar el directorio por defecto que el programa debe utilizar en los diálogos de archivo cuando se carga un perfil o guardar un nuevo perfil.</p></body></html> Recent Profile Count: Contaje de Perfiles Recientes: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Número de perfiles que se puede colocar en la lista de perfil reciente. 0 dará lugar a que el programa no cumplir un límite en el número de perfiles que se muestran.</p></body></html> Gamepad Poll Rate: Taza de Sondeo de Mando: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Cambiar la velocidad de sondeo que el programa utiliza para descubrir nuevos eventos de mandos. El valor predeterminado es de 10 ms. La reducción del valor de velocidad de sondeo podría causar que la aplicación usar más energía de la CPU así que por favor probar la configuración que utilice antes de usar AntimicroX desatendida. Hide main window when the main window close button is clicked instead of quitting the program. Ocultar ventana principal cuando el botón de la ventana principal es estrecha se hace clic en lugar de salir del programa. Close To Tray Cerrar para la bandeja del sistema Have Windows start AntiMicroX at system startup. Hacer que Windows inicie AntimicroX junto con el sistema. Launch At Windows Startup Iniciar junto con Windows Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Mostrar perfiles más recientes de todos los mandos como una única lista en el menú de la bandeja. predeterminados a la utilización de los submenús. Single Profile List in Tray Lista única de perfiles en la bandeja de sistema Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Hacer que el programa minimize la barra de tareas. Por defecto, el programa se minimiza en el sistema la bandeja si está disponible. Minimize to Taskbar Minimizar para la barra de tareas This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Esta opción hará que el programa para ocultar todos los botones que no tienen ranuras asignadas. La ventana de diálogo de configuración rápida tendrá que ser utilizado para que aparezca el diálogo de edición para los botones del mando. Hide Empty Buttons Ocultar Botones Vacíos When the program is launched, open the last known profile that was opened during the previous session. Cuando el programa esté en marcha, abrir el último perfil conocido que se abrió durante la sesión anterior. Auto Load Last Opened Profile Auto Cargar el ultimo perfil abierto Only show the system tray icon when the program first launches. Solamente mostrar el icono en la bandeja de sistema cuando el programa inicie por primera vez. Launch in Tray Lanzar en la bandeja del sistema Associate .amgp files with AntiMicroX in Windows Explorer. Asociar archivos .amgp con AntiMicroX en Windows Explorer. Associate Profiles Asociar Perfiles Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Repetición de Tecla Active keys will be repeatedly pressed when this option is enabled. Las teclas activadas serán presionadas repetidamente cuando esta opción esté activada. Enable Habilitar Specifies how much time should elapse before key repeating begins. Especifica cuánto tiempo debe transcurrir antes de repetión de tecla comienza. Specifies how many times key presses will be performed per seconds. Especifica cuántas veces se llevarán a cabo las pulsaciones de teclas por segundo. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntimicroX ha sido traducido a muchos idiomas diferentes por los contribuyentes. Por defecto, el programa elegirá una traducción apropiada basada en la configuración regional de su sistema. Sin embargo, puede hacer que la carga AntimicroX una traducción diferente en función del idioma que elija en la lista siguiente.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Nada Error Warning Info info Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset French Francés Japanese Japonés Russian Ruso Serbian Serbio Simplified Chinese Chino Simplificado Ukrainian Ucraniano Class Clase Title Titulo Program Programa Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Deshabilitar la configuración de Windows "mejorada precisión del puntero" mientras AntimicroX se está ejecutando. La desactivación "mejorada precisión del puntero" permitirá el movimiento del ratón dentro de AntimicroX a ser más preciso. Disable Enhance Pointer Precision Desactivar la precisión del puntero mejorado Smoothing suavizado Histor&y Size: Tamaño del &Historial: Weight &Modifier: &Modificador de peso: Refresh Rate: Taza de Actualizacion: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. La frecuencia de actualización es la cantidad de tiempo que transcurrirá entre los eventos del ratón. Por favor tenga cuidado cuando la edición de este ajuste ya que esto haría que el programa utilice más potencia de CPU. Un valor demasiado bajo puede causar inestabilidad del sistema. Por favor, probar la configuración antes de usar sin vigilancia. Spring Spring Screen: Pantalla: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Utilizar la pantalla especificada para el modo spring. En Linux, el por defecto es el uso de la pantalla principal. En Windows, el valor por defecto es utilizar todas las pantallas disponibles. Accel Numerator: Numerador de Aceleración: 0 0 Accel Denominator: Denominador de Aceleración: Accel Threshold: Límite de Aceleración: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Si los valores de aceleración para el ratón virtual han sido cambiados por un proceso diferente, particularmente cuando se cierra un juego antiguo, entonces es posible que desee restablecer la aceleración Los valores utilizados por el ratón virtual. Reset Acceleration Resetear Aceleración Delay: Retraso: Profi&le Directory: Directorio de Perfi&l: ms ms Rate: Taza: times/s tiempo/s Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. A continuación se muestra una lista de las asignaciones personalizados que se han guardado. Puede usar la siguiente tabla para eliminar las asignaciones o tienen asignaciones temporalmente deshabilitados. También puede desactivar las asignaciones que se incluyen con SDL; sólo tiene que insertar una nueva fila con el GUID de la palanca de mando correspondiente y vaya desactivar. Los ajustes no tendrán efecto hasta que actualizar todos los mandos o desenchufar el mando en particular. GUID GUID Mapping String Cadena de Mapeo Disable? Inhabilitar? Delete Borrar Insert Insertar Default Por Defecto Brazilian Portuguese Portugués de Brasil English Inglés German Alemán Active Activo Devices: Dispositivos: All Todo Device Dispositivo Profile Perfil Default? Por Defecto? Add Agregar Edit Editar Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Además, los usuarios de Windows que deseen utilizar un valor bajo,pueden tambien marcarl "Desactivar el puntero de precisión" en caso de que no haya desactivado la opción en Windows. Select Default Profile Directory Seleccionar el Directorio de Perfil por defecto Are you sure you want to delete the profile? Está seguro que quiere borrar el perfil? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [SIN TECLA] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Ningún Mando fue encontrado Por favor conecte un Mando y elija la opción "Actualizar Mandos" en el menu principal If events are not seen by a game, please click here to run this application as the Adminstrator. Si los eventos no son vistos por un juego, por favor haga clic aquí para ejecutar esta aplicación como administrador. If events are not seen by a game, please click here to run this application as Administrator. &App &App &Options &Opciones &Help A&yuda He&lp &Quit S&alir Ctrl+Q Ctrl+Q &Update Joysticks Act&ualizar Mandos Ctrl+U Ctrl+U &Hide O&cultar Ctrl+H Ctrl+H &About So&bre Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt Sobre Qt Properties Propiedades Key Checker Verificador de Teclas Home Page Home Page GitHub Page Página GitHub Game Controller Mapping Mapeo de Controles de Juego Settings Configuraciones Stick/Pad Assign Asignación de Palanca/Pad Wiki Wiki Could not find a proper controller identifier. Exiting. No se pudo encontrar un identificador de controlador apropiado.Saliendo. (%1) (%1) Open File Abrir Archivo %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore &Restaurar Calibration couldn't be opened You must connect at least one controller to open the window Run as Administrator? ¿Ejecutar como Administrador? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. ¿Estás seguro de que desea ejecutar este programa como Adminstrator? Algunos juegos se ejecutan como administrador lo que hará que los eventos generados por AntimicroX para no ser utilizado por aquellos juegos a menos AntimicroX también se ejecuta como el Adminstrator. Esto se debe a problemas de permisos causadas por las opciones de Control de cuentas de usuario (UAC) en Windows Vista y versiones posteriores. Failed to elevate program Fallo al elevar el programa Failed to restart this program as the Administrator Fallo al reiniciar este programa como administrador Could not find controller. Exiting. No se pudo encontrar un controlador. Saliendo. MouseAxisSettingsDialog Mouse Settings - Set %1 MouseButtonSettingsDialog Mouse Settings - Set %1 MouseControlStickSettingsDialog Mouse Settings Set %1 MouseDPadSettingsDialog Mouse Settings Set %1 MouseSettingsDialog Mouse Settings Configuracion de Ratón Mouse Mode: Modo Ratón: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Cursor Spring Spring Acceleration: Aceleración: Enhanced Precision Puntero Mejorado Linear Quadratic Cubic Quadratic Extreme Power Function Easing Quadratic Easing Cubic Mouse Speed Settings Enable to change the horizontal and vertical speed boxes at the same time. Change Together Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: Horizontal Speed: Velocidad Horizontal: 1 = 20 pps Vertical Speed: Velocidad Vertical: Wheel Hori. Speed: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: s s Extra Acceleration Aceleración Extra Multiplier: Multiplicador: Highest value to accelerate mouse movement by x Start %: Acceleration begins at this percentage of the base multiplier La aceleración comienza en este porcentaje de la base de multiplicador Min Threshold: Límite Mínimo: Minimum amount of axis travel required for acceleration to begin cantidad mínima de recorrido del eje requerido para la aceleración a comenzar Max Threshold: Límite Máximo: Maximum axis travel before acceleration has reached the multiplier value El recorrido máximo del eje antes de la aceleración ha alcanzado el valor del multiplicador E&xtra Duration: Curve: Curva: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Mouse Status X: 0 (0 pps) Y: 1 = 1 notch(es)/s Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Spring Width: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. %n notch(es)/s %n notch/s %n notches/s ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Cancelar OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Verificador de Teclas <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Presione una tecla del teclado para ver cómo se detecta la tecla por esta aplicación. La ventana mostrará el valor de la tecla del sistema nativo, el valor original dada por Qt (si es el caso), y el valor personalizado utilizado por AntimicroX. </p><p> El valor de la tecla AntimicroX y el valor de tecla Qt generalmente es la misma . AntiMicroX intenta utilizar los valores de las claves definidas en Qt cuando sea posible. Vea la página <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> para una lista de valores definidos por Qt. Si descubre que la tecla no es compatible de forma nativa por este programa, por favor informa del problema al estilo de AntiMicroX <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> para que el programa pueda editarlo para soportarlo directamente. Tal como es, se añade un prefijo personalizado para valores desconocidos por lo que todavía se pueden utilizar; el principal problema es que el perfil ya no será portátil.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Controlador de eventos: Native Key Value: Valor de tecla nativo: 0x00000000 0x00000000 Qt Key Value: Valor QT de Tecla: antimicro Key Value: AntiMicroX Key Value: Valor AntimicroX de Tecla: QObject Menu Menu Pause Pausa Media Media Search Buscar Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Failed to launch daemon Launching daemon Display string "%1" is not valid. Failed to set a signature id for the daemon Failed to change working directory to / Quitting Program # of joysticks found: %1 List Joysticks: --------------- Joystick %1: Index: %1 GUID: %1 UniqueID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Yes No Game Controller: %1 # of Axes: %1 # of Buttons: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Profile location %1 does not exist. Controller identifier is not a valid value. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. No controller was specified. No display string was specified. An invalid event generator was specified. No event generator string was specified. No log file specified. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Por favor, pulse un botón o mueva un eje en %1 (<span style=" font-weight:600;">%2</span>).<br/>una ventana de diálogo aparecerá entonces<br/>permitirá crear una asignación.</p></body></html> Quick Set %1 Configuración rápida %1 SetAxisThrottleDialog Throttle Change The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? La posición del acelerador para el Eje %1 ha sido cambiado ¿Le gustaría distribuir este cambio acelerador para todos los sets? SetJoystick Set %1: %2 Set %1 Set %1 SetNamesDialog Set Name Settings Set 1 Set 1 Set 2 Set 2 Set 3 Set 3 Set 4 Set 4 Set 5 Set 5 Set 6 Set 6 Set 7 Set 7 Set 8 Set 8 Name Nombre SimpleKeyGrabberButton Mouse SpringModeRegionPreview Spring Mode Preview UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device No se pudo abrir archivo de dispositivo uinput Por favor, compruebe que tiene permiso para escribir en el dispositivo Using uinput device file %1 El uso de archivos del dispositivo uinput %1 UInputHelper a b c d e f g h i j k l m n o p q r s s t u v w x y z Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace Tab [ [ ] ] \ \ CapsLock ; ; ' ' Enter Shift_L , , . . / / Ctrl_L Super_L Alt_L Space Alt_R Menu Menu Ctrl_R Shift_R Up Arriba Left Izquierda Down Abajo Right Derecha PrtSc Ins Del Home End PgUp PgDn NumLock * * + + KP_Enter Enter_Num KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9 KP_0 SCLK SCLK Pause Pausa Super_R Mute VolDn VolUp Play Stop Prev Next [NO KEY] [SIN TECLA] UnixWindowInfoDialog Captured Window Properties Information About Window Class: Clase: TextLabel Title: Titulo: Path: Camino: Match By Properties Class Clase Title Titulo Path Camino VDPad VDPad VirtualKeyPushButton Space Espaciador Tab Tabulador Shift (L) Mayus (Izq) Shift (R) Mayus (Der) Ctrl (L) Ctrl (Izq) Ctrl (R) Ctrl (Der) Alt (L) Alt (Izq) Alt (R) Alt (Der) Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP RePag DEL SUPR PGDN AvPag 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK BLOCK NUM * * + + Enter Del E N T E R E N T E R < < : : Super (L) Super (Izq) Menu Menu Up Arriba Down Abajo Left Izquierda Right Derecha VirtualKeyboardMouseWidget Keyboard Teclado Mouse Ratón Mouse Settings Configuraciones de Ratón Left Mouse Ratón Izquierda Up Mouse Ratón Arriba Left Button Mouse Ratón Boton Izquierdo Middle Button Mouse Ratón Boton del Medio Right Button Mouse Ratón Botón Derecho Wheel Up Mouse Ratón Rueda Arriba Wheel Left Mouse Ratón Rueda Izquierda Wheel Right Mouse Ratón Rueda Derecha Wheel Down Mouse Ratón Rueda Abajo Down Mouse Ratón Abajo Right Mouse Ratón Derecha Button 4 Mouse Ratón Botón 4 Mouse 8 Mouse Ratón Ratón 8 Button 5 Mouse Ratón Botón 5 Mouse 9 Mouse Ratón Ratón 9 NONE NADA [NO KEY] [SIN TECLA] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Applications Aplicaciones Browser Back Navegador Atrás Browser Favorites Navegador Favoritos Browser Forward Navegador Adelante Browser Home Navegador Inicio Browser Refresh Navegador Actualizar Browser Search Navegador Busca Browser Stop Navegador Parar Calc Calc Email Email F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 Media Media Media Next Media Próximo Media Play Media Reproduzir Media Previous Media Anterior Media Stop Media Parar Search Buscar Volume Down Volume Bajar Volume Mute Volume Mudo Volume Up Volume Subir VirtualMousePushButton INVALID WinAppProfileTimerDialog Capture Application Solicitación de Captura After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Después de pulsar el botón "Solicitud de captura", por favor, seleccione la ventana de la aplicación que desea tener un perfil asociado. La aplicación activa será capturado después del número de segundos seleccionado. Timer: Temporizador: Seconds Segundos Cancel Cancelar WinExtras [NO KEY] [SIN TECLA] AntiMicroX Profile Perfil AntiMicroX X11Extras ESC ESC Tab Tab Space espaciador DEL SUPR Return ENTER KP_Enter Enter_Num Backspace Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. No se ha encontrado la extensión xinput. no se producirán cambios en la aceleración del ratón. xinput version must be at least 2.0. No mouse acceleration changes will occur. La versión xinput debe ser al menos 2,0. no se producirán cambios en la aceleración del ratón. Virtual pointer found with id=%1. Puntero virtual encontrado con el id=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 PeerFeedback clase no se encontró para el puntero virtual. Ningún cambio en la aceleración del ratón se producirá para el dispositivo con el id=%1 Changing mouse acceleration for device with id=%1 Cambiando la aceleración del ratón para el dispositivo con id=%1 XMLConfigReader Could not write updated profile XML to file %1. XMLConfigWriter Could not write to profile at %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_ru.ts000066400000000000000000013406071377703515000275310ustar00rootroot00000000000000 AboutDialog About О программе Version Версия <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Info Информация Changelog Credits Авторы AntiMicroX About Development License Лицензия Program Version %1 Версия программы %1 Program Compiled on %1 at %2 Программа скомпилирована %1 в %2 Built Against SDL %1 Собрана на SDL %1 Running With SDL %1 Запускается на SDL %1 Using Qt %1 Версия Qt %1 Using Event Handler: %1 AddEditAutoProfileDialog Auto Profile Dialog Окно Авто Профиля Profile: Профиль: Pro&file: Browse Обзор Window: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Кликните по нужному окну приложения чтобы автоматически добавить путь до него в форму. Detect Window Properties &Class: T&itle: set partial title Application: Select Выбор De&vices: Devices: Устройства: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Выберите профиль, который будет автоматически загружаться для выбранного устройства. Выбранный профиль загрузится даже если выбран профиль по-умолчанию. Set as Default for Controller Установить по-умолчанию для этого контроллера A different profile is already selected as the default for this device. Для этого контроллера уже назначен профиль по-умолчанию. Current (%1) Текущий (%1) Open Config Открыть Конфигурацию Select Program Выбрать Программу Please use the main default profile selection. Пожалуйста, используйте основной профиль по-умолчанию. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Capture Application Window Could not obtain information for the selected window. Application Capture Failed Profile file path is invalid. Неверный путь до профиля. No window matching property was specified. Program path is invalid or not executable. Путь до программы содержит ошибку или не может быть выполнен. No window matching property was selected. AdvanceButtonDialog Advanced Продвинутые настройки Assignments Назначения Toggle Переключатель Turbo Турбо Set Selector Установить Селектор Blank or KB/M Hold Удерживать Pause Пауза Cycle Цикл Distance Дистанция Insert Вставить Delete Удалить Clear All Очистить Все Time: Время: 0.01s 0,01 сек 0s 0 сек Insert a pause that occurs in between key presses. Вставить паузу между нажатиями на кнопку. Release Отпускание Insert a new blank slot. Вставить новый пустой слот. Join Split Delete a slot. Удалить слот. Clear all currently assigned slots. Очистить все заполненные слоты. Specify the duration of an inserted Pause or Hold slot. Определяет продолжительность для слотов Пауза и Удерживание. 0m 0 мин &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Определяет диапазон оси для мертвой зоны в котором следует выполнять действия. Distance: Дистанция: % % Mouse Mod Скорость Мыши Press Time Время Нажатия Delay Задержка Execute Load Загрузить Set Change Text Entry Placeholder Заполнитель 0 0 Mouse Speed Mod: Модификатор Скорости Мыши: Set the percentage that mouse speeds will be modified by. Определяет в процентах на сколько должна быть изменена скорость мыши. Auto Reset Cycle After Автоматически сбросить цикл после seconds секунд Executable: ... Arguments: Enabled Включено Mode: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Нормально Gradient Pulse Delay: Задержка: 0.10s 0,10 сек Rate: Частота: 10.0/s 10,0/сек Disabled Отключено Select Set 1 One Way Установить Набор 1 Односторонним Select Set 1 Two Way Установить Набор 1 Двусторонним Select Set 1 While Held Установить Набор 1 Пока Нажато Select Set 2 One Way Установить Набор 2 Односторонним Select Set 2 Two Way Установить Набор 2 Двусторонним Select Set 2 While Held Установить Набор 2 Пока Нажато Select Set 3 One Way Установить Набор 3 Односторонним Select Set 3 Two Way Установить Набор 3 Двусторонним Select Set 3 While Held Установить Набор 3 Пока Нажато Select Set 4 One Way Установить Набор 4 Односторонним Select Set 4 Two Way Установить Набор 4 Двусторонним Select Set 4 While Held Установить Набор 4 Пока Нажато Select Set 5 One Way Установить Набор 5 Односторонним Select Set 5 Two Way Установить Набор 5 Двусторонним Select Set 5 While Held Установить Набор 5 Пока Нажато Select Set 6 One Way Установить Набор 6 Односторонним Select Set 6 Two Way Установить Набор 6 Двусторонним Select Set 6 While Held Установить Набор 6 Пока Нажато Select Set 7 One Way Установить Набор 7 Односторонним Select Set 7 Two Way Установить Набор 7 Двусторонним Select Set 7 While Held Установить Набор 7 Пока Нажато Select Set 8 One Way Установить Набор 8 Односторонним Select Set 8 Two Way Установить Набор 8 Двусторонним Select Set 8 While Held Установить Набор 8 Пока Нажато [NO KEY] [ПУСТО] sec. сек. /sec. /сек. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Набор %1 Select Set %1 Установить Набор %1 One Way Односторонним Two Way Двусторонним While Held Пока Нажато Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Choose Profile Config Files (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Настройки Стиков / Крестовин Sticks Стики DPads Крестовины Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Геймпад %2) Stick 1 Стик 1 Enabled Включено Assign Назначить X Axis: Ось X: Y Axis: Ось Y: Stick 2 Стик 2 Number of Physical DPads: %1 Количество физических крестовин: %1 Virtual DPad 1 Виртуальная Крестовина 1 Up: Вверх: Down: Вниз: Left: Влево: Right: Вправо: Axis %1 Ось %1 Axis %1 - Ось %1 - Axis %1 + Ось %1 + Button %1 Кнопка %1 Move stick 1 along the X axis Переместите Cтик 1 по оси X Move stick 1 along the Y axis Переместите Cтик 1 по оси Y Move stick 2 along the X axis Переместите Cтик 2 по оси X Move stick 2 along the Y axis Переместите Cтик 2 по оси Y Press a button or move an axis Нажмите кнопку или подвигайте стик AxisEditDialog Axis Ось Mouse (Horizontal) Мышь (горизонталь) Mouse (Inverted Horizontal) Мышь (инвертированная горизонталь) Mouse (Vertical) Мышь (вертикаль) Mouse (Inverted Vertical) Мышь (инвертированная вертикаль) Arrows: Up | Down Стрелки: Вверх | Вниз Arrows: Left | Right Стрелки: Влево | Вправо Keys: W | S Клавиши: W | S Keys: A | D Клавиши: A | D NumPad: KP_8 | KP_2 NumPad: 8 | 2 NumPad: KP_4 | KP_6 NumPad: 4 | 6 None Отсутствует Set the value to use as the limit for an axis. Useful for a worn out analog stick. Negative Half Throttle Отрицательная Полутяга Positive Half Throttle Положительная Полутяга Name: Имя: Specify the name of an axis. Укажите имя для оси. Mouse Settings Настройки Мыши Set the value of the dead zone for an axis. Устанавливает значение мертвой зоны для оси. Presets: Пресет: Dead Zone: Мертвая Зона: Max Zone: Лимит: [NO KEY] [ПУСТО] Throttle setting that determines the behavior of how to interpret an axis hold or release. Настройки тяги определяют как программа будет расценивать удерживание или отпускание оси. Negative Throttle Отрицательная Тяга Normal Нормально Positive Throttle Положительная Тяга Current Value: Текущее значение: Set Установки для Set %1 Набор %1 Left Mouse Button Right Mouse Button ButtonEditDialog Dialog Окно To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab <center>Чтобы назначить новое действие нажмите на соответствующую кнопку во вкладках "Клавиатура" или "Мышь"</center> Placeholder Заполнитель Toggle Переключатель Enables a key press or release to only occur when a controller button is pressed. Добавляет возможность производить действие только в случае нажатия или отпускания кнопки. Enables rapid key presses and releases. Turbo controller. Добавляет возможность быстрого нажатия кнопок (как в турбо контроллере). Turbo Турбо Current: Текущая: Last keyboard/mouse button: Slots Слоты Na&me: Имя: Specify the name of a button. Укажите название кнопки. Action: Действие: Specify the action that will be performed in game while this button is being used. Укажите какое действие будет производится при нажатии данной кнопки. Advanced Дополнительно Set Установки для Set %1 Набор %1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [ПУСТО] Calibration Form Start calibration Sticks: Reset settings Cancel Отмена Save Сохранить Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 Ось %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path Full Path File Name CommandLineUtility Profile location %1 is not an XML file. Профиль, находящийся в %1 не является XML файлом. Profile location %1 does not exist. Профиль, находящийся в %1 не существует. No display string was specified. Не указана строка для отображения. Controller identifier is not a valid value. Идентификатор контроллера имеет недопустимое значение. No set number was specified. Не указан набор значений. Options Опции Print help text. Показать текст помощи. Print version information. Показать информацию о версии. Launch program in system tray only. Запускать программу только в системном трее. Launch program with the tray menu disabled. Запустить программу с отключенным меню трея. Launch program without the main window displayed. Запускать программу без отображения главного окна. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Запускать программу с конфигурационным файлом, назначенным по-умолчанию для выбранных контроллеров. Настройки контроллеров будут выставлены по-умолчанию. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Применить файл конфигурации для определенных контроллеров. Значениями могут быть индекс контроллера, имя или GUID. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Загрузить текущие активные профили. Значениями могут быть индекс контроллера, имя или GUID. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Запускать геймпады на определнном наборе. Значениями могут быть индекс контроллера, имя или GUID. Launch program as a daemon. Запускать программу в качестве демона. DPadContextMenu Mouse (Normal) Мышь (Нормально) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Стрелки Keys: W | A | S | D Клавиши: W | A | S | D NumPad NumPad None Отсутствует Standard Стандартный Eight Way 8-ми сторонний 4 Way Cardinal 4-х сторонний основной 4 Way Diagonal 4-х сторонний диагональный Mouse Settings DPadEditDialog Dialog Окно Presets: Пресет: Mouse (Normal) Мышь (Нормально) Mouse (Inverted Horizontal) Мышь (Инвертированная Горизонталь) Mouse (Inverted Vertical) Мышь (Инвертированная Вертикаль) Mouse (Inverted Horizontal + Vertical) Мышь (Инвертированная Горизонталь + Вертикаль) Arrows Стрелки Keys: W | A | S | D Клавиши: W | A | S | D NumPad NumPad None Отсутствует Dpad Mode: Режим Крестовины: &Name: 4 Way Cardinal 4-х сторонний основной 4 Way Diagonal 4-х сторонний диагональный DPad Delay: Time lapsed before a direction change is taken into effect. s Specify the name of a dpad. Укажите имя для крестовины. Mouse Settings Настройки Мыши Standard Стандартный Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way 8-ми сторонний Set Установки для Set %1 Набор %1 EditAllDefaultAutoProfileDialog Default Profile Профиль По-Умолчанию Profile: Профиль: Browse Обзор Open Config Открыть Конфигурацию Profile file path is invalid. Путь до профиля неверен. ExtraProfileSettingsDialog Extra Profile Settings Дополнительные настройки профиля Key Press Time: Отклик Клавиш: 0.00 ms 0,00 мс Profile Name: Имя Профиля: s сек GameController Game Controller Геймпад GameControllerDPad DPad Крестовина GameControllerMappingDialog Game Controller Mapping Настройка Игрового Контроллера <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A A B B X X Y Y Back Back Start Start Guide Guide Left Shoulder Левый Бампер Right Shoulder Правый Бампер Left Stick Click Кнопка Левого Стика Right Stick Click Кнопка Правого Стика Left Stick X Ось X Левого Стика Left Stick Y Ось Y Левого Стика Right Stick X Ось X Правого Стика Right Stick Y Ось Y Правого Стика Left Trigger Левый Триггер Right Trigger Правый Триггер DPad Up Крестовина Вверх DPad Left Крестовина Влево DPad Down Крестовина Вниз DPad Right Крестовина Вправо Mapping Настройка SDL 2 Game Controller Mapping String Вывод настройщика контроллеров SDL 2 Last Axis Event: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Discard Controller Mapping? Сбросить настройки контроллера? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Сбросить настройки для этого контроллера? Если сбросить настройки, контроллер вернется к своему изначальному состоянию после обновления всех геймпадов. GameControllerSet Back Back Guide Guide Start Start LS Click RS Click L Shoulder R Shoulder L Trigger R Trigger GameControllerTrigger Trigger Триггер JoyAxis Axis Ось JoyAxisButton Negative Отрицательно Positive Положительно Unknown Неизвестно Button Кнопка JoyAxisContextMenu Mouse (Horizontal) Мышь (горизонталь) Mouse (Inverted Horizontal) Mouse (Vertical) Мышь (вертикаль) Mouse (Inverted Vertical) Arrows: Up | Down Стрелки: Вверх | Вниз Arrows: Left | Right Стрелки: Влево | Вправо Keys: W | S Клавиши: W | S Keys: A | D Клавиши: A | D NumPad: KP_8 | KP_2 NumPad: 8 | 2 NumPad: KP_4 | KP_6 NumPad: 4 | 6 None Отсутствует Mouse Settings Left Mouse Button Right Mouse Button JoyButton Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Button Кнопка [NO KEY] [ПУСТО] [Set %1 1W] [Set %1 2W] [Set %1 WH] JoyButtonContextMenu Toggle Переключатель Turbo Турбо Clear Set Select Disabled Отключено Set %1 Set %1 1W Набор %1 1W Set %1 2W Набор %1 2W Set %1 WH JoyButtonSlot Mouse Мышь Up Вверх Down Вниз Left Влево Right Вправо LB LB MB MB RB RB B4 B4 B5 B5 Pause Пауза Hold Удерживание Cycle Цикл Distance Дистанция Release Отпускание Mouse Mod Скорость Мыши Press Time Время Нажатия Delay Задержка Load %1 Set Change %1 [Text] %1 [Exec] %1 [NO KEY] [ПУСТО] JoyControlStick Stick Стик JoyControlStickButton Up Вверх Down Вниз Left Влево Right Вправо Button Кнопка JoyControlStickContextMenu Mouse (Normal) Мышь (Нормально) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Стрелки Keys: W | A | S | D Клавиши: W | A | S | D NumPad NumPad None Отсутствует Standard Стандартный Eight Way 8-ми сторонний 4 Way Cardinal 4-х сторонний основной 4 Way Diagonal 4-х сторонний диагональный Mouse Settings JoyControlStickEditDialog Dialog Окно X: Х: 0 0 Y: Y: Distance: Дистанция: Presets: Пресет: Mouse (Normal) Мышь (Нормально) Mouse (Inverted Horizontal) Мышь (инвертированная горизонталь) Mouse (Inverted Vertical) Мышь (инвертированная вертикаль) Mouse (Inverted Horizontal + Vertical) Мышь (инвертированная горизонталь + вертикаль) Arrows Стрелки Keys: W | A | S | D Клавиши: W | A | S | D NumPad NumPad None Отсутствует Stick Mode: Режим Стика: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 4 Way Cardinal 4-х сторонний основной 4 Way Diagonal 4-х сторонний диагональный Dead zone value to use for an analog stick. Value when an analog stick is considered moved 100%. The area (in degrees) that each diagonal region occupies. Square Stick: Percentage to modify a square stick coordinates to confine values to a circle % % Stick Delay: Time lapsed before a direction change is taken into effect. s Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Na&me: Name: Имя: Specify the name of an analog stick. Укажите имя для аналогового стика. Mouse Settings Настройки Мыши Standard Стандартный Bearing: Точка Опоры: % Safe Zone: % ограничения: Eight Way 8-ми сторонний Dead Zone: Мертвая Зона: Max Zone: Лимит: Diagonal Range: Диагональный диапазон: Set Установки для Set %1 Установки для %1 JoyControlStickModifierButton Modifier JoyDPad DPad Крестовина JoyDPadButton Up Вверх Down Вниз Left Влево Right Вправо Button Кнопка JoyTabWidget <New> <Новый> Remove Удалить Remove configuration from recent list. Удалить конфигурацию из списка недавно использованных файлов. Load Загрузить Load configuration file. Загрузить файл конфигурации. Save Сохранить Save changes to configuration file. Сохранить изменения в файл конфигурации. Save As Сохранить Как Save changes to a new configuration file. Сохранить изменения в новый файл конфигурации. Sets Наборы Copy from Set Settings Настройки Set 1 Набор 1 Set 2 Набор 2 Set 3 Набор 3 Set 4 Набор 4 Set 5 Набор 5 Set 6 Набор 6 Set 7 Набор 7 Set 8 Набор 8 Stick/Pad Assign Настройка Стиков/Крестровин Controller Mapping Настройка Контроллера Quick Set Быстрая Настройка Names Бирки Toggle button name displaying. Вкл. / Выкл. отображение названий команд на кнопках. Pref Настройки Профиля Change global profile settings. Изменить общие настройки профиля. Reset Сброс Revert changes to the configuration. Reload configuration file. Отменяет изменения конфигурации. Перезагружает конфигурационный файл. Open Config Открыть Конфигурацию Config Files (*.amgp *.xml) Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Сохранить изменения в профиле? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Изменения в новом профиле не были сохранены. Сохранить или отменить изменения в текущем профиле? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Изменения в профиле "%1" не были сохранены. Сохранить или отменить изменения в текущем профиле? Sticks Стики DPads Крестовины No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. <center>Не было назначено ни одной кнопки. Воспользуйтесь "Быстрой Настройкой" <br>для назначения кнопок или отключите сокрытие пустых кнопок.</center> Set %1: %2 Набор %1: %2 Set %1 Набор %1 Copy Set Assignments Скопировать Набор Настроек Are you sure you want to copy the assignments and device properties from %1? Вы уверены что хотите скопировать настройки и параметры устройства из %1? Save Config Сохранить Конфигурацию Set Набор Joystick Joystick Геймпад JoystickStatusWindow Properties Свойства Details Детали Name: Имя: %1 %1 Number: Номер: Axes: Осей: Buttons: Кнопок: Hats: Мини-джойстиков: Battery: Unknown Неизвестно GUID: GUID: Game Controller: Axes Оси Buttons Кнопки Hats Мини-джойстики %1 (#%2) Properties %1 (#%2) Свойства Axis %1 Ось %1 Hat %1 Мини-джойстик %1 No Yes MainSettingsDialog Edit Settings Редактировать настройки General Общие Controller Mappings Настройки Контроллера Language Язык Auto Profile АвтоПрофиль Mouse Мышь Advanced <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Укажите путь до директории, которую программа будет использовать для хранения профилей.</p></body></html> Recent Profile Count: Количество недавних профилей: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Количество профилей, которые будут хранится в списке недавних. Если выставить "0" то программа не будет ограничивать количество отображаемых профилей.</p></body></html> Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Прятать главное окно программы по нажатию на кнопку выхода вместо того чтобы закрывать программу. Close To Tray Сворачивать в трей Have Windows start AntiMicroX at system startup. Launch At Windows Startup Загружать вместе с Windows Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Отображает недавно открытые профили для всех контроллеров в виде единого списка под иконкой в трее. По-умолчанию использует подменю. Single Profile List in Tray Единый лист профилей в трее Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Заставляет программу сворачиватся в панель задач. По-умолчанию программа сворачивается в системный трей. Minimize to Taskbar Сворачивать в панель задач This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Эта опция заставит программу скрывать все кнопки, к которым не привязаны слоты с командами. Воспользуйтесь окном "Быстрой Настройки" для отображения скрытых кнопок. Hide Empty Buttons Скрыть пустые кнопки When the program is launched, open the last known profile that was opened during the previous session. Когда программа запустится, будет открыт последний профиль, использованный в предыдущей сессии. Auto Load Last Opened Profile Автоматически загружать последний открытый профиль Only show the system tray icon when the program first launches. При запуске программы появится лишь значок в системном трее. Launch in Tray Запускаться в свернутом виде Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Повтор клавиш Active keys will be repeatedly pressed when this option is enabled. Если активировать данную опцию то активные клавиши будут нажиматься автоматически. Enable Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Отсутствует Error Warning Info Информация Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset Сброс Class Title Program Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision Smoothing Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Пружина Screen: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: 0 0 Accel Denominator: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Delay: Задержка: Pro&file Directory: ms мс Rate: Частота: times/s раз/сек Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Ниже приведен сохраненный список из пользовательских настроек. Вы можете использовать эту таблицу, чтобы удалять настройки или же временно их отключать. Также Вы можете отключить настройки, входящие в SDL - просто добавьте новую строку с соответствующим GUID геймпада и активируйте чекбокс "Отключить" Изменения не вступят в силу пока вы не обновите или переподключите все геймпады. GUID GUID Mapping String Строка Настроек Disable? Отключить? Delete Удалить Insert Вставить Default По-умолчанию Brazilian Portuguese Бразильский / Португальский English Английский German Немецкий Active Активировать Devices: Устройства: All Все Device Устройство Profile Профиль Default? По-умолчанию? Add Добавить Edit Редактировать Select Default Profile Directory Выбрать как профиль по-умолчанию Are you sure you want to delete the profile? Вы уверены что хотите удалить этот профиль? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [ПУСТО] MainWindow AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Геймпады не обнаружены. Пожалуйста, подключите геймпад к компьютеру и выберете опцию "Обновить Геймпады" из главного меню. If events are not seen by a game, please click here to run this application as Administrator. &App &Приложение &Options &Опции &Help &Помощь He&lp &Quit &Выход Ctrl+Q Ctrl+Q &Update Joysticks &Обновить Геймпады Ctrl+U Ctrl+U &Hide &Скрыть Ctrl+H Ctrl+H &About &О программе Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt О Qt Properties Свойства Key Checker Проверка Клавиш Home Page Домашняя страница GitHub Page Страница на GitHub Game Controller Mapping Настройки Игрового Контроллера Settings Настройки Stick/Pad Assign Настройки Стиков / Крестовин Could not find a proper controller identifier. Exiting. (%1) (%1) Open File Открыть файл %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore &Восстановить Calibration couldn't be opened You must connect at least one controller to open the window Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Настройки Мыши - Set %1 Установки для %1 MouseButtonSettingsDialog Mouse Settings - Настройки Мыши - Set %1 Установки для %1 MouseControlStickSettingsDialog Mouse Settings Настройки Мыши Set %1 Установки для %1 MouseDPadSettingsDialog Mouse Settings Настройки Мыши Set %1 Установки для %1 MouseSettingsDialog Mouse Settings Настройки Мыши Mouse Mode: Режим Мыши: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Режим Курсора используется для перемещения курсора мыши по экрану по отношению к текущей позиции в зависимости от того, насколько вы переместили ось, или при нажатии кнопки. Режим Пружины используется для перемещения курсора мыши от центра экрана в зависимости от того, насколько вы переместили ось. Курсор мыши будет возвращен в центр экрана, когда ось переместится обратно к мертвой зоне. Cursor Курсор Spring Пружина Acceleration: Усиление: Enhanced Precision Улучшенная Точность Linear Линейное Quadratic Квадратное Cubic Кубическое Quadratic Extreme Экстримально Кубическое Power Function Степенная Функция Easing Quadratic Easing Cubic Mouse Speed Settings Настройки скорости мыши Enable to change the horizontal and vertical speed boxes at the same time. Позволяет увеличивать скорость мыши по горизонтали и вертикали одновременно. Change Together Изменять совместно Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: Horizontal Speed: Скорость по горизонтали: 1 = 20 pps 1 = 20 pps Vertical Speed: Скорость по вертикали: Wheel Hori. Speed: Скорость колесика по горизонтали: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Устанавливает скорость движения колесика мыши по горизонтали. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Устанавливает скорость движения колесика мыши по вертикали. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: s Highest value to accelerate mouse movement by x x Start %: Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Max Threshold: Maximum axis travel before acceleration has reached the multiplier value E&xtra Duration: Curve: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Привязывает пружину к позиции мыши. Relative Привязка Mouse Status X: Х: 0 (0 pps) Y: Y: 1 = 1 notch(es)/s 1 = 1 шаг(ов)/сек Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Скорость колесика по вертикали: Sensitivity: Чувствительность: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. % % Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Spring Settings Настройки Пружины Spring Width: Ширина Пружины: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Изменяет ширину области, по которой будет двигаться курсор в режиме Пружины. Если выставить "0" будет использоваться вся ширина экрана. Spring Height: Высота Пружины: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Изменяет высоту области, по которой будет двигаться курсор в режиме Пружины. Если выставить "0" будет использоваться вся высота экрана. %n notch(es)/s %n шаг/сек %n шагов/сек %n шаг(ов)/сек ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Отмена OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Проверка Клавиш <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Native Key Value: Родное Значение Клавиши: 0x00000000 0x00000000 Qt Key Value: Значение Клавиши в Qt: antimicro Key Value: QObject Super Super Menu Меню Pause Пауза Next Next Home Home Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Демон запущен Failed to launch daemon Не удалось запустить демон Launching daemon Демон запускается Display string "%1" is not valid. Failed to set a signature id for the daemon Не удалось подписать демон Failed to change working directory to / Не удалось менить рабочую директорию на "/" Quitting Program # of joysticks found: %1 List Joysticks: --------------- Joystick %1: Index: %1 UniqueID: %1 GUID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Yes No Game Controller: %1 # of Axes: %1 # of Buttons: %1 # of Hats: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Профиль, находящийся в %1 не является XML файлом. Profile location %1 does not exist. Профиль, находящийся в %1 не существует. Controller identifier is not a valid value. Идентификатор контроллера имеет недопустимое значение. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. Не указан набор значений. No controller was specified. No display string was specified. Не указана строка для отображения. An invalid event generator was specified. No event generator string was specified. No log file specified. Options Опции Print help text. Показать текст помощи. Print version information. Показать информацию о версии. Launch program in system tray only. Запускать программу только в системном трее. Launch program with the tray menu disabled. Запустить программу с отключенным меню трея. Launch program without the main window displayed. Запускать программу без отображения главного окна. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Запускать программу с конфигурационным файлом, назначенным по-умолчанию для выбранных контроллеров. Настройки контроллеров будут выставлены по-умолчанию. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Применить файл конфигурации для определенных контроллеров. Значениями могут быть индекс контроллера, имя или GUID. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Загрузить текущие активные профили. Значениями могут быть индекс контроллера, имя или GUID. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Запускать геймпады на определнном наборе. Значениями могут быть индекс контроллера, имя или GUID. Launch program as a daemon. Запускать программу в качестве демона. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. QuickSetDialog Quick Set Быстрая настройка <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Пожалуйста, нажмите кнопку или подвигайте стик на %1 (<span style=" font-weight:600;">%2</span>).<br/>Появится окно, которое позволит вам назначить кнопку.</p></body></html> Quick Set %1 Быстрая Настройка %1 SetAxisThrottleDialog Throttle Change Смена Тяги The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? Настройки профиля для Оси %1 были изменены. Желаете применить эти настройки ко всем наборам? SetJoystick Set %1: %2 Набор %1: %2 Set %1 Набор %1 SetNamesDialog Set Name Settings Установить имена для наборов Set 1 Набор 1 Set 2 Набор 2 Set 3 Набор 3 Set 4 Набор 4 Set 5 Набор 5 Set 6 Набор 6 Set 7 Набор 7 Set 8 Набор 8 Name Имя SimpleKeyGrabberButton Mouse Мышь SpringModeRegionPreview Spring Mode Preview Предпросмотр Режима Пружины UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Using uinput device file %1 UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s сек t t u u v v w w x x y y z z Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock ; ; ' ' Enter Shift_L Shift_L , , . . / / Ctrl_L Super_L Super_L Alt_L Alt_L Space Пробел Alt_R Alt_R Menu Меню Ctrl_R Shift_R Shift_R Up Left Down Right PrtSc Ins Del Home Home End End PgUp PgDn NumLock * * + + KP_Enter KP_Enter KP_1 KP_1 KP_2 KP_2 KP_3 KP_3 KP_4 KP_4 KP_5 KP_5 KP_6 KP_6 KP_7 KP_7 KP_8 KP_8 KP_9 KP_9 KP_0 KP_0 SCLK SCLK Pause Пауза Super_R Mute VolDn VolUp Play Stop Prev Next Next [NO KEY] [ПУСТО] UnixWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path VDPad VDPad Виртуальная Крестовина VirtualKeyPushButton Space Пробел Tab Tab Shift (L) Shift (Л) Shift (R) Shift (П) Ctrl (L) Ctrl (Л) Ctrl (R) Ctrl (П) Alt (L) Alt (Л) Alt (R) Alt (П) Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP PGUP DEL DEL PGDN PGDN 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK NUM * * + + Enter Del E N T E R E N T E R < < : : Super (L) Super Menu Меню Up Вверх Down Вниз Left Влево Right Вправо VirtualKeyboardMouseWidget Keyboard Клавиатура Mouse Мышь Mouse Settings Наcтройка Мыши Left Mouse Left Up Mouse Up Left Button Mouse Left Button Middle Button Mouse Middle Button Right Button Mouse Right Button Wheel Up Mouse Wheel Up Wheel Left Mouse Wheel Left Wheel Right Mouse Wheel Right Wheel Down Mouse Wheel Down Down Mouse Down Right Mouse Right Button 4 Mouse Button 4 Mouse 8 Mouse Mouse 8 Button 5 Mouse Button 5 Mouse 9 Mouse Mouse 9 NONE ПУСТО [NO KEY] [ПУСТО] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Browser Back Browser Favorites Browser Forward Browser Home Browser Refresh Browser Search Browser Stop Calc Email F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 Media Media Next Media Play Media Previous Media Stop Search Volume Down Volume Mute Volume Up VirtualMousePushButton INVALID ОШИБКА WinAppProfileTimerDialog Capture Application Звхватить Приложение After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. После нажатия на кнопку "Захватить Приложение" кликните по приложению с которым хотите ассоциировать данный профиль. Активное приложение будет захвачено после выбранного количества секунд. Timer: Таймер: Seconds Секунды Cancel Отмена WinExtras [NO KEY] [ПУСТО] X11Extras ESC ESC Tab Tab Space Пробел DEL DEL Return Return KP_Enter KP_Enter Backspace Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. xinput version must be at least 2.0. No mouse acceleration changes will occur. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Changing mouse acceleration for device with id=%1 XMLConfigReader Could not write updated profile XML to file %1. XMLConfigWriter Could not write to profile at %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Запускать программу только в системном трее. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_sr.ts000066400000000000000000014450161377703515000275270ustar00rootroot00000000000000 AboutDialog About О програму Version Издање <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2020 Ауторска права: 2013 - 2020. {2013 ?} {2013 ?} Copyright: 2013 - 2018 Ауторска права: 2013 - 2018. {2013 ?} {2013 ?} Info Подаци Changelog Дневник измена Copyright: 2013 - 2016 Ауторска права: 2013 - 2016. {2013 ?} Since December 30, 2012, I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Once the Steam controller is finally released to the public, the need for this program might not exist anymore. Just based on the concept of the controller alone, the Steam controller would have so many advantages over using a program like this to provide KB+M emulation. Од 30. децембра 2012. године, стварао сам Анти-микро у своје слободно време. Оно што је првобитно започето као верзија програма КЈу-Џој-Пед (енг. „QJoyPad“) и начин да се научи правилно програмирање управљано догађајима, претворило се у нешто много веће од оне моје првобитна намере. Иако сам провео доста времена учећи нове технике, сазнавајући више о симулацији тастатуре и миша, те проводећи петак увече разбијајући главу о моју тастатуру, било је забавно ово радити свеукупно обогаћујући сопствено искуство. Програм сам створио јер није било природне подршке за контролере код неких игара као код сличних програма на Виндоузу. Иако су постојали слични програми на Гну/Линуксу, није било оних који би, по мени, били довољно добри у смислу функционалности или у играма које сам желео да играм са употребљавајући симулацију тастатуре и миша. КЈу-Џој-Пед је био основни програм који сам користио раније, али он се предуго није развијао и није пружао неке основне функционалности за које сам веровао да су од суштинског значаја. Како се КЈу-Џој-Пед није развијао већ неколико година одлучио сам да направим свој. Од тада, покушавао сам да откријем оно што други програми раде ваљано и да то онда унапредим и побољшам. Успут, открио сам неке лепе фазоне и научио више него што сам икада желео да знам о унутрашњим контролама гејмпеда и њиховој изведби у неким играма. Иако се у неким областима овај програм и даље може унапређивати, сматрам да нуди најбоље искуство у-контролама игара код играње старијих, а неки новијих игара које саме не обезбеђују природну подршку за контролер. Овај се програм, највероватније, неће даље развијати, када се званично појави програм Стим-контролер. Управо заснован на идеји самог контролера, Стим-контролер ће имати толико предности у односу на друге програме који обезбеђују симулацију тастатуре и миша. Credits Заслуге AntiMicroX Анти-микро About Development О развоју програма License Лиценца Program Version %1 Издање програма %1 Program Compiled on %1 at %2 Програмски код је превођен дана %1 у %2 Built Against SDL %1 Изграђен помоћу СДЛ %1 Running With SDL %1 Употребљава СДЛ %1 Using Qt %1 Уз КјуТ-библиотеке %1 Using Event Handler: %1 Употребљава руковаоца догађајима („Event Handler“) : %1 AddEditAutoProfileDialog Auto Profile Dialog Самостално профилисање Profile: Профил: Pro&file: Browse Разгледај Window: Прозор: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Одабир прозора — Притиском на одговарајући прозор програма у обрасцу се попуњава путања до датотеке програма. Detect Window Properties Сам откриј особине прозора &Class: T&itle: Class: Класа: Title: Наслов: set partial title Application: Програм: Select Одабери De&vices: Devices: Уређаји: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Подразумевано поставља овај профил за дати уређај. Овај избор ће се користити уместо свеопштих опција профила. Set as Default for Controller Постави као подразумевано за контролер A different profile is already selected as the default for this device. За овај уређај је већ одабран други подразумевани профил. Current (%1) Текући (%1) Open Config Отвори подешавања Select Program Одабери програм Programs (*.exe) Програми (*.exe) Please use the main default profile selection. Користите главни избор подразумеваног профила. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Одабирајте прозор употребом миша, а поништите одабир тастером <Esc>. Capture Application Window Разоткривање графичког сучеља програма Could not obtain information for the selected window. Не могу да добавим податке о одабраном прозору. Application Capture Failed Није успело разоткривање програма Profile file path is invalid. Путања до датотеке профила није ваљана. No window matching property was specified. Није била одређена одговарајућа особина прозора. Program path is invalid or not executable. Путања до програма није ваљана или није извршна. File is not an .exe file. Ово није извршна датотека. No window matching property was selected. Није била одабрана одговарајућа особина прозора. AdvanceButtonDialog Advanced Напредно Assignments Придруживања Toggle Преклопник Turbo Набуџи Set Selector Изборник скупа Blank or KB/M Празно или „Таст./Миш“ Hold Држи Pause Пауза Cycle Врти Distance Раздаљина Insert Уметни Delete Уклони Clear All Уклони све Time: Време: 0.01s 0,01 сек 0s 0 сек Insert a pause that occurs in between key presses. Време између притиска два притиска дугмета. Release Пусти Insert a new blank slot. Унеси нов, празан слот. Join Split Delete a slot. Уклони слот. Clear all currently assigned slots. Уклони све већ придружене слотове. Specify the duration of an inserted Pause or Hold slot. Одређивање трајања за већ унет Пауза/Држи слот. 0m 0 мин &Mouse Speed Mod: Specify the range past an axis dead zone in which a sequence of actions will execute. Поставите област изван мртве области правца, у којој ће се извршити низ радњи. Distance: Раздаљина: % % Mouse Mod Мишар Press Time Трајање притиска Delay Кашњење Execute Изврши Load Учитај Set Change Измени скуп Text Entry Унос текста Placeholder Препознавач положаја 0 0 Mouse Speed Mod: Брзина Мишара: Set the percentage that mouse speeds will be modified by. Поставите промену брзине померања миша у процентима. Auto Reset Cycle After Самопоништавање „вртње“ након seconds секунди Executable: ... ... Arguments: Enabled Омогућено Mode: Режим: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>Обично: Узастопно притискање-пуштање дугмета одабраном брзином.</p><p>Постепено: Измена кашњења код притиска-пуштања дугмета засновано на померају осног растојањ. Брзина остаје неизмењена.</p><p>Импулсно: Измена броја притисака-пуштања дугмета по секунди. Кашњење остаје неизмењено.</p></body></html> Normal Обично Gradient Постепено Pulse Импулсно Delay: Кашњење: 0.10s 0,10 сек Rate: Брзина: 10.0/s 10,0/сек Disabled Онемогућено Select Set 1 One Way Изабери 1. скуп, једносмерно Select Set 1 Two Way Изабери 1. скуп, двосмерно Select Set 1 While Held Изабери 1. скуп, док држим Select Set 2 One Way Изабери 2. скуп, једносмерно Select Set 2 Two Way Изабери 2. скуп, двосмерно Select Set 2 While Held Изабери 2. скуп, док држим Select Set 3 One Way Изабери 3. скуп, једносмерно Select Set 3 Two Way Изабери 3. скуп, двосмерно Select Set 3 While Held Изабери 3. скуп, док држим Select Set 4 One Way Изабери 4. скуп, једносмерно Select Set 4 Two Way Изабери 4. скуп, двосмерно Select Set 4 While Held Изабери 4. скуп, док држим Select Set 5 One Way Изабери 5. скуп, једносмерно Select Set 5 Two Way Изабери 5. скуп, двосмерно Select Set 5 While Held Изабери 5. скуп, док држим Select Set 6 One Way Изабери 6. скуп, једносмерно Select Set 6 Two Way Изабери 6. скуп, двосмерно Select Set 6 While Held Изабери 6. скуп, док држим Select Set 7 One Way Изабери 7. скуп, једносмерно Select Set 7 Two Way Изабери 7. скуп, двосмерно Select Set 7 While Held Изабери 7. скуп, док држим Select Set 8 One Way Изабери 8. скуп, једносмерно Select Set 8 Two Way Изабери 8. скуп, двосмерно Select Set 8 While Held Изабери 8. скуп, док држим [NO KEY] [Без тастера] sec. сек. /sec. /сек. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Скуп %1 Select Set %1 Одабери %1. скуп One Way Једносмерно Two Way Двосмерно While Held Док држим Choose Executable Избор извршне датотеке Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Слотови изван „вртње“ ће се извршити по наредном притиску тастера. Вишеструке „вртње“ се могу додавати код стварање делова једног низа. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Покретање наредног слота биће одложено за наведено време.Слотови покренути пре овог одлагања ће остати покренути и по његовом истеку. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Овом се радњом одређује да накнадни слотови могу да се изврше само када се нека оса помери за одређени опсег изван дате мртве области. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Уметање задржавања. Слотови након дате радње ће да се изврше само ако се тастер задржи ван наведеног периода. Chose a profile to load when this slot is activated. Одабир профила који ће се учитати по укључењу овог слота. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Радња за управљањем начином рада миша ће изменити све поставке брзине миша за одређен проценат,а док је радња у току. Ово може бити корисно за успоравање миша при нишањењу. Specify the time that keys past this slot should be held down. Одређује колико ће дуго бити задржани у доњем положају (притиснути) тастери ван овог слота. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Уметање отпуштања. Слотови након дате радње ће да се изврше само по отпуштању тастера ако је он задржан ван наведеног периода. Change to selected set once slot is activated. Промени на одабрани скуп по отпочињању слота. Full string will be typed when a slot is activated. Уписује пуну ниску знакова по отпочињању слота. Execute program when slot is activated. Извршава програм по отпочињању слота. Choose Profile Одабир профила Config Files (*.amgp *.xml) Датотеке подешавања (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Придружвање Управљача/Тастера Sticks Управљачи DPads Тастери правца или смера (дирекционални) Д-тастери Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (Џојстик %2) Stick 1 Управљач 1 Enabled Омогућен Assign Придружи X Axis: »X« правац: Y Axis: »Y« правац: Stick 2 Управљач 2 Number of Physical DPads: %1 Број стварних Д-тастера: %1 Virtual DPad 1 Патворено = Виртуелно Патворен Д-тастатер 1 Up: Горе: Down: Доле: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. Обавештење: Ово прозорче још увек постоји само због усаглашености са ранијим издањима програма (пре издања 2.0). Придруживач тастера контролера се препоручује од издања 2.0. Left: Лево: Right: Десно: Axis %1 Правац %1 Axis %1 - Правац %1 - Axis %1 + Правац %1 + Button %1 Дугме %1 Move stick 1 along the X axis Померајте по »Х-оси« 1. управљач Move stick 1 along the Y axis Померајте по »У-оси« 1. управљач Move stick 2 along the X axis Померајте по »Х-оси« 2. управљач Move stick 2 along the Y axis Померајте по »У-оси« 2. управљач Press a button or move an axis Притисните тастер или померите управљач AxisEditDialog Axis Правац Mouse (Horizontal) Миш (водоравно) Mouse (Inverted Horizontal) Миш (обрнуто водоравно) Mouse (Vertical) Миш (усправно) Mouse (Inverted Vertical) Миш (обрнуто усправно) Arrows: Up | Down Стрелице: Горе | Доле Arrows: Left | Right Стрелице: Лево | Десно Keys: W | S Тастери: Њ | С Keys: A | D Тастери: А | Д NumPad: KP_8 | KP_2 Број.Тастатура: КП_8 | КП_2 NumPad: KP_4 | KP_6 Број.Тастатура: КП_4 | КП_6 None Ништа Set the value to use as the limit for an axis. Useful for a worn out analog stick. Постави ову вредност као граничну за правац. Употребљиво у раду са истрошеним аналогним управљачем. Negative Half Throttle Полу-регулатор умањења Positive Half Throttle Полу-регулатор увећавања Name: Назив: Specify the name of an axis. Одредите Назив осе(правца). Mouse Settings Поставке миша Set the value of the dead zone for an axis. Подеси вредност мртве области за правaц. Presets: Поставке: Dead Zone: Мртва област: Max Zone: Највиша област: [NO KEY] [Без тастера] Throttle setting that determines the behavior of how to interpret an axis hold or release. Поставке регулатора које одређују понашање при тумачењу држи („hold“) или пусти („release“) за правац. Negative Throttle Регулатор умањења Normal Нормално Positive Throttle Регулатор увећавања Current Value: Текућа вредност: Set Постави Set %1 Скуп %1 Left Mouse Button Леви тастер миша Right Mouse Button Десни тастер миша ButtonEditDialog Dialog Прозорче To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Да би сте створили ново придруживање, притисните неко од дугмади тастатуре или кликните мишем на неко дугме у неком од језичака „Тастатура“ или „Миш“ Placeholder Препознавач положаја Toggle Преклопник Enables a key press or release to only occur when a controller button is pressed. Омогућава да се догоди дугме „притисни“ или „пусти“, и то, само ако је дугме контролера притиснуто. Enables rapid key presses and releases. Turbo controller. Омогућава хитрије дугме „притисни“ или дугме „пусти“. Контролер набуџивања. Turbo Набуџи Current: Тренутно стање: Last keyboard/mouse button: Slots Слотови Na&me: Назив: Specify the name of a button. Унесите назив за дугме. Action: Радња: Specify the action that will be performed in game while this button is being used. Одредите радњу која ће се извршавати при употреби овог дугмета. Advanced Напредно Set Подеси Set %1 Скуп %1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [Без тастера] Calibration Form Start calibration Sticks: Reset settings Cancel Поништи Save Сачувај Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 Правац %1 CapturedWindowInfoDialog Captured Window Properties Особине откривеног прозора Information About Window Подаци о прозору Class: Класа: TextLabel Текст-натпис Title: Наслов: Path: Путања: Match By Properties Прилагоди по Class класи Title наслову Path путањи Full Path Пуна путања File Name Назив датотеке CommandLineUtility Profile location %1 is not an XML file. Путања до профила „%1“ није ИксМЛ датотека. Profile location %1 does not exist. Путања до профила „%1“ не постоји. No display string was specified. Није постављено »Display string«. Controller identifier is not a valid value. Означивач контролера нема ваљану вредност. No set number was specified. Није одређен број скупа. No controller was specified. Није одређен контролер. An invalid event generator was specified. Одређен је неважећи стваралац догађаја. No event generator string was specified. Није одређен назив ствараоца догађаја. Qt style flag was detected but no style was specified. Откривен је белег Кјут-стила али сам стил није одређен. No log level specified. Није одређен ниво извештавања. AntiMicroX version Издање програма Options Опције Print help text. Исписује овај текст помоћи. Print version information. Исписује податке о издању. Launch program in system tray only. Покреће програм само у обавештајној зони. Launch program with the tray menu disabled. Покреће програм не користећи обавештајну зону. Launch program without the main window displayed. Покреће програм без приказивања главног произора. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Покреће програм учитавајући датотеку са подешавањима обележену као подразумевана за одабрани контролер. Подразумевано је, примена на све контролере. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Примени датотеку са подешавањима на одређени контролер, чија вредност се може представити као индекс контролера, назив, или ЈИБГ. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Одбаци текући, укључени профил(е). Вредност се може представити као индекс контролера, назив, или ЈИБГ. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Покрени џојстик употребом одређеног скупа. Вредност се може представити као индекс контролера, назив, или ЈИБГ. Launch program as a daemon. Покрени програм као позадински процес. Enable logging. Укључује извештавање. Use specified display for X11 calls. Useful for ssh. Употребљава дати екран за Икс-11 позиве. Употребљиво за „ssh“. Choose between using XTest support and uinput support for event generation. Default: xtest. Одабир између Икс-тест и „uinput“ подршке за стварање догађаја. Подразумевано: „xtest“. Choose between using SendInput and vmulti support for event generation. Default: sendinput. Одабир између „SendInput“ и „vmulti“ подршке за стварање догађаја. Подразумевано: „sendinput“. Print information about joysticks detected by SDL. Приказује податке о џојсицима које је открио СДЛ. Open game controller mapping window of selected controller. Value can be a controller index or GUID. Отвори прозор придруживача тастера контролера за одабран контролер. Вредност може бити индекс контролера или ЈИБГ (енг. „GUID“). DPadContextMenu Mouse (Normal) Миш (обично) Mouse (Inverted Horizontal) Миш (обрнуто водоравно) Mouse (Inverted Vertical) Миш (обрнуто усправно) Mouse (Inverted Horizontal + Vertical) Миш (обрнуто водоравно и усправно) Arrows Стрелице Keys: W | A | S | D Тастери: Њ | А | С | Д NumPad Број.тастатура None Ништа Standard Уобичајено Eight Way Осмосмерно 4 Way Cardinal Уобичајено четворосмерно 4 Way Diagonal Четворосмерно-дијагонално Mouse Settings Поставке миша DPadEditDialog Dialog Прозорче Presets: Поставке: Mouse (Normal) Миш (нормално) Mouse (Inverted Horizontal) Миш (обрнуто водоравно) Mouse (Inverted Vertical) Миш (обрнуто усправно) Mouse (Inverted Horizontal + Vertical) Миш (обрнуто водоравно и усправно) Arrows Стрелице Keys: W | A | S | D Тастери: Њ | А | С | Д NumPad Бројчана тастатура None Ништа Dpad Mode: Употреба Д-тастера: &Name: 4 Way Cardinal Уобичајено четворосмерно 4 Way Diagonal Четворосмерно-дијагонално DPad Delay: Д-тастери — кашњење: Time lapsed before a direction change is taken into effect. Кашњење пре но промена смера приметно наступи. s с Specify the name of a dpad. Унесите назив за Д-тастер. Mouse Settings Поставке миша Standard Уобичајено Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Eight Way Осмосмерно Set Подеси Set %1 Скуп %1 EditAllDefaultAutoProfileDialog Default Profile Подразумеван профил Profile: Профил: Browse Разгледај Open Config Отвори подешавања Profile file path is invalid. Путања до датотеке профила није ваљана. ExtraProfileSettingsDialog Extra Profile Settings Додатна подешавања профила Key Press Time: Време притиска тастера: 0.00 ms 0.00 мс Profile Name: Назив профила: s сек. GameController Game Controller Контролер програма GameControllerDPad DPad Д-тастер GameControllerMappingDialog Game Controller Mapping Придруживач тастера контролера <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> <html><head/><body><p>Да би се у већини програма различити контролери (гејмпедови) употребљавали на јединствен начин програм Анти-микро употребљава програмско сучеље дефинисано у пројекту СДЛ издања2, а названо „Гејм-контролер АПИ“ (енг. <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">„Game Controller API“</span></a>). За придруживање тастера одаберите поље за придруживање у реду одговарајућег тастера, а након тога притисните неки тастер на гејмпеду или померите ручицу управљача правца на њему. У пољу за придруживање ће се појавити подаци стварног (физичког) тастера или ручице управљача који ће се употребљавати.</p><p>Анти-микро ће да употреби ова придруживања за чување знаковних ниски придруживања које се могу учитавати помоћу СДЛ програма.</p></body></html> A 3 B 2 X 4 Y 1 Back Назад Start Почни Guide Водич Left Shoulder Леви окидач 1 Right Shoulder Десни окидач 1 Left Stick Click Притисак на леви управљач Right Stick Click Притисак на десни управљач Left Stick X Леви управљач — водоравно Left Stick Y Леви управљач — усправно Right Stick X Десни управљач — водоравно Right Stick Y Десни управљач — усправно Left Trigger Леви окидач 2 Right Trigger Десни окидач 2 DPad Up Д-тастер — Горе DPad Left Д-тастер — Лево DPad Down Д-тастер — Доле DPad Right Д-тастер — Десно Mapping Придруживања SDL 2 Game Controller Mapping String СДЛ-2 ниска придруживања тастера контролера Last Axis Event: Задњи догађај на правцу: Current Axis Detection Dead Zone: Откривање мртве области текућег правца: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Придруживач тастера контролера (%1) (#%2) Discard Controller Mapping? Поништавање придруживања контролера? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. Да ли да поништим придруживања за овај контролер? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. GameControllerSet Back Назад Guide Водич Start Почни LS Click Притисак 1. левог окидача RS Click Притисак 1. десног окидача L Shoulder 1. леви окидач R Shoulder 1. десни окидач L Trigger 2. леви окидач R Trigger 2. десни окидач GameControllerTrigger Trigger Окидач JoyAxis Axis Правац JoyAxisButton Negative Умањи Positive Увећај Unknown Непознато Button Дугме JoyAxisContextMenu Mouse (Horizontal) Миш (водоравно) Mouse (Inverted Horizontal) Миш (обрнуто водоравно) Mouse (Vertical) Миш (усправно) Mouse (Inverted Vertical) Миш (обрнуто усправно) Arrows: Up | Down Стрелице: Горе | Доле Arrows: Left | Right Стрелице: Лево | Десно Keys: W | S Тастери: Њ | С Keys: A | D Тастери: А | Д NumPad: KP_8 | KP_2 Број.Тастатура: КП_8 | КП_2 NumPad: KP_4 | KP_6 Број.Тастатура: КП_4 | КП_6 None Ништа Mouse Settings Поставке миша Left Mouse Button Леви тастер миша Right Mouse Button Десни тастер миша JoyButton Processing turbo for #%1 - %2 Буџим за #%1 - %2 Finishing turbo for button #%1 - %2 Завршено набуџивање тастера #%1 - %2 Processing press for button #%1 - %2 Притискам за тастер #%1 - %2 Processing release for button #%1 - %2 Отпуштам за тастер #%1 - %2 Distance change for button #%1 - %2 Промена раздаљине за тастер #%1 - %2 Button Тастер [NO KEY] [Без тастера] [Set %1 1W] [Скуп %1 1-смерно] [Set %1 2W] [Скуп %1 2-смерно] [Set %1 WH] [Скуп %1 WH] JoyButtonContextMenu Toggle Преклопи Turbo Набуџи Clear Очисти Set Select Одабир скупа Disabled Онемогућено Set %1 Скуп %1 Set %1 1W Скуп %1 1-смерно Set %1 2W Скуп %1 2-смерно Set %1 WH Скуп %1 WH JoyButtonSlot Mouse Миш Up Напред Down Назад Left Лево Right Десно LB Л.дугме MB С.дугме RB Д.дугме B4 Дугме 4 B5 Дугме 5 Pause Пауза Hold Држи Cycle Врти Distance Раздаљина Release Пусти Mouse Mod Мишар Press Time Трајање притиска Delay Кашњење Load %1 Учитај %1 Set Change %1 Измена скупа %1 [Text] %1 [Текст] %1 [Exec] %1 [Извршавам] %1 [NO KEY] [Без тастера] JoyControlStick Stick Управљач JoyControlStickButton Up Напред Down Назад Left Лево Right Десно Button Дугме JoyControlStickContextMenu Mouse (Normal) Миш (обично) Mouse (Inverted Horizontal) Миш (обрнуто водоравно) Mouse (Inverted Vertical) Миш (обрнуто усправно) Mouse (Inverted Horizontal + Vertical) Миш (обрнуто водоравно и усправно) Arrows Стрелице Keys: W | A | S | D Тастери: Њ | А | С | Д NumPad Број.тастатура None Ништа Standard Уобичајено Eight Way Осмосмерно 4 Way Cardinal Уобичајено четворосмерно 4 Way Diagonal Четворосмерно-дијагонално Mouse Settings Поставке миша JoyControlStickEditDialog Dialog Прозорче X: X: 0 0 Y: Y: Distance: Раздаљина: Presets: Поставке: Mouse (Normal) Миш (обично) Mouse (Inverted Horizontal) Миш (обрнуто водоравно) Mouse (Inverted Vertical) Миш (обрнуто усправно) Mouse (Inverted Horizontal + Vertical) Миш (обрнуто водоравно и усправно) Arrows Стрелице Keys: W | A | S | D Тастери: Њ | А | С | Д NumPad Бројчана тастатура None Ништа Stick Mode: Начин рада управљача: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Уобичајено: 8-смерни управљач са два притиснута тастера за померање по дијагонали. Осмосмерно: 8-смерни управљач са сопственим тастерима за сваки смер. У једном тренутку, радни је само један тастер. Употребљиво за роголике (енг. „rougelike“) игре. Уобичајено 4-смерно: 4-смерни управљач за померање у 4 смера (померена за 90°). Употребљиво за изборнике. 4-смерно дијагонално: 4-смерни управљач где свака област одговара дијагоналној области датог управљача. 4 Way Cardinal Уобичајено четворосмерно 4 Way Diagonal Четворосмерно-дијагонално Dead zone value to use for an analog stick. Вредност мртве области код аналогних управљача. Value when an analog stick is considered moved 100%. Вредност у којој је аналогни управљач у крајњем положају. The area (in degrees) that each diagonal region occupies. Област (у степенима) коју свака област на дијагонали заузима. Square Stick: Четвртаст управљач: Percentage to modify a square stick coordinates to confine values to a circle Постотак промене квадратних координата управљача за ограничавање вредности у кружници % % Stick Delay: Кашњење управљача: Time lapsed before a direction change is taken into effect. Кашњење пре но промена смера приметно наступи. s с Modifier: Измењивач: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. Дугме за уређивање који је радно док управљач ради. Употребљиво за доделе области тастерима-измењивачима који могу да се употребе за додавање могућности ходај-трчи аналогним управљачима. PushButton Дугме Na&me: Name: Назив: Specify the name of an analog stick. Унесите назив за аналогни управљач. Mouse Settings Поставке миша Standard Уобичајено Bearing: Азимут: % Safe Zone: % Безбедна област: Eight Way Осмосмерно Dead Zone: Мртва област: Max Zone: Највиша област: Diagonal Range: Дијагонални опсег: Set Постави Set %1 Скуп %1 JoyControlStickModifierButton Modifier Измењивач JoyDPad DPad Д-тастер JoyDPadButton Up Горе Down Доле Left Лево Right Десно Button Дугме JoyTabWidget <New> <Ново> Remove Уклони Remove configuration from recent list. Уклони подешавање са текуће листе. Load Учитај Load configuration file. Учитај датотеку са подешавањима. Save Сачувај Save changes to configuration file. Сачувај измене у датотеку подешавања. Save As Сачувај као Save changes to a new configuration file. Сачувај измене у новој датотеци подешавања. Sets Скупови Copy from Set Умножи из ... Settings Постави називе Set 1 1. скупа Set 2 2. скупа Set 3 3. скупа Set 4 4. скупа Set 5 5. скупа Set 6 6. скупа Set 7 7. скупа Set 8 8. скупа Stick/Pad Assign Придружи Управљач/Тастатуру Controller Mapping Придруживач тастера контролера Quick Set Брзе поставке Names Називи Toggle button name displaying. Приказивање назива преклопника. Pref Опште поставке Change global profile settings. Измените опште поставке профила. Reset Поништи Revert changes to the configuration. Reload configuration file. Поништи измене и учитај опет датотеку са подешавањем. Open Config Отвори подешавања Config Files (*.amgp *.xml) Датотеке подешавања (*.amgp *.xml) Config File (*.%1.amgp) Датотека подешавања (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? Да ли да сачувам измене профила? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Имате несачуваних промена новог профила. Да ли желите да их сачувам или да их поништим? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Имате несачуваних промена у профилу "%1" . Да ли желите да их сачувам или да их поништим? Sticks Управљачи DPads Д-тастери No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Нема придруживања за дугмад. Можете да употребите „Брзе поставке“ за придруживања дугмадима или да искључите скривање „празних“ дугмади. Set %1: %2 Скуп %1: %2 Set %1 Скуп %1 Copy Set Assignments Умножи придруживања из скупа Are you sure you want to copy the assignments and device properties from %1? Да ли заиста желите да умножите придруживања и особине уређаја из %1? Save Config Сачувај подешавања Set Постави Joystick Joystick Џојстик JoystickStatusWindow Properties Особине Details Детаљи Name: Назив: %1 %1 Number: Број: Axes: Праваца: Buttons: Дугмад: Hats: Капице: Battery: Unknown Непознато GUID: ЈИБГ: Game Controller: Контролер за игре: Axes Правци Buttons Дугмад Hats Капице %1 (#%2) Properties %1 (#%2) Особине Axis %1 Правац %1 Hat %1 Хат %1 No Не Yes Да MainSettingsDialog Edit Settings Уређивање поставки General Опште поставке Controller Mappings Придруживања контролера Language Језик Auto Profile Ауто-профил Mouse Миш Advanced Напредно <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Постављање уобичајеног директоријума за учитавање постојећих или чување нових профила.</p></body></html> Recent Profile Count: Број скорашњих профила: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Број профила који се може сместити у листу недавно употребљаваних профила. Број 0 означава приказ свих употребљаваних профила.</p></body></html> Gamepad Poll Rate: Провера порука џојстика након: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Измените време након кога ће програм да провери да ли је гејмпед производио догађаје (поруке). Уобичајена вредност је 10 мс. Ниже вредности ове опције могу да доведу до веће употребе ЦПЈ (процесора), Проверите ову поставку пре озбиљније употребе. Hide main window when the main window close button is clicked instead of quitting the program. Притиском на дугме затварања главног прозора, он се затвара али програм остаје покренут у обавештајној зони. Close To Tray Смести у обавештајну зону Have Windows start AntiMicroX at system startup. Покрени програм са покретањем система. Launch At Windows Startup Покрени по покретању система Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Приказаће се скорашњи профили за све контролере као јединствен списак профила у обавештајној зони. Уобичајено је употреба под-изборника. Single Profile List in Tray Јединствен списак профила у обавештајној зони Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Програм ће се сместити у траку покренутих задатака. Подразумевано смештање програма је у обавештајној зони ако је она доступна. Minimize to Taskbar Смести у траку покренутих задатака This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Ако је укључена ова опција, програм ће скрити дугмад која немају придружених слотова. У прозору „Брзе поставке“ моћи ћете да подесите придруживања тастера гејмпеда. Hide Empty Buttons Сакриј „празну“ дугмад When the program is launched, open the last known profile that was opened during the previous session. Ово омогућава да се по покретању програма учита познат, последње учитаван профил у претходној сесији. Auto Load Last Opened Profile Отвори сам последњи употребљени профил Only show the system tray icon when the program first launches. Приказује само икону у обавештајној зони по првом покретању програма. Launch in Tray Покрени у обавештајној зони Associate .amgp files with AntiMicroX in Windows Explorer. Придружуј „.amgp“-датотеке програму Анти-микро (виндоуз експлорер). Associate Profiles Придружени профили Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Вишеструки притисци тастера Active keys will be repeatedly pressed when this option is enabled. Ако је укључено омогућени су вишеструки, узастопни притисци тастера. Enable Омогућено Specifies how much time should elapse before key repeating begins. Кашњење пре започињања вишеструког, узастопног притискања тастера. Specifies how many times key presses will be performed per seconds. Одређује број притисака тастера у секунди код вишеструког, узастопног притискања тастера. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>Сарадници аутора су локализовали програм за разне језике. Уобичајено, програм ће употребљавати језичке поставке самог система за приказ, али, уколико то желите, можете употребљавати програм и на језику који одаберете на листи испод.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Ништа Error Warning Info Подаци Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset Поништи French француски Russian руски Serbian српски Ukrainian украјински Class класи Title наслову Program Програм Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Искључи виндоуз-поставку за „побољшање прецизности показивача“ док програм ради. Онемогућавањем ове виндоуз-поставке повећава се прецисност померања показивача (миша) у самом програму. Disable Enhance Pointer Precision Искључи побољшања прецизности показивача Smoothing Углађеност Refresh Rate: Брзина освежавања: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Брзина освежавања представља протекло време између догађаја миша. Будите врло опрезни при уређивању ове поставке јер се може повећати употреба ЦПЈ (процесора), а при премалим вредностима ове поставке систем може да пређе у нестабилно стање. Проверите ову поставку пре озбиљније употребе. Spring Скоковито Screen: Екран: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Употребљава наведени екран за „скоковит“ режим. Уобичајено, На ГНУ-Линуксу је употреба основног екрана, а на Виндоузу свих расположивих екрана. Accel Numerator: Бројилац убрзања: 0 0 Accel Denominator: Именилац убрзања: Accel Threshold: Праг убрзања: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Када су вредности убрзања патвореног миша измењене од стране различитих процеса, посебно при изласку из старијих игара, можете пожелети да вратите ове вредности убрзања патвореног миша на оне претходне. Reset Acceleration Поврати убрзање Delay: Кашњење: Pro&file Directory: ms мс Rate: Брзина: times/s пута/сек. Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. Испод је листа сачуваних, прилагођених мапирања. Можете да употребите следећу табелу да бисте избрисали мапирања или да их привремено онемогућите. Можете да онемогућите мапирања која су укључена у СДЛ; само уметните нови ред са одговарајућим ЈИБГ-џојстика и означите онемогући. Подешавања се неће узети у обзир док се не освежи листа доступних џојстика или док не искључите дати, конкретан џојстик. GUID ЈИБГ Mapping String Ниска придруживања Disable? Искључи? Delete Уклони Insert Уметни Default подразумевано Brazilian Portuguese португалски (Бразил) English енглески German немачки Active Омогућен Devices: Уређаји: All Сви Device Уређај Profile Профил Default? Подразумевано? Add Додај Edit Уреди Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. Такође, Виндоуз корисници који желе да употребе нижу вредност, нека провере и „Искључи побољшања прецизности показивача“, ако нису онемогућили ову опцију у самом систему. Select Default Profile Directory Одабир уобичајеног директоријум профила Are you sure you want to delete the profile? Да ли заиста желите да уклоните овај профил? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [Без тастера] MainWindow No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Нисам пронашао џојстик. Када га прикључите покрените „Поставке > Пронађи џојстике“ из главног менија If events are not seen by a game, please click here to run this application as Administrator. &App &Датотека Stick/Pad Assign Придружи Управљач/Тастатуру &Options П&оставке AntiMicroX Анти-микро If events are not seen by a game, please click here to run this application as the Adminstrator. Ако догађаје игра не „види“, притисните ово дугме за покретање овог програма као администратор. &Help &Помоћ He&lp &Quit &Затвори Ctrl+Q Ctrl+Q &Update Joysticks Про&нађи џојстике Ctrl+U Ctrl+U &Hide &Сакриј Ctrl+H Ctrl+H &About О прогр&аму Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt О КјуТ Properties Особине Key Checker Провера тастера тастатуре Home Page Матична страна GitHub Page Гит-хаб страна Game Controller Mapping Придруживач тастера контролера Settings Постави називе Wiki Вики-стране Could not find a proper controller identifier. Exiting. (%1) (%1) Open File Отвори датотеку %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore В&рати Calibration couldn't be opened You must connect at least one controller to open the window Run as Administrator? Покрени као администратор? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. Да ли заиста желите да покренете програм уз администраторске дозволе? Неки програми покренути уз администраторске дозволе могу да доведу до тога да радње које захтева Анти-микро не буду ваљано препознате све док се и сам Анти-микро не покрене уз исте дозволе. Код Видоуз-Виста или новијих виндоуза ово је изазвано проблемима са дозволама које ствара опција за управљање корисничким налозима (енг. скр. „UAC“). Failed to elevate program Не могу да покренем програм Failed to restart this program as the Administrator Неуспело покретање програма са админ. дозволама Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Поставке миша - Set %1 Скуп %1 MouseButtonSettingsDialog Mouse Settings - Поставке миша - Set %1 Скуп %1 MouseControlStickSettingsDialog Mouse Settings Поставке миша Set %1 Скуп %1 MouseDPadSettingsDialog Mouse Settings Поставке миша Set %1 Скуп %1 MouseSettingsDialog Mouse Settings Поставке миша Mouse Mode: Мишар: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. У начину „показивач“, омогућава се релативно померање показивача миша у односу на његову текућу позицију. У „скоковитом“ начину померање показивача миша је од средишта екрана у свим смеровима, а када се показивач миша нађе у мртвој области програм га враћа на средину екрана. Cursor Показивач Spring Скоковито Acceleration: Убрзавање: Enhanced Precision Побољшана прецизност Linear Линеарно Quadratic Квадратно Cubic Кубно Quadratic Extreme Набуџено квадратно Power Function Нај-функција Easing Quadratic Квадратно попуштање Easing Cubic Кубно попуштање Mouse Speed Settings Брзина померања Enable to change the horizontal and vertical speed boxes at the same time. Омогућује истовремену промену брзине у оба правца. Change Together Измењуј повезано Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: Horizontal Speed: Лево→Десно: 1 = 20 pps 1 = 20 тачака/сек. Vertical Speed: Горе→Доле: Wheel Hori. Speed: Tочкић водоравно: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Постављање брзине водоравног померања миша према одговарајућем, симулираном броју зареза по секунди. Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Постављање брзине усправног померања миша према одговарајућем, симулираном броју зареза по секунди. Sensitivit&y: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. За кривуљу убрзавања Нај-функције. Одређује чинилац код постављања осетљивости кривуље. За вредност изнад 1.0, покрети миша ће се више убрзавати у крајњем доњем положају осе. Easing Duration: Трајање попуштањa: s с Extra Acceleration Додатно убрзање Multiplier: Чинилац: Highest value to accelerate mouse movement by Највиша вредност за убрзање померања миша x x Start %: Почетак %: Acceleration begins at this percentage of the base multiplier Убрзање почиње након оволико процената од основног чиниоца Min Threshold: Најмањи праг: Minimum amount of axis travel required for acceleration to begin Најмања количина осног померања неопходна за отпочињање убрзања Max Threshold: Највећи праг: Maximum axis travel before acceleration has reached the multiplier value Највиша количина осног померања пре но се достигне вредност датог чиниоца E&xtra Duration: Curve: Ease Out Sine Ease Out Quad Ease Out Cubic Release Radius: Пречник пуштања: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Одређује да ће „скоковито“ подручје бити релативно у односу на положај миша постављен не-релативним скоком. Relative Релативно Mouse Status Стање миша X: X: 0 (0 pps) 0 (0 тачака/сек) Y: Y: 1 = 1 notch(es)/s 1 = 1 зарез(а)/сек. Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Подиже брзину померања миша 1,5 пута по достизању 95% осног пута Побољшана прецизност: Трослојна кривуља која чини да померање миша буде споро на доњем крају осе и брзо на њеном горњем крају. Линеарно: Померања миша је сразмерно по оси. Квадратно: Померања миша се лагано убрзавају на доњем крају. Кубно: Спорије убрзавање миша од „Квадратног“. Набуџено квадратно: Подиже брзину померања миша 1,5 пута по достизању 95% од могућег осног померања. Нај-функција: Дозвољава потпуније прилагођавање кривуље убрзавања. Квадратно попуштање: У горњем крају осе, постепено убрзање током времена употребљавајући квадратну кривуљу. Кубно попуштање: У горњем крају осе, постепено убрзање током времена употребљавајући кубну кривуљу. Hori&zontal Speed: &Vertical Speed: Wheel Vert. Speed: Tочкић усправно: Sensitivity: Осетљивост: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. Одређује количину времена (у секундама) неопходну за потпуно убрзање миша, а након достизања горњег краја осе. % % Extra Duration: Додатно трајање: Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Продужује време за које ће се применити додатно убрзање. У обзир ће се узети осно померање. Спорији „флик“ смањује стварно време након кога ће се примењивати додатно убрзање. Spring Settings Скоковито померање Spring Width: По ширини: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Мењање ширине области за померање показивача у скоковитом начину. „0“ означава искоришћавање укупне ширине Вашег екрана. Spring Height: По висини: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Мењање висине области за померање показивача у скоковитом начину. „0“ означава искоришћавање укупне висине Вашег екрана. %n notch(es)/s %n зарез/сек. %n зареза/сек. %n зареза/сек. ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Поништи OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Провера тастера тастатуре <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>Притисните тастер на тастатури да бисте видели како је овај програм открио одговарајућу вредност. У прозору ће се приказати вредност руковаоца догађаја, вредност у КјуТ-библиотекама (по потреби), као и прилагођена вредност у Анти-микро програму.</p><p>Вредности које су откривене програмима Анти-микро и КјуТ ће обично бити идентичне. јер Анти-микро употребљава вредности КјуТ-библиотека када је то могуће. Погледајте страницу на мрежи <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum (енг.)</span></a> за вредности одређене за употребу КјуТ-програмима. Ако откријете неке неподржане вредности за тастере у овом програму, известите о том проблему на <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">Анти-микро гит-странама</span></a>, а у циљу исправљања уочених недостатака. Како год, додат је предложак за непознате вредности да би се програм могао употребљавати, али остаје главни проблем који се односи на преносивост профила.</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Руковалац догађајем: Native Key Value: Очитана вредност: 0x00000000 0x00000000 Qt Key Value: КјуТ вредност: antimicro Key Value: AntiMicroX Key Value: Анти-микро вредност: QObject Super Супер Menu Изборник Mute Мук Vol+ Гласније Vol- Тише Play/Pause Пусти/Пауза Play Пусти Pause Пауза Prev Претходно Next Наредно Mail Е-пошта Home Почетно Media Медији Search Нађи Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Покренут је позадински процес Failed to launch daemon Није успело покретање позадинског процеса Launching daemon Покрећем позадински процес Display string "%1" is not valid. Није ваљана »Display string „%1“«. Failed to set a signature id for the daemon Није успело постављање ИБ-потписа за позадински процес Failed to change working directory to / Не могу да поставим „/“ као радни директоријум Quitting Program Излазак из програма # of joysticks found: %1 # џојстика пронађено: %1 List Joysticks: Списак џојстика: --------------- --------------- Joystick %1: Џојстик %1: Index: %1 Индекс: %1 GUID: %1 ЈИБГ: %1 UniqueID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Назив: %1 Yes Да No Не Game Controller: %1 Контролер програма: %1 # of Axes: %1 # праваца: %1 # of Buttons: %1 # тастера: %1 # of Hats: %1 # капица: %1 Attempting to use fallback option %1 for event generation. Покушавам да користим резервну опцију %1 у стварању догађаја. Failed to open event generator. Exiting. Не могу да отворим ствараоца догађаја. Излазим. Using %1 as the event generator. Употребљавам %1 као ствараоца догађаја. Could not raise process priority. Не могу да повисим приоритет процеса. Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Путања до профила „%1“ није ИксМЛ датотека. Profile location %1 does not exist. Путања до профила „%1“ не постоји. Controller identifier is not a valid value. Означивач контролера нема ваљану вредност. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. Није одређен број скупа. No controller was specified. Није одређен контролер. No display string was specified. Није постављено »Display string«. An invalid event generator was specified. Одређен је неважећи стваралац догађаја. No event generator string was specified. Није одређен назив ствараоца догађаја. Qt style flag was detected but no style was specified. Откривен је белег Кјут-стила али сам стил није одређен. No log file specified. AntiMicroX version Издање програма Options Опције Print help text. Исписује овај текст помоћи. Print version information. Исписује податке о издању. Launch program in system tray only. Покреће програм само у обавештајној зони. Launch program with the tray menu disabled. Покреће програм не користећи обавештајну зону. Launch program without the main window displayed. Покреће програм без приказивања главног произора. Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. Покреће програм учитавајући датотеку са подешавањима обележену као подразумевана за одабрани контролер. Подразумевано је, примена на све контролере. Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. Примени датотеку са подешавањима на одређени контролер, чија вредност се може представити као индекс контролера, назив, или ЈИБГ. Unload currently enabled profile(s). Value can be a controller index, name, or GUID. Одбаци текући, укључени профил(е). Вредност се може представити као индекс контролера, назив, или ЈИБГ. Start joysticks on a specific set. Value can be a controller index, name, or GUID. Покрени џојстик употребом одређеног скупа. Вредност се може представити као индекс контролера, назив, или ЈИБГ. Launch program as a daemon. Покрени програм као позадински процес. Enable logging. Укључује извештавање. Use specified display for X11 calls. Useful for ssh. Употребљава дати екран за Икс-11 позиве. Употребљиво за „ssh“. Choose between using XTest support and uinput support for event generation. Default: xtest. Одабир између Икс-тест и „uinput“ подршке за стварање догађаја. Подразумевано: „xtest“. Choose between using SendInput and vmulti support for event generation. Default: sendinput. Одабир између „SendInput“ и „vmulti“ подршке за стварање догађаја. Подразумевано: „sendinput“. Print information about joysticks detected by SDL. Приказује податке о џојсицима које је открио СДЛ. Open game controller mapping window of selected controller. Value can be a controller index or GUID. Отвори прозор придруживача тастера контролера за одабран контролер. Вредност може бити индекс контролера или ЈИБГ (енг. „GUID“). Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. Издање проширење „xinput“ је старије од издања 2.0. Нису могуће измене брзина при руковању мишем. QuickSetDialog Quick Set Брзе поставке <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Притисните неки тастер или померите управљач на уређају <br/>„%1“ (<span style=" font-weight:600;">%2</span>). Након тога, појавиће се прозорче <br/>у којем ћете моћи да придружите том тастеру-управљачу <br/>одговарајући тастер тастатуре, догађај и сл.</p></body></html> Quick Set %1 Брзе поставке — %1 SetAxisThrottleDialog Throttle Change Промена регулатора The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? Поставке регулатора за правац %1 су се промениле. Желите ли да ове промене регулатора буду доступне у свим групама? SetJoystick Set %1: %2 Скуп %1: %2 Set %1 Скуп %1 SetNamesDialog Set Name Settings Поставке назива скупова Set 1 1. скуп Set 2 2. скуп Set 3 3. скуп Set 4 4. скуп Set 5 5. скуп Set 6 6. скуп Set 7 7. скуп Set 8 8. скуп Name Назив SimpleKeyGrabberButton Mouse Миш SpringModeRegionPreview Spring Mode Preview Преглед за начин „Скоковито“ UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Не могу да нађем ваљану „uinput“-датотеку уређаја. Проверите да ли је „uinput“-модул учитан. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Не могу да отворим „uinput“-датотеку уређаја Проверите да ли имате дозволу за уписивање на уређај Using uinput device file %1 Употребљавам „uinput“-датотеку уређаја %1 UInputHelper a а b б c ц d д e е f ф g г h х i и j ј k к l л m м n н o о p п q љ r р s с t т u у v в w њ x џ y ж z з Esc Врати („Esc“) F1 Ф1 F2 Ф2 F3 Ф3 F4 Ф4 F5 Ф5 F6 Ф6 F7 Ф7 F8 Ф8 F9 Ф9 F10 Ф10 F11 Ф11 F12 Ф12 F13 Ф13 F14 Ф14 F15 Ф15 F16 Ф16 F17 Ф17 F18 Ф18 F19 Ф19 F20 Ф20 F21 Ф21 F22 Ф22 F23 Ф23 F24 Ф24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace Уназад Tab Таб [ [ ] ] \ \ CapsLock В.слова ; ; ' ' Enter Унеси Shift_L л.Мењач , , . . / / Ctrl_L л.Ктрл Super_L л.Супер Alt_L л.Алт Space Размакница Alt_R д.Алт Menu Изборник Ctrl_R д.Ктрл Shift_R д.Мењач Up Горе Left Лево Down Доле Right Десно PrtSc Сликај Ins Уметни Del Бриши Home Почетак End Крај PgUp Страна изнад PgDn Страна испод NumLock УКЉ/ ИСКЉ * * + + KP_Enter КП_Унеси KP_1 КП_1 KP_2 КП_2 KP_3 КП_3 KP_4 КП_4 KP_5 КП_5 KP_6 КП_6 KP_7 КП_7 KP_8 КП_8 KP_9 КП_9 KP_0 КП_0 SCLK SCLK Pause Пауза Super_R д.Супер Mute Мук VolDn Тише VolUp Гласније Play Пусти Stop Заустави Prev Претходно Next Наредно [NO KEY] [Без тастера] UnixWindowInfoDialog Captured Window Properties Особине откривеног прозора Information About Window Подаци о прозору Class: Класа: TextLabel Текст-натпис Title: Наслов: Path: Путања: Match By Properties Прилагоди по Class класи Title наслову Path путањи VDPad VDPad Патворен Д-тастер VirtualKeyPushButton Space Размакница Tab Таб Shift (L) л. Мењач Shift (R) д. Мењач Ctrl (L) л. Ктрл Ctrl (R) д. Ктрл Alt (L) л. Алт Alt (R) д. Алт Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps В.слова ; ; ' ' , , . . / / ESC Врати PRTSC Сликај SCLK SCLK INS Уметни PGUP Страна изнад DEL Бриши PGDN Страна испод 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK УКЉ/ ИСКЉ * * + + Enter Унеси Del Бриши E N T E R У Н Е С И < < : : Super (L) л.Супер Menu Избор Up Горе Down Доле Left Лево Right Десно VirtualKeyboardMouseWidget Keyboard Тастатура Mouse Миш Mouse Settings Поставке миша Left Mouse Лево Up Mouse Горе Left Button Mouse Леви тастер Middle Button Mouse Средњи тастер Right Button Mouse Десни тастер Wheel Up Mouse Точкић унапред Wheel Left Mouse Точкић улево Wheel Right Mouse Точкић удесно Wheel Down Mouse Точкић уназад Down Mouse Доле Right Mouse Десно Button 4 Mouse Тастер 4 Mouse 8 Mouse Миш 8 Button 5 Mouse Тастер 5 Mouse 9 Mouse Миш 9 NONE НИШТА [NO KEY] [Без тастера] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Applications Програми Browser Back Претходно (веб прегледник) Browser Favorites Обележивачи (веб прегледник) Browser Forward Наредно (веб прегледник) Browser Home Почетна страна (веб прегледник) Browser Refresh Освежи (веб прегледник) Browser Search Претрага (веб прегледник) Browser Stop Заустави учитавање (веб прегледник) Calc Калкулатор Email Е-пошта F13 Ф13 F14 Ф14 F15 Ф15 F16 Ф16 F17 Ф17 F18 Ф18 F19 Ф19 F20 Ф20 F21 Ф21 F22 Ф22 F23 Ф23 F24 Ф24 Media Медији Media Next Медији — Наредно Media Play Медији — Пусти Media Previous Медији — Претходно Media Stop Медији — Заустави Search Нађи Volume Down Тише Volume Mute Мук Volume Up Гласније VirtualMousePushButton INVALID ОШТЕЋЕНО WinAppProfileTimerDialog Capture Application Разоткриј прозор After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. По притиску дугмета „Разоткриј прозор“, одаберите прозор програма који желите да повежете са профилом. Разоткривање тог прозора отпочеће након истека доле задатог времена. Timer: Након: Seconds секунди(е,а) Cancel Поништи WinExtras [NO KEY] [Без тастера] AntiMicroX Profile Профил за Анти-микро X11Extras ESC Врати Tab Таб Space Размакница DEL Бриши Return Унеси („Return“) („Enter“) KP_Enter КП_Унеси Backspace Уназад Alt Gr xinput extension was not found. No mouse acceleration changes will occur. Није нађено проширење „xinput“. Нису могуће измене брзина при руковању мишем. xinput version must be at least 2.0. No mouse acceleration changes will occur. Издање проширење „xinput“ је старије од издања 2.0. Нису могуће измене брзина при руковању мишем. Virtual pointer found with id=%1. Нађен је патворени показивач са ИБ=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Није нађено „НPtrFeedbackClass“ за патворени показивач. Нису могуће измене брзина при руковању мишем за уређај чији је ИБ=%1 Changing mouse acceleration for device with id=%1 Измена убрзања при употреби миша за уређај чији је ИБ=%1 XMLConfigReader Could not write updated profile XML to file %1. Не могу да упишем зановљен ИксМЛ-профил у датотеку %1. XMLConfigWriter Could not write to profile at %1. Не могу да уписујем у профил у %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Покреће програм само у обавештајној зони. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_uk.ts000066400000000000000000013270451377703515000275230ustar00rootroot00000000000000 AboutDialog About Про програму Version Версія Credits Розробники "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Changelog Info Інформація AntiMicroX <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> About Development Copyright: 2013 - 2020 License Ліцензія Program Version %1 Версія програми %1 Program Compiled on %1 at %2 Програму скомпільовано %1 о %2 Built Against SDL %1 Зібрано на SDL %1 Running With SDL %1 Запущено з SDL %1 Using Qt %1 Використано Qt %1 Using Event Handler: %1 Обробник подій: %1 AddEditAutoProfileDialog Auto Profile Dialog Вікно автоматичного профілю Profile: Профіль: Pro&file: Browse Оглянути Window: Select Window. Click on the appropriate application window and the application file path will be populated in the form. Оберіть вікно. Натисніть на вікно необхідного додатку, і шлях до нього автоматично заповниться в поле вводу. Detect Window Properties &Class: T&itle: set partial title Application: Select Обрати De&vices: Devices: Пристрої: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Оберіть цей профіль як типовий для вказаного пристрою. Обраний профіль перекриватиме загальні налаштування типового профілю. Set as Default for Controller Встановити типовим для контролера A different profile is already selected as the default for this device. Інший профіль вже встановлено типовим для вказаного пристрою. Current (%1) Поточний (%1) Open Config Відкрити конфігурацію Select Program Обрати програму Please use the main default profile selection. Використовуйте основний типовий профіль. Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. Оберіть мишкою вікно. Аби скасувати вибір натисніть Escape. Capture Application Window Захоплення вікна програми Could not obtain information for the selected window. Не отримано інформації для обраного вікна. Application Capture Failed Захоплення програми зазнало невдачі Profile file path is invalid. Шлях до профілю хибний. No window matching property was specified. Program path is invalid or not executable. Шлях до програми хибний, або вона не має прав на виконання. No window matching property was selected. AdvanceButtonDialog Advanced Розширені параметри Assignments Призначення Toggle Перемикач Turbo Турбо Set Selector Встановити селектор Press Time Час натиску Insert a pause that occurs in between key presses. Вставте паузу між натисканнями клавіш. Pause Пауза Hold Утримання Mouse Mod Мод. мишки Cycle Цикл Distance Дистанція Release Віджати Blank or KB/M Delay Затримка Execute Load Завантажити Set Change Text Entry Insert a new blank slot. Вставити новий пустий слот. Insert Вставити Join Split Delete a slot. Вилучити слот. Delete Вилучити Clear all currently assigned slots. Очистити всі поточні слоти. Clear All Очистити все Placeholder Заповнювач Specify the duration of an inserted Pause or Hold slot. Встановити тривалість слотів Пауза чи Утримання. Time: Час: 0.01s 0.01с 0m 0хв 0 0 0s Mouse Speed Mod: Зміна швидкості мишки: &Mouse Speed Mod: Set the percentage that mouse speeds will be modified by. Встановіть зміну швидкості миші у відсотковому співвідношенні. % % Specify the range past an axis dead zone in which a sequence of actions will execute. Distance: Дистанція: Auto Reset Cycle After Автоматично скидати цикл опісля seconds секунд Executable: ... Arguments: Enabled Включити Mode: Режим: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Звичайний Gradient Наростаючий Pulse Пульсуючий Delay: Затримка: 0.10s 0.10с Rate: Частота: 10.0/s 10.0/с Disabled Вимкнено Select Set 1 One Way Встановити набір 1 одностороннім Select Set 1 Two Way Встановити набір 1 двостороннім Select Set 1 While Held Встановити набір 1 доки натиснуто Select Set 2 One Way Встановити набір 2 одностороннім Select Set 2 Two Way Встановити набір 2 двостороннім Select Set 2 While Held Встановити набір 2 доки натиснуто Select Set 3 One Way Встановити набір 3 одностороннім Select Set 3 Two Way Встановити набір 3 двостороннім Select Set 3 While Held Встановити набір 3 доки натиснуто Select Set 4 One Way Встановити набір 4 одностороннім Select Set 4 Two Way Встановити набір 4 двостороннім Select Set 4 While Held Встановити набір 4 доки натиснуто Select Set 5 One Way Встановити набір 5 одностороннім Select Set 5 Two Way Встановити набір 5 двостороннім Select Set 5 While Held Встановити набір 5 доки натиснуто Select Set 6 One Way Встановити набір 6 одностороннім Select Set 6 Two Way Встановити набір 6 двостороннім Select Set 6 While Held Встановити набір 6 доки натиснуто Select Set 7 One Way Встановити набір 7 одностороннім Select Set 7 Two Way Встановити набір 7 двостороннім Select Set 7 While Held Встановити набір 7 доки натиснуто Select Set 8 One Way Встановити набір 8 одностороннім Select Set 8 Two Way Встановити набір 8 двостороннім Select Set 8 While Held Встановити набір 8 доки натиснуто [NO KEY] [НЕМАЄ КНОПКИ] sec. сек. /sec. /сек. Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 Набір %1 Select Set %1 Обрати набір %1 One Way Односторонній Two Way Двосторонній While Held Доки натиснуто Choose Executable Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. Chose a profile to load when this slot is activated. Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. Specify the time that keys past this slot should be held down. Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. Change to selected set once slot is activated. Full string will be typed when a slot is activated. Execute program when slot is activated. Choose Profile Config Files (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment Призначення стіків/хрестовин Sticks Стіки DPads DPad'и Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1 (джойстик %2) Stick 1 Стік 1 Enabled Активний Assign Призначити X Axis: Вісь X: Y Axis: Вісь Y: Stick 2 Стік 2 Number of Physical DPads: %1 Кількість фізичних DPad'ів: %1 Virtual DPad 1 Віртуальний DPad 1 Down: Вниз: Left: Вліво: Right: Вправо: Up: Вверх: Axis %1 Вісь %1 Axis %1 - Вісь %1 - Axis %1 + Вісь %1 + Button %1 Кнопка %1 Move stick 1 along the X axis Рухайте стік 1 по вісі X Move stick 1 along the Y axis Рухайте стік 1 по вісі Y Move stick 2 along the X axis Рухайте стік 2 по вісі X Move stick 2 along the Y axis Рухайте стік 2 по вісі Y Press a button or move an axis Натисніть кнопки чи змістіть вісь AxisEditDialog Axis Вісь Presets: Типовий набір: Mouse (Horizontal) Мишка (Горизонтально) Mouse (Inverted Horizontal) Мишка (Горизонтально інвертовано) Mouse (Vertical) Мишка (Вертикально) Mouse (Inverted Vertical) Мишка (Вертикально інвертовано) Arrows: Up | Down Стрілки: Вверх | Вниз Arrows: Left | Right Стрілки: Вліво | Вправо Keys: W | S Клавіші: W | S Keys: A | D Клавіші: A | D NumPad: KP_8 | KP_2 NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 NumPad: KP_4 | KP_6 None Відсутній Set the value to use as the limit for an axis. Useful for a worn out analog stick. Dead Zone: Сліпа зона: Set the value of the dead zone for an axis. Встановіть значення сліпої зони для вісі. Max Zone: Максимальна зона: [NO KEY] [НЕМАЄ КНОПКИ] Throttle setting that determines the behavior of how to interpret an axis hold or release. Параметри тяги визначають, як програма має реагувати на утримання та натискання вісі. Negative Half Throttle Зворотня напівтяга Negative Throttle Зворотня тяга Normal Звичайний Positive Throttle Пряма тяга Positive Half Throttle Пряма напівтяга Current Value: Поточне значення: Name: Ім'я: Specify the name of an axis. Назначте ім'я для вісі. Mouse Settings Параметри мишки Set Набір Set %1 Набір %1 Left Mouse Button Right Mouse Button ButtonEditDialog Dialog Діалог To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab Аби зробити нове призначення, натисніть клавішу на клавіатурі, чи клацніть по кнопці розташованій на вкладках «Клавіатура» чи «Мишка» Placeholder Заповнювач Enables a key press or release to only occur when a controller button is pressed. Дозволяє виконувати дію тільки при натисканні чи відпусканні клавіші. Toggle Перемикач Enables rapid key presses and releases. Turbo controller. Дозволити прискорене натискання клавіш. Турбо контролер. Turbo Турбо Last keyboard/mouse button: Current: Поточний: Slots Слоти Na&me: Ім'я: Specify the name of a button. Назначте ім'я для кнопки. Action: Дія: Specify the action that will be performed in game while this button is being used. Advanced Розширені параметри Set Набір Set %1 Набір %1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 [NO KEY] [НЕМАЄ КНОПКИ] Calibration Form Start calibration Sticks: Reset settings Cancel Скасувати Save Зберегти Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 Вісь %1 CapturedWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path Full Path File Name CommandLineUtility Profile location %1 is not an XML file. Профіль %1 не є XML файлом. Profile location %1 does not exist. Профіль %1 не існує. Controller identifier is not a valid value. Контролер має хибне значення ідентифікатора. No set number was specified. Не вказаний набір значень. No controller was specified. Жодного контролеру не було вказано. No display string was specified. Жодного рядка для показу не було вказано. Options Параметри Print help text. Вивести довідку. Print version information. Вивести версію програми. Launch program in system tray only. Запустити програму згорнутою у системний лоток. Launch program with the tray menu disabled. Запустити програму із заблокованим меню в лотку. Launch program without the main window displayed. Запустити програму без показу головного вікна. Launch program as a daemon. Запустити програму в режимі демона. DPadContextMenu Mouse (Normal) Мишка (стандарт) Mouse (Inverted Horizontal) Мишка (Горизонтально інвертовано) Mouse (Inverted Vertical) Мишка (Вертикально інвертовано) Mouse (Inverted Horizontal + Vertical) Мишка (Інвертовано гор.+верт.) Arrows Стрілки Keys: W | A | S | D Клавіші: W | A | S | D NumPad NumPad None Відсутній Standard Стандарт Eight Way Вісім сторін 4 Way Cardinal 4 основні сторони 4 Way Diagonal 4 діагональні сторони Mouse Settings Параметри мишки DPadEditDialog Dialog Діалог Presets: Типовий набір: Mouse (Normal) Мишка (стандарт) Mouse (Inverted Horizontal) Мишка (Горизонтально інвертовано) Mouse (Inverted Vertical) Мишка (Вертикально інвертовано) Mouse (Inverted Horizontal + Vertical) Мишка (Інвертовано гор.+верт.) Arrows Стрілки Keys: W | A | S | D Клавіші: W | A | S | D NumPad NumPad None Відсутній Dpad Mode: Режим DPad: Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. &Name: Standard Стандарт Eight Way Вісім сторін 4 Way Cardinal 4 основні сторони 4 Way Diagonal 4 діагональні сторони DPad Delay: Затримка DPad'а: Time lapsed before a direction change is taken into effect. Час затримки, через який зміна напрямку набуде чинності. s с Specify the name of a dpad. Назначте ім'я для DPad. Mouse Settings Параметри мишки Set Набір Set %1 Набір %1 EditAllDefaultAutoProfileDialog Default Profile Типовий профіль Profile: Профіль: Browse Оглянути Open Config Відкрити конфігурацію Profile file path is invalid. Шлях до профілю некоректний. ExtraProfileSettingsDialog Extra Profile Settings Розширені параметри профілю Key Press Time: Час натиску клавіші: 0.00 ms 0.00 мс Profile Name: Ім'я профілю: s с GameController Game Controller Ігровий контролер GameControllerDPad DPad DPad GameControllerMappingDialog Game Controller Mapping Відображення ігрового контролеру <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> A A B B X X Y Y Back Назад Start Старт Guide Guide Left Shoulder Ліве плече Right Shoulder Праве плече Left Stick Click Клік лівого стіку Right Stick Click Клік правого стіку Left Stick X Лівий стік X Left Stick Y Лівий стік Y Right Stick X Правий стік X Right Stick Y Правий стік Y Left Trigger Лівий триґер Right Trigger Правий триґер DPad Up DPad Верх DPad Left DPad Ліво DPad Down DPad Низ DPad Right DPad Право Mapping Відображення SDL 2 Game Controller Mapping String Рядок відображення контролеру від SDL 2 Last Axis Event: Current Axis Detection Dead Zone: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) Відображення ігрового контролеру (%1) (#%2) Discard Controller Mapping? Скинути відображення контролеру? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. GameControllerSet Back Назад Guide Guide Start Старт LS Click Клік ЛС RS Click Клік ПС L Shoulder Л плече R Shoulder П плече L Trigger Л триґер R Trigger П триґер GameControllerTrigger Trigger Триґер JoyAxis Axis Вісь JoyAxisButton Button Кнопка Negative Зворотній Positive Прямий Unknown Невідомо JoyAxisContextMenu Mouse (Horizontal) Мишка (Горизонтально) Mouse (Inverted Horizontal) Мишка (Горизонтально інвертовано) Mouse (Vertical) Мишка (Вертикально) Mouse (Inverted Vertical) Мишка (Вертикально інвертовано) Arrows: Up | Down Стрілки: Вверх | Вниз Arrows: Left | Right Стрілки: Вліво | Вправо Keys: W | S Клавіші: W | S Keys: A | D Клавіші: A | D NumPad: KP_8 | KP_2 NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 NumPad: KP_4 | KP_6 None Відсутній Mouse Settings Параметри мишки Left Mouse Button Right Mouse Button JoyButton Processing turbo for #%1 - %2 Finishing turbo for button #%1 - %2 Processing press for button #%1 - %2 Processing release for button #%1 - %2 Distance change for button #%1 - %2 Button Кнопка [NO KEY] [НЕМАЄ КНОПКИ] [Set %1 1W] [Набір %1 1W] [Set %1 2W] [Набір %1 2W] [Set %1 WH] [Набір %1 WH] JoyButtonContextMenu Toggle Перемкнути Turbo Турбо Clear Очистити Set Select Встановити вибір Disabled Вимкнено Set %1 Набір %1 Set %1 1W Набір %1 1W Set %1 2W Набір %1 2W Set %1 WH Набір %1 WH JoyButtonSlot Mouse Мишка Up Вверх Down Вниз Left Вліво Right Вправо LB ЛК MB СК RB ПК B4 К4 B5 К5 Pause Пауза Hold Утримання Cycle Цикл Distance Дистанція Release Віджати Mouse Mod Мод. мишки Press Time Час натиску Delay Затримка Load %1 Set Change %1 [Text] %1 [Exec] %1 [NO KEY] [НЕМАЄ КНОПКИ] JoyControlStick Stick Стік JoyControlStickButton Up Верх Down Низ Left Ліво Right Право Button Кнопка JoyControlStickContextMenu Mouse (Normal) Мишка (Стандарт) Mouse (Inverted Horizontal) Мишка (Горизонтально інвертовано) Mouse (Inverted Vertical) Мишка (Вертикально інвертовано) Mouse (Inverted Horizontal + Vertical) Мишка (Інвертовано гор.+верт.) Arrows Стрілки Keys: W | A | S | D Клавіші: W | A | S | D NumPad NumPad None Відсутній Standard Стандарт Eight Way Вісім сторін 4 Way Cardinal 4 основні сторони 4 Way Diagonal 4 діагональні сторони Mouse Settings Параметри мишки JoyControlStickEditDialog Dialog Діалог X: X: 0 0 Y: Y: Distance: Дистанція: Bearing: Напрям: % Safe Zone: % Безпечна зона: Presets: Типовий набір: Mouse (Normal) Мишка (стандарт) Mouse (Inverted Horizontal) Мишка (Горизонтально інвертовано) Mouse (Inverted Vertical) Мишка (Вертикально інвертовано) Mouse (Inverted Horizontal + Vertical) Мишка (Інвертовано гор.+верт.) Arrows Стрілки Keys: W | A | S | D Клавіші: W | A | S | D NumPad NumPad None Відсутній Stick Mode: Режим стіка: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Standard Стандарт Eight Way Вісім сторін 4 Way Cardinal 4 основні сторони 4 Way Diagonal 4 діагональні сторони Dead Zone: Сліпа зона: Dead zone value to use for an analog stick. Max Zone: Максимальна зона: Value when an analog stick is considered moved 100%. Diagonal Range: Діагональний діапазон: The area (in degrees) that each diagonal region occupies. Square Stick: Квадратність стіку: Percentage to modify a square stick coordinates to confine values to a circle % % Stick Delay: Затримка стіка: Time lapsed before a direction change is taken into effect. Час затримки, через який зміна напрямку набуде чинності. s с Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Na&me: Name: Ім'я: Specify the name of an analog stick. Назначте ім'я для аналогового стіка. Mouse Settings Параметри мишки Set Набір Set %1 Набір %1 JoyControlStickModifierButton Modifier JoyDPad DPad DPad JoyDPadButton Up Верх Down Низ Left Ліво Right Право Button Кнопка JoyTabWidget <New> <Новий> Remove Вилучити Remove configuration from recent list. Вилучити конфігурацію з переліку частого користування. Load Завантажити Load configuration file. Завантажити файл конфігурації. Save Зберегти Save changes to configuration file. Зберегти зміни до файлу конфігурації. Save As Зберегти як Save changes to a new configuration file. Зберегти зміни в новий файл конфігурації. Sets Набори Copy from Set Копіювати з набору Settings Параметри Set 1 Набір 1 Set 2 Набір 2 Set 3 Набір 3 Set 4 Набір 4 Set 5 Набір 5 Set 6 Набір 6 Set 7 Набір 7 Set 8 Набір 8 Stick/Pad Assign Призначення стіків/DPad Controller Mapping Відображення контролеру Quick Set Швидкий набір Names Імена Toggle button name displaying. Перемкнути показ команд на кнопках. Pref Параметри Change global profile settings. Змінити глобальні параметри профілю. Reset Скинути Revert changes to the configuration. Reload configuration file. Відновити зміни. Перезавантажити файл конфігурації. Open Config Відкрити конфігурацію Config Files (*.amgp *.xml) Save Config Зберегти конфігурацію Config File (*.%1.amgp) Do you really want to reset buttons settings for joystick? Set Набір Save Profile Changes? Зберегти зміни профілю? Changes to the new profile have not been saved. Would you like to save or discard the current profile? Зміни до нового профілю не збережені. Зберегти їх до поточного профілю? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? Зміни до профілю "%1" не збережені. Зберегти їх до поточного профілю? Sticks Стіки DPads DPad'и No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. Жодної кнопки не назначено. Використовуйте «Швидкий набір» для призначення клавіш, або ж вимкніть приховування пустих кнопок. Set %1: %2 Набір %1: %2 Set %1 Набір %1 Copy Set Assignments Скопіювати набір значень Are you sure you want to copy the assignments and device properties from %1? Дійсно бажаєте скопіювати значення і властивості пристрою з %1? Joystick Joystick Джойстик JoystickStatusWindow Properties Властивості Details Деталі Name: Ім'я: %1 %1 Number: Кількість: Axes: Вісь: Buttons: Кнопок: Hats: Міні джойстиків: Battery: Unknown Невідомо GUID: GUID: Game Controller: Ігровий контролер: Axes Вісь Buttons Кнопки Hats Міні джойстики %1 (#%2) Properties Властивості %1 (#%2) Axis %1 Вісь %1 Hat %1 Міні джойстик %1 No Ні Yes Так MainSettingsDialog Edit Settings Змінити параметри General Основні Controller Mappings Відображення контролеру Language Мова Auto Profile Авто-профіль Mouse Мишка Advanced Розширені параметри <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>Вкажіть типову теку, яку програма використовуватиме для збереження профілів.</p></body></html> Recent Profile Count: Кількість швидких профілів: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>Кількість профілів, які будуть показані в переліку часто уживаних. Значення 0 трактується програмою, як необмежена кількість профілів для показу.</p></body></html> Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Приховувати головне вікно кнопкою закриття замість виходу з програми. Close To Tray Закривати до лотку Have Windows start AntiMicroX at system startup. Launch At Windows Startup Запускати разом із Windows Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Виводить часто уживані профілі до всіх контролерів єдиним переліком в меню лотку. Типово використовується підменю. Single Profile List in Tray Один перелік профілів в лотку Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Вказує програмі згортатись до панелі завдань. Зазвичай, програма згортається до системного лотку, якщо є можливість. Minimize to Taskbar Згортати до панелі завдань This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Параметр вказує програмі приховувати всі кнопки, якім не назначено жодного слоту. Використовуйте діалог «Швидкий набір» аби повернути діалог редагування кнопок ігрового контролера. Hide Empty Buttons Приховати пусті кнопки When the program is launched, open the last known profile that was opened during the previous session. Під час запуску програми, відкривається останній відомий профіль, який був відкритий у попередній сесії. Auto Load Last Opened Profile Автоматично завантажувати останній відкритий профіль Only show the system tray icon when the program first launches. Показувати лише піктограму в системному лотку під час першого запуску. Launch in Tray Запускати в лотку Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles Прив'язати профілі Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat Повтор клавіш Active keys will be repeatedly pressed when this option is enabled. Активні клавіші повторно натискатимуться коли цей параметр активний. Enable Specifies how much time should elapse before key repeating begins. Specifies how many times key presses will be performed per seconds. <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> Português do Brasil Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski History Si&ze: Weight Modi&fier: Log File: Log Level: None Відсутній Error Warning Info Інформація Debug Note: To see the change of log level in console output (not in log file), application restart is required Reset Скинути Class Title Program Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision Smoothing Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring Пружинний Screen: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. Accel Numerator: 0 0 Accel Denominator: Accel Threshold: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Delay: Затримка: Pro&file Directory: ms мс Rate: Частота: times/s разів/с Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. GUID GUID Mapping String Рядок відображення Disable? Вимкнути? Delete Вилучити Insert Вставити Default Типова Brazilian Portuguese Brazilian Portuguese English English German German Active Активний Devices: Пристрої: All Всі Device Пристрій Profile Профіль Default? Типовий? Add Додати Edit Змінити Select Default Profile Directory Обрати типову теку профілю Are you sure you want to delete the profile? Дійсно вилучити профіль? Save Log File As Log Files (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] [НЕМАЄ КНОПКИ] MainWindow AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu Не знайдено жодного джойстика. Будь ласка, під'єднайте джойстик, і натисніть пункт «Оновити джойстики» в головному меню If events are not seen by a game, please click here to run this application as the Adminstrator. Якщо події в грі не спостерігаються, натисніть тут, аби запустити програму з правами Адміністратора. If events are not seen by a game, please click here to run this application as Administrator. &App Прогр&ама &Options &Параметри &Help &Допомога He&lp &Quit &Вихід Ctrl+Q Ctrl+Q &Update Joysticks &Оновити джойстики Ctrl+U Ctrl+U &Hide &Згорнути Ctrl+H Ctrl+H &About Пр&о програму Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt Про Qt Properties Властивості Key Checker Перевірка клавіш Home Page Домашня сторінка GitHub Page Сторінка на GitHub Game Controller Mapping Відображення ігрового контролеру Settings Параметри Stick/Pad Assign Призначення стіків/DPad Wiki Wiki Could not find a proper controller identifier. Exiting. (%1) (%1) Open File Відкрити файл %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore &Відновити Calibration couldn't be opened You must connect at least one controller to open the window Run as Administrator? Запустити із правами Адміністратора? Failed to elevate program Не вдалося підняти права програмі Failed to restart this program as the Administrator Не вдалось перезапустити програму із правами Адміністратора Could not find controller. Exiting. MouseAxisSettingsDialog Mouse Settings - Параметри мишки - Set %1 Набір %1 MouseButtonSettingsDialog Mouse Settings - Параметри мишки - Set %1 Набір %1 MouseControlStickSettingsDialog Mouse Settings Параметри мишки Set %1 Набір %1 MouseDPadSettingsDialog Mouse Settings Параметри мишки Set %1 Набір %1 MouseSettingsDialog Mouse Settings Параметри мишки Mouse Mode: Режим мишки: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Курсор Spring Пружинний Acceleration: Прискорення: Enhanced Precision Покращена точність Linear Лінійне Quadratic Квадратичне Cubic Кубічне Quadratic Extreme Екстремально квадратичне Power Function По степеневій функції Easing Quadratic Просте квадратичне Easing Cubic Просте кубічне Mouse Speed Settings Параметри швидкості мишки Enable to change the horizontal and vertical speed boxes at the same time. Змінювати значення гоизонтальної та вертикальної швидкості разом. Change Together Змінювати разом Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration &Multiplier: Mi&n Threshold: E&xtra Duration: Horizontal Speed: Горизонтальна швидкість: 1 = 20 pps 1 = 20 pps Vertical Speed: Вертикальна швидкість: Wheel Hori. Speed: Коліщатко горизонт.: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. Встановіть швидкість для горизонтальної прокрутки коліщатка миші відносно від числа симуляції кроків за секунду. 1 = 1 notch(es)/s 1 = 1 крок(ів)/с Wheel Vert. Speed: Коліщатко вертикаль.: Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. Встановіть швидкість для вертикальної прокрутки коліщатка миші відносно від числа симуляції кроків за секунду. Sensitivity: Чутливість: For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. Easing Duration: % % Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Hori&zontal Speed: &Vertical Speed: Sensitivit&y: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. s с Highest value to accelerate mouse movement by x x Start %: Acceleration begins at this percentage of the base multiplier Minimum amount of axis travel required for acceleration to begin Max Threshold: Maximum axis travel before acceleration has reached the multiplier value Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. Curve: Ease Out Sine Ease Out Quad Ease Out Cubic Spring Settings Параметри пружини Spring Width: Ширина пружини: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. Spring Height: Висота пружини: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. Release Radius: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Відносний Mouse Status Стан мишки X: X: 0 (0 pps) 0 (0 pps) Y: Y: %n notch(es)/s %n крок/с %n кроки/с %n кроків/с ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel Скасувати OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker Перевірка клавіш <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: Обробник подій: Native Key Value: Нативне значення клавіші: 0x00000000 0x00000000 Qt Key Value: Значення клавіші Qt: antimicro Key Value: QObject Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched Демон завантажений Failed to launch daemon Помилка під час завантаження демону Launching daemon Запуск демона Display string "%1" is not valid. Виведений рядок «%1» не є вірним. Failed to set a signature id for the daemon Failed to change working directory to / Не вдалось змінити робочу теку на / Quitting Program # of joysticks found: %1 # джойстиків знайдено: %1 List Joysticks: Перелік джойстиків: --------------- --------------- Joystick %1: Джойстик %1: Index: %1 Індекс: %1 GUID: %1 GUID: %1 UniqueID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 Ім'я: %1 Yes Так No Ні Game Controller: %1 Ігровий контролер: %1 # of Axes: %1 # Вісі: %1 # of Buttons: %1 # Кнопок: %1 # of Hats: %1 # Міні-падів: %1 Attempting to use fallback option %1 for event generation. Failed to open event generator. Exiting. Using %1 as the event generator. Super Super Menu Меню Mute Mute Vol+ Vol+ Vol- Vol- Play/Pause Play/Pause Play Play Pause Pause Prev Prev Next Next Mail Пошта Home Home Media Media Search Пошук Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". Profile location %1 is not an XML file. Профіль %1 не є XML файлом. Profile location %1 does not exist. Профіль %1 не існує. Controller identifier is not a valid value. Контролер має хибне значення ідентифікатора. An invalid set number '%1' was specified. Controller identifier '%s'' is not a valid value. No set number was specified. Не вказаний набір значень. No controller was specified. Жодного контролеру не було вказано. No display string was specified. Жодного рядка для показу не було вказано. An invalid event generator was specified. No event generator string was specified. No log file specified. Options Параметри Print help text. Вивести довідку. Print version information. Вивести версію програми. Launch program in system tray only. Запустити програму згорнутою у системний лоток. Launch program with the tray menu disabled. Запустити програму із заблокованим меню в лотку. Launch program without the main window displayed. Запустити програму без показу головного вікна. Launch program as a daemon. Запустити програму в режимі демона. Logging started Auto-switching to profile "%1". Auto-switching to nullptr profile! xinput version must be at least 2.0. No mouse acceleration changes will occur. Версія xinput має бути вище 2.0. Зміна швидкості миші не використовується. QuickSetDialog Quick Set Швидкий набір <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>Натисніть кнопку, чи змістіть вісь по %1 (<span style=" font-weight:600;">%2</span>).<br/>З'явиться діалогове вікно<br/>в якому зможете зробити переназначення.</p></body></html> Quick Set %1 Швидкий набір %1 SetAxisThrottleDialog Throttle Change Зміна тяги The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? Параметри тяги були змінені для вісі %1. Застосувати ці зміни до всіх наборів? SetJoystick Set %1: %2 Набір %1: %2 Set %1 Набір %1 SetNamesDialog Set Name Settings Параметри наборів Set 1 Набір 1 Set 2 Набір 2 Set 3 Набір 3 Set 4 Набір 4 Set 5 Набір 5 Set 6 Набір 6 Set 7 Набір 7 Set 8 Набір 8 Name Ім'я SimpleKeyGrabberButton Mouse Мишка SpringModeRegionPreview Spring Mode Preview Перегляд пружинного режиму UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput Не можливо знайти прийнятний файл пристрою uinput. Перевірте, чи завантажений модуль uinput. lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device Неможливо відкрити uinput файл пристрою Перевірте, чи маєте ви права на запис до пристрою Using uinput device file %1 UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z Esc Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock CapsLock ; ; ' ' Enter Enter Shift_L Shift_Л , , . . / / Ctrl_L Ctrl_Л Super_L Super_Л Alt_L Alt_Л Space Пробіл Alt_R Alt_П Menu Меню Ctrl_R Ctrl_П Shift_R Shift_П Up Вверх Left Вліво Down Вниз Right Вправо PrtSc PrtSc Ins Ins Del Del Home Home End End PgUp PgUp PgDn PgDn NumLock NumLock * * + + KP_Enter KP_Enter KP_1 KP_1 KP_2 KP_2 KP_3 KP_3 KP_4 KP_4 KP_5 KP_5 KP_6 KP_6 KP_7 KP_7 KP_8 KP_8 KP_9 KP_9 KP_0 KP_0 SCLK SCLK Pause Pause Super_R Super_П Mute Mute VolDn VolDn VolUp VolUp Play Play Stop Stop Prev Prev Next Next [NO KEY] [НЕМАЄ КНОПКИ] UnixWindowInfoDialog Captured Window Properties Information About Window Class: TextLabel Title: Path: Match By Properties Class Title Path VDPad VDPad VDPad VirtualKeyPushButton Space Пробіл Tab Tab Shift (L) Shift (Л) Shift (R) Shift (П) Ctrl (L) Ctrl (Л) Ctrl (R) Ctrl (П) Alt (L) Alt (Л) Alt (R) Alt (П) Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP PGUP DEL DEL PGDN PGDN 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK NUM LK * * + + Enter Enter Del Del E N T E R E N T E R < < : : Super (L) Super (Л) Menu Меню Up Вверх Down Вниз Left Вліво Right Вправо VirtualKeyboardMouseWidget Keyboard Клавіатура Mouse Мишка Left Mouse Вліво Up Mouse Вверх Left Button Mouse Ліва кнопка Middle Button Mouse Середня кнопка Right Button Mouse Права кнопка Wheel Up Mouse Коліщатко вверх Wheel Left Mouse Коліщатко вліво Wheel Right Mouse Коліщатко вправо Wheel Down Mouse Коліщатко вниз Down Mouse Вниз Right Mouse Вправо Button 4 Mouse Кнопка 4 Mouse 8 Mouse Мишка 8 Button 5 Mouse Кнопка 5 Mouse 9 Mouse Мишка 9 Mouse Settings Параметри мишки NONE Відсутній [NO KEY] [НЕМАЄ КНОПКИ] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Browser Back Browser Favorites Browser Forward Browser Home Browser Refresh Browser Search Browser Stop Calc Email F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media Media Media Next Media Play Media Previous Media Stop Search Пошук Volume Down Volume Mute Volume Up VirtualMousePushButton INVALID ХИБНИЙ WinAppProfileTimerDialog Capture Application Захопити програму After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. Після натискання «Захопити програму», зробіть активним вікно програм, яку ви хочете прив'язати до поточного профілю. Активне вікно буде захоплено через вказаний проміжок часу. Timer: Таймер: Seconds Секунд Cancel Скасувати WinExtras [NO KEY] [НЕМАЄ КНОПКИ] AntiMicroX Profile AntiMicroX профіль X11Extras ESC ESC Tab Tab Space Пробіл DEL DEL Return Return KP_Enter KP_Enter Backspace Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. Розширення xinput не знайдено. Зміна швидкості миші не використовується. xinput version must be at least 2.0. No mouse acceleration changes will occur. Версія xinput має бути вище 2.0. Зміна швидкості миші не використовується. Virtual pointer found with id=%1. Віртуальний вказівник знайдено із id=%1. PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 Не знайдено PtrFeedbackClass для віртуального вказівника. Зміна швидкості миші не використовується для пристрою із id=%1 Changing mouse acceleration for device with id=%1 Зміна прискорення мишки для пристрою із id=%1 XMLConfigReader Could not write updated profile XML to file %1. Неможливо записати оновлений профіль до файлу %1. XMLConfigWriter Could not write to profile at %1. Неможливо записати профіль як %1. AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. Запустити програму згорнутою у системний лоток. Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/share/antimicrox/translations/antimicrox_zh_CN.ts000066400000000000000000017372761377703515000301200ustar00rootroot00000000000000 AboutDialog About 关于 AntiMicroX AntiMicroX Version 版本 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, next maintained by the AntiMicro group at https://github.com/AntiMicro, and now by juliagoda at https://github.com/juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Old Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></span><span style=" font-family:'Sans Serif'; font-size:9pt;">Zerro Alvein</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">aybe</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">7185</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">DarkStarSword</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">est31</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">ProfessorKaos64</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">qwerty12</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA0</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Noto Sans'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> Copyright: 2013 - 2020 版权:2013 - 2020 {2013 ?} Info 信息 Changelog 更新日志 "juliagoda" (since March, 2018) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. Copyright: 2013 - 2018 版权:2013 - 2018 {2013 ?} Since December 30, 2012, I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. As next, project has been continued since 2018 by juliagoda on antimicroX project. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. 自2012年12月30日以来,我利用业余时间编写 AntiMicroX。这个项目本来是 QJoyPad 的派生,用来学习事件驱动编程,没想到规模变得如此之大。尽管我花了很多时间去学习新的技巧、探索键鼠模拟的领域、每周五晚上用头撞键盘,我仍然觉得这是一段有趣并且充实的经历。 对这个程序的需求来源于我想在 Windows 上使用类似的程序玩一些原生不支持手柄的游戏。虽然 Linux 上有其它替代品,但是我并没有找到在功能上或者游戏内控制足够好,以至于我可以使用键鼠模拟来享受游戏的工具。QJoyPad 是我过去主要使用的工具,尽管它非常古老而且不提供一些我认为非常关键的功能。那个项目已经停止开发很多年,所以我决定编写一个我自己的工具。 从那时起,我不断寻找其它程序的长处,然后在它们的基础上继续开发。在此期间,我还发现了一些不错的小技巧,并且学到了很多关于游戏如何实现原生支持手柄的知识。这些知识远远广于我之前想学的范围。尽管 AntiMicroX 还有很多可以改进的地方,我还是认为它提供了最好的游戏内控制体验,不管是针对老一些还是新一些的原生不支持手柄的游戏。 开发这个程序对我来说已经不像以往那样高优先级了。这主要是因为相比较 Xbox 360 手柄来说,Steam 手柄可以很好地进行 PC 游戏。然而,这个程序似乎仍然有理由再存在一段时间。 --- 截止至2016年5月24日,这个项目已经被移动到了 https://github.com/AntiMicroX/AntiMicroX。此外,由于 Travis 希望将更多精力放到其它兴趣和事务上,项目管理已经从 Travis (Ryochan7) 移交到了 AntiMicroX 项目组。 Copyright: 2013 - 2016 版权:2013 - 2016 Credits 致谢 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;, now maintained by the AntiMicroX group at https://github.com/AntiMicroX.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Contributors:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"><br /></span>Zerro Alvein</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">aybe</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">7185</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">DarkStarSword</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">est31</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ProfessorKaos64</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">qwerty12</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">WAZAAAAA0</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx - Chinese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">phob - German</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tou omiya - Japanese</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">burunduk - Ukrainian</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">原作者 Travis Nickles &lt;nickles.travis@gmail.com&gt;。<br />现由 AntiMicroX 开发组 (https://github.com/AntiMicroX) 维护。</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">贡献者:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"><br /></span>Zerro Alvein</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">aybe</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jeff Backus &lt;jeff.backus@gmail.com&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Arthur Moore<br />Anton Tornqvist &lt;antont@inbox.lv&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">7185</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">DarkStarSword</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">est31</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ProfessorKaos64</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">qwerty12</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">WAZAAAAA0</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">翻译:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - 巴西葡萄牙语</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">zzpxyx - 简体中文</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Belleguic Terence &lt;hizo@free.fr&gt; - 法语</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans';">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - 德语</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">phob - 德语</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">tou omiya - 日语</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - 俄语</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - 塞尔维亚语</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">burunduk - 乌克兰语</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - 西班牙语</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - 意大利语</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> About Development 关于开发 License 许可 Program Version %1 程序版本 %1 Program Compiled on %1 at %2 编译时间 %1 %2 Built Against SDL %1 使用 SDL %1 构建 Running With SDL %1 使用 SDL %1 运行 Using Qt %1 使用 Qt %1 Using Event Handler: %1 使用事件处理程序:%1 AddEditAutoProfileDialog Auto Profile Dialog 自动配置文件对话框 Profile: 配置文件: Pro&file: Browse 浏览 Window: 窗口: Select Window. Click on the appropriate application window and the application file path will be populated in the form. 选择窗口。 单击应用程序的窗口,程序文件路径将被自动填入表格。 Detect Window Properties 检测窗口属性 &Class: T&itle: Class: 类: Title: 标题: set partial title Application: 应用程序: Select 选择 De&vices: Devices: 设备: Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. 将这个配置文件设定为上述设备的默认配置文件。 这个配置文件将取代全局默认配置文件选项。 Set as Default for Controller 设为上述设备的默认配置文件 A different profile is already selected as the default for this device. 这个设备已被指定了另一个不同的默认配置文件。 Current (%1) 当前 (%1) Open Config 打开配置文件 Select Program 选择程序 Programs (*.exe) 程序 (*.exe) Please use the main default profile selection. 请使用全局默认配置文件选项。 Main Profile Already selected Chosen Profile The selection will be used instead of the all default profile option. Please select a window by using the mouse. Press Escape if you want to cancel. 请使用鼠标选择窗口。按 Esc 键取消。 Capture Application Window 捕捉应用程序窗口 Could not obtain information for the selected window. 无法获得所选窗口的信息。 Application Capture Failed 应用程序捕捉失败 Profile file path is invalid. 配置文件路径无效。 No window matching property was specified. 未指定窗口匹配属性。 Program path is invalid or not executable. 程序路径无效或非可执行文件。 File is not an .exe file. 文件不是 .exe 文件。 No window matching property was selected. 未选择窗口匹配属性。 AdvanceButtonDialog Advanced 高级选项 Assignments 分配 Toggle 开关 Turbo 连发 Set Selector 设置选择器 Blank or KB/M 空白或键鼠 Hold 按下 Pause 暂停 Cycle 周期 Distance 距离 Insert 插入 Delete 删除 Clear All 清除所有 Time: 时间: 0.01s 0.01秒 0s 0秒 Insert a pause that occurs in between key presses. 在按键间插入暂停。 Release 释放 Insert a new blank slot. 插入新动作。 Delete a slot. 删除所选动作。 Clear all currently assigned slots. 清除所有动作。 Specify the duration of an inserted Pause or Hold slot. 为“暂停”或“按下”动作指定所需时长。 0m 0分 &Mouse Speed Mod: 鼠标速度更改 (&M): Specify the range past an axis dead zone in which a sequence of actions will execute. 为“距离”动作指定所需的超过不灵敏区的距离。 Distance: 距离: % % Mouse Mod 鼠标变速 Press Time 按下时间 Delay 延迟 Execute 运行 Load 载入 Set Change 设置改变 Text Entry 文本键入 Join Split Placeholder 占位符 0 0 Set the percentage that mouse speeds will be modified by. 设置鼠标移动速度百分比。 Auto Reset Cycle After 在此时间之后取消未完成的“周期”动作 seconds Executable: 可执行文件: ... ... Arguments: 参数: Enabled 启用 Mode: 模式: <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> <html><head/><body><p>正常:以所选频率重复按下并释放按键。</p><p>梯度:根据轴移动幅度调整按钮被按下和释放的延迟。频率保持不变。</p><p>脉冲:调整每秒按钮被按下和释放的次数。按钮延迟保持不变。</p></body></html> Normal 正常 Gradient 梯度 Pulse 脉冲 Delay: 延迟: 0.10s 0.10秒 Rate: 频率: 10.0/s 10.0/秒 Disabled 禁用 Select Set 1 One Way 单向选择设置1 Select Set 1 Two Way 双向选择设置1 Select Set 1 While Held 按下时选择设置1 Select Set 2 One Way 单向选择设置2 Select Set 2 Two Way 双向选择设置2 Select Set 2 While Held 按下时选择设置2 Select Set 3 One Way 单向选择设置3 Select Set 3 Two Way 双向选择设置3 Select Set 3 While Held 按下时选择设置3 Select Set 4 One Way 单向选择设置4 Select Set 4 Two Way 双向选择设置4 Select Set 4 While Held 按下时选择设置4 Select Set 5 One Way 单向选择设置5 Select Set 5 Two Way 双向选择设置5 Select Set 5 While Held 按下时选择设置5 Select Set 6 One Way 单向选择设置6 Select Set 6 Two Way 双向选择设置6 Select Set 6 While Held 按下时选择设置6 Select Set 7 One Way 单向选择设置7 Select Set 7 Two Way 双向选择设置7 Select Set 7 While Held 按下时选择设置7 Select Set 8 One Way 单向选择设置8 Select Set 8 Two Way 双向选择设置8 Select Set 8 While Held 按下时选择设置8 [NO KEY] sec. 秒。 /sec. /秒。 Not checked slots To delete slots, you need to select at least one To insert slots, you need to select at least one Unknown current slot Click on chosen slots before joining them Not enough slots It's impossible to join slots. Add at least one other slot. Not selected slots It's impossible to join slots. Select at least two slots before joining them Only keyboard slots It's only possible to join simple and mix keyboard slots It's impossible to split slots. Add at least one other slot. Not selected slot Select your slot before splitting. Too many mix slots Select one mix slot. Only mix slots It's only possible to split mix slot. Empty execution path Line for execution file path is empty. Fill the first line before you are going to add a slot. File doesn't exist There is no such file locally, that could be executed. Check the file on your system Set %1 设置%1 Select Set %1 选择设置%1 One Way 单向 Two Way 双向 While Held 按下时 Choose Executable 选择可执行文件 Slots past a Cycle action will be executed on the next button press. Multiple cycles can be added in order to create partitions in a sequence. “周期”动作之后的动作将在下一次按下相同按钮的时候被执行。可以添加多个“周期”动作来创建一个按键序列中不同的子序列。 Delays the time that the next slot is activated by the time specified. Slots activated before the delay will remain active after the delay time has passed. 根据指定时长延迟下个动作开始执行的时间。延迟之前处于活动状态的动作将在延迟结束后保持活动状态。 Distance action specifies that the slots afterwards will only be executed when an axis is moved a certain range past the designated dead zone. “距离”动作之后的动作只有在轴移出不灵敏区并超过指定距离之后才会被执行。 Insert a hold action. Slots after the action will only be executed if the button is held past the interval specified. 插入一个“按下”动作。“按下”动作之后的动作只有在按钮被按下超过指定的时长之后才会被执行。 Chose a profile to load when this slot is activated. 当该动作被执行时,载入所选配置文件。 Mouse mod action will modify all mouse speed settings by a specified percentage while the action is being processed. This can be useful for slowing down the mouse while sniping. “鼠标变速”动作被处理时,将根据指定的百分比改变所有鼠标速度。这可以用在狙击时减缓鼠标速度。 Specify the time that keys past this slot should be held down. 按钮被按下超过指定的时长将保持被按下的状态。 Insert a release action. Slots after the action will only be executed after a button release if the button was held past the interval specified. 插入一个“释放”动作。“释放”动作之后的动作只有在按钮被按下超过指定时长并被释放之后才会被执行。 Change to selected set once slot is activated. 该动作被执行时,切换到所选的设置。 Full string will be typed when a slot is activated. 当该动作被执行时,整个字符串将被键入。 Execute program when slot is activated. 当该动作被执行时,运行一个程序。 Choose Profile 选择配置文件 Config Files (*.amgp *.xml) 配置文件 (*.amgp *.xml) AdvanceStickAssignmentDialog Stick/Pad Assignment 摇杆/十字键分配 Sticks 摇杆 DPads 十字键 Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. %1 (Joystick %2) %1(手柄%2) Stick 1 手柄1 Enabled 启用 Assign 分配 X Axis: X轴: Y Axis: Y轴: Stick 2 手柄2 Number of Physical DPads: %1 物理十字键数:%1 Virtual DPad 1 虚拟十字键1 Up: 上: Down: 下: Note: This window is meant for backwards compatibility with profiles made before AntiMicroX 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. 注意:这个窗口是为了兼容 AntiMicroX 2.0 版之前创建的配置文件。自 AntiMicroX 2.0 起,推荐使用游戏控制器映射窗口。 Left: 左: Right: 右: Axis %1 轴%1 Axis %1 - 轴%1 - Axis %1 + 轴%1 + Button %1 按钮%1 Move stick 1 along the X axis 沿X轴移动摇杆1 Move stick 1 along the Y axis 沿Y轴移动摇杆1 Move stick 2 along the X axis 沿X轴移动摇杆2 Move stick 2 along the Y axis 沿Y轴移动摇杆2 Press a button or move an axis 按任意键或移动任意轴 AxisEditDialog Axis Mouse (Horizontal) 鼠标(水平) Mouse (Inverted Horizontal) 鼠标(水平翻转) Mouse (Vertical) 鼠标(垂直) Mouse (Inverted Vertical) 鼠标(垂直翻转) Arrows: Up | Down 方向键:上|下 Arrows: Left | Right 方向键:左|右 Keys: W | S 按键:W | S Keys: A | D 按键:A | D NumPad: KP_8 | KP_2 数字键盘:8 | 2 NumPad: KP_4 | KP_6 数字键盘:4 | 6 None Set the value to use as the limit for an axis. Useful for a worn out analog stick. 设置轴的最大值。 对老旧磨损的模拟摇杆尤其有帮助。 Negative Half Throttle 负半阀 Positive Half Throttle 正半阀 Name: 名称: Specify the name of an axis. 指定轴的名称。 Mouse Settings 鼠标设置 Set the value of the dead zone for an axis. 设置轴的不灵敏区。 Presets: 预设: Dead Zone: 不灵敏区: Max Zone: 最大区: [NO KEY] [无按键] Throttle setting that determines the behavior of how to interpret an axis hold or release. 阀设置决定如何判断一个轴的按下和释放。 Negative Throttle 负阀 Normal 正常 Positive Throttle 正阀 Current Value: 当前值: Set 设置 Set %1 设置%1 Left Mouse Button 鼠标左键 Right Mouse Button 鼠标右键 ButtonEditDialog Dialog 对话框 To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab 若想分配按键,请按键盘上任意键或在键盘、鼠标页上点击按钮 Placeholder 占位符 Toggle 开关 Enables a key press or release to only occur when a controller button is pressed. 当游戏控制器按钮被按下时,按下或释放某个按键,并一直保持此状态。 Enables rapid key presses and releases. Turbo controller. 快速按下和释放某个键。 连发游戏控制器。 Turbo 连发 Current: 当前: Last keyboard/mouse button: Slots 动作 Na&me: 名称 (&m): Specify the name of a button. 指定按钮的名称。 Action: 动作: Specify the action that will be performed in game while this button is being used. 指定游戏中这个按钮被按下时的动作。 Advanced 高级选项 Set 设置 Set %1 设置%1 Choose your keyboard key No button Last button To change settings for last button, it must be at least one assignment from keyboard to gamepad To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad No choice Before you open window with advanced settins, you have to choice a key To open advanced dialog, it's needed to map at least one button from keyboard to gamepad Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad As last gamepad button has been set Index %1 Calibration Form Start calibration Sticks: Reset settings Cancel 取消 Save 保存 Calibration Do you really want to reset settings of current axis? Calibration was saved for the preset. Do you really want to reset settings? Place the joystick in the center position. It's the part, where often you don't have to move. Just skip it in such situation. Calibrating center Start second step Center X: %1 Center Y: %1 Place the joystick in the top-left corner many times Calibrating position X: %1 Y: %1 Place the joystick in the bottom-right corner Start final step range X: %1 - %2 range Y: %1 - %2 deadzone X: %1 deadzone Y: %1 ---Calibration done!--- Calibration values have been saved Dead zone calibration You have to move axes to the top-left corner at least five times. You have to move axes to the bottom-right corner at least five times. Do you want to save calibration of current axis? Axis %1 轴%1 CapturedWindowInfoDialog Captured Window Properties 捕获的窗口属性 Information About Window 窗口信息 Class: 类: TextLabel 文本标签 Title: 标题: Path: 路径: Match By Properties 根据属性匹配 Class Title 标题 Path 路径 Full Path 全路径 File Name 文件名 CommandLineUtility Profile location %1 is not an XML file. 配置文件 %1 不是一个 XML 文件。 Profile location %1 does not exist. 配置文件 %1 不存在。 An invalid set number '%1' was specified. 指定的设置编号 "%1" 无效。 Controller identifier '%s'' is not a valid value. 游戏控制器标识符 "%s" 无效。 No display string was specified. 未指定显示字符串。 Controller identifier is not a valid value. 游戏控制器标识符无效。 No set number was specified. 未指定设置编号。 No controller was specified. 未指定游戏控制器。 An invalid event generator was specified. 指定的事件发生器无效。 No event generator string was specified. 未指定事件发生器字符串。 Qt style flag was detected but no style was specified. 检测到 Qt 样式标识,但未指定样式。 No log file specified. 未指定日志文件。 AntiMicroX version AntiMicroX 版本 Usage: AntiMicroX [options...] [profile] 用法:AntiMicroX [选项] [配置文件] Options 选项 Print help text. 打印帮助文本。 Print version information. 打印版本信息。 Launch program in system tray only. 启动后最小化到系统托盘。 Launch program with the tray menu disabled. 启动后禁用系统托盘菜单。 Launch program without the main window displayed. 启动后不显示主窗口。 Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. 启动后将指定的配置文件作为默认配置文件。默认应用到所有游戏控制器。 Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. 应用配置文件到指定的游戏控制器。值可以是编号、名称或全局唯一标识符。 Unload currently enabled profile(s). Value can be a controller index, name, or GUID. 卸载当前生效的配置文件。值可以是控制器编号、名称或全局唯一标识符。 Start joysticks on a specific set. Value can be a controller index, name, or GUID. 为摇杆指定设置编号。值可以是控制器编号、名称或全局唯一标识符。 Advance profile loading set options. 切换到下一个配置文件载入选项。 Launch program as a daemon. 以后台服务方式启动程序。 Enable logging. 开启日志。 Use specified display for X11 calls. Useful for ssh. 为 X11 调用指定显示设备。对 ssh 尤其有用。 Choose between using XTest support and uinput support for event generation. Default: xtest. 为事件发生器选择 XTest 支持或 uinput 支持。默认:XTest。 Choose between using SendInput and vmulti support for event generation. Default: sendinput. 为事件发生器选择使用 SendInput 或 vmulti 支持。默认:SendInput。 Print information about joysticks detected by SDL. 打印 SDL 检测到的摇杆。 Open game controller mapping window of selected controller. Value can be a controller index or GUID. 为所选的游戏控制器打开游戏控制器映射窗口。值可以是控制器编号或全局唯一标识符。 DPadContextMenu Mouse (Normal) 鼠标(正常) Mouse (Inverted Horizontal) 鼠标(水平翻转) Mouse (Inverted Vertical) 鼠标(垂直翻转) Mouse (Inverted Horizontal + Vertical) 鼠标(水平翻转 + 垂直翻转) Arrows 方向键 Keys: W | A | S | D 按键:W | A | S | D NumPad 数字键盘 None Standard 标准 Eight Way 八向 4 Way Cardinal 正四向 4 Way Diagonal 斜四向 Mouse Settings 鼠标设置 DPadEditDialog Dialog 对话框 Presets: 预设: Mouse (Normal) 鼠标(正常) Mouse (Inverted Horizontal) 鼠标(水平翻转) Mouse (Inverted Vertical) 鼠标(垂直翻转) Mouse (Inverted Horizontal + Vertical) 鼠标(水平翻转 + 垂直翻转) Arrows 方向键 Keys: W | A | S | D 按键:W | A | S | D NumPad 数字键盘 None Dpad Mode: 十字键模式: &Name: 名称 (&N): 4 Way Cardinal 正四向 4 Way Diagonal 斜四向 DPad Delay: 十字键延迟: Time lapsed before a direction change is taken into effect. 方向改变生效前的延迟。 s Specify the name of a dpad. 指定十字键的名称。 Mouse Settings 鼠标设置 Standard 标准 Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. 标准:十字键有八个区域。当十字键处于对角线区域时,两个方向的按键同时被激活。 八向:十字键有八个区域。每个区域有自己的方向按键。同一时间仅有一个方向按键被激活。尤其适用于类 Rouge 游戏。 正四向:十字键有四个区域,分别对应上下左右四个方向。尤其适用于菜单选择。 斜四向:十字键有四个区域,分别对应对角线的四个方向。 Eight Way 八向 Set 设置 Set %1 设置%1 EditAllDefaultAutoProfileDialog Default Profile 默认配置文件 Profile: 配置文件: Browse 浏览 Open Config 打开配置文件 Profile file path is invalid. 配置文件路径无效。 ExtraProfileSettingsDialog Extra Profile Settings 附加配置文件设置 Key Press Time: 按键按下时间: 0.00 ms 0.00毫秒 Profile Name: 配置文件名称: s GameController Game Controller 游戏控制器 GameControllerDPad DPad 十字键 GameControllerMappingDialog Game Controller Mapping 游戏控制器映射 <html><head/><body><p>AntiMicroX makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>AntiMicroX will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> <html><head/><body><p>AntiMicroX 使用 SDL 2 的<a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">游戏控制器应用程序接口</span></a>把各式各样的手柄进行抽象,使它们适用于统一的标准。若要进行按钮分配,请选择下面相应的按钮映射单元格。之后您可以按一个按钮或者移动手柄上的一个轴,映射单元格将更新以匹配这个物理按键或轴。</p><p>AntiMicroX 将把您指定的映射保存为一个字符串,而这个字符串将被加载到 SDL 中。</p></body></html> A A键 B B键 X X键 Y Y键 Back 后退键 Start 开始键 Guide 导航键 Left Shoulder 左肩键 Right Shoulder 右肩键 Left Stick Click 左摇杆点击 Right Stick Click 右摇杆点击 Left Stick X 左摇杆X轴 Left Stick Y 左摇杆Y轴 Right Stick X 右摇杆X轴 Right Stick Y 右摇杆Y轴 Left Trigger 左扳机 Right Trigger 右扳机 DPad Up 十字键上 DPad Left 十字键左 DPad Down 十字键下 DPad Right 十字键右 Mapping 映射 SDL 2 Game Controller Mapping String SDL 游戏控制器映射字符串 Last Axis Event: 最近轴事件: Current Axis Detection Dead Zone: 当前轴不灵敏区: 5000 5000 10000 10000 15000 15000 20000 20000 25000 25000 30000 30000 32000 32000 Game Controller Mapping (%1) (#%2) 游戏控制器映射 (%1) (#%2) Discard Controller Mapping? 放弃修改游戏控制器映射? Discard mapping for this controller? If discarded, the controller will be reverted to a joystick once you refresh all joysticks. 放弃修改这个游戏控制器的映射? 如果放弃,这个游戏控制器将在您刷新所有摇杆时被重新识别为一个摇杆。 GameControllerSet Back 后退键 Guide 导航键 Start 开始键 LS Click 左摇杆点击 RS Click 右摇杆点击 L Shoulder 左肩键 R Shoulder 右肩键 L Trigger 左扳机 R Trigger 右扳机 GameControllerTrigger Trigger 扳机 JoyAxis Axis JoyAxisButton Negative Positive Unknown 未知 Button 按钮 JoyAxisContextMenu Mouse (Horizontal) 鼠标(水平) Mouse (Inverted Horizontal) 鼠标(水平翻转) Mouse (Vertical) 鼠标(垂直) Mouse (Inverted Vertical) 鼠标(垂直翻转) Arrows: Up | Down 方向键:上|下 Arrows: Left | Right 方向键:左|右 Keys: W | S 按键:W | S Keys: A | D 按键:A | D NumPad: KP_8 | KP_2 数字键盘:8 | 2 NumPad: KP_4 | KP_6 数字键盘:4 | 6 None Mouse Settings 鼠标设置 Left Mouse Button 鼠标左键 Right Mouse Button 鼠标右键 JoyButton Processing turbo for #%1 - %2 正在处理按钮#%1-%2的连发 Finishing turbo for button #%1 - %2 正在完成按钮#%1-%2的连发 Processing press for button #%1 - %2 正在处理按下按钮#%1-%2 Processing release for button #%1 - %2 正在处理释放按钮#%1-%2 Distance change for button #%1 - %2 按钮#%1-%2距离改变 Button 按钮 [NO KEY] [无按键] [Set %1 1W] [单向选择设置%1] [Set %1 2W] [双向选择设置%1] [Set %1 WH] [按下时选择设置%1] JoyButtonContextMenu Toggle 开关 Turbo 连发 Clear 清除 Set Select 选择设置 Disabled 禁用 Set %1 设置%1 Set %1 1W 单向选择设置%1 Set %1 2W 双向选择设置%1 Set %1 WH 按下时选择设置%1 JoyButtonSlot Mouse 鼠标 Up Down Left Right LB 鼠标左键 MB 鼠标中键 RB 鼠标右键 B4 按钮4 B5 按钮5 Pause 暂停 Hold 按下 Cycle 周期 Distance 距离 Release 释放 Mouse Mod 鼠标变速 Press Time 按下时间 Delay 延迟 Load %1 载入%1 Set Change %1 设置改变%1 [Text] %1 [文本]%1 [Exec] %1 [运行]%1 [NO KEY] [无按键] JoyControlStick Stick 摇杆 JoyControlStickButton Up Down Left Right Button 按钮 JoyControlStickContextMenu Mouse (Normal) 鼠标(正常) Mouse (Inverted Horizontal) 鼠标(水平翻转) Mouse (Inverted Vertical) 鼠标(垂直翻转) Mouse (Inverted Horizontal + Vertical) 鼠标(水平翻转 + 垂直翻转) Arrows 方向键 Keys: W | A | S | D 按键:W | A | S | D NumPad 数字键盘 None Standard 标准 Eight Way 八向 4 Way Cardinal 正四向 4 Way Diagonal 斜四向 Mouse Settings 鼠标设置 JoyControlStickEditDialog Dialog 对话框 X: X轴: 0 0 Y: Y轴: Distance: 距离: Presets: 预设: Mouse (Normal) 鼠标(正常) Mouse (Inverted Horizontal) 鼠标(水平翻转) Mouse (Inverted Vertical) 鼠标(垂直翻转) Mouse (Inverted Horizontal + Vertical) 鼠标(水平翻转 + 垂直翻转) Arrows 方向键 Keys: W | A | S | D 按键:W | A | S | D NumPad 数字键盘 None Stick Mode: 摇杆模式: Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. 标准:摇杆有八个区域。当摇杆处于对角线区域时,两个方向的按键同时被激活。 八向:摇杆有八个区域。每个区域有自己的方向按键。同一时间仅有一个方向按键被激活。尤其适用于类 Rouge 游戏。 正四向:摇杆有四个区域,分别对应上下左右四个方向。尤其适用于菜单选择。 斜四向:摇杆有四个区域,分别对应对角线的四个方向。 4 Way Cardinal 正四向 4 Way Diagonal 斜四向 Dead zone value to use for an analog stick. 设置模拟摇杆的不灵敏区。 Value when an analog stick is considered moved 100%. 设置模拟摇杆的最大值。当达到这个值时,模拟摇杆被认为移动到了100%的位置。 The area (in degrees) that each diagonal region occupies. 每个对角线区域的角度数。 Square Stick: 方形摇杆: Percentage to modify a square stick coordinates to confine values to a circle 这个百分比用来调整方形摇杆的坐标值使其被限制在一个圆里 % % Stick Delay: 摇杆延迟: Time lapsed before a direction change is taken into effect. 方向改变生效前的延迟。 s Modifier: 修饰键: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. 编辑当摇杆被激活时同时激活的按钮。 这个按钮尤其适用于分配带有修饰键的区域,例如在模拟摇杆上分配行走/跑步的功能。 PushButton 按钮 Na&me: Name: 名称: Specify the name of an analog stick. 指定模拟摇杆的名称。 Mouse Settings 鼠标设置 Standard 标准 Bearing: 方向: % Safe Zone: 安全区(%): Eight Way 八向 Dead Zone: 不灵敏区: Max Zone: 最大区: Diagonal Range: 对角线区域范围: Set 设置 Set %1 设置%1 JoyControlStickModifierButton Modifier 修饰 JoyDPad DPad 十字键 JoyDPadButton Up Down Left Right Button 按钮 JoyTabWidget <New> <新> Remove 移除 Remove configuration from recent list. 从最近使用列表中移除配置。 Load 载入 Load configuration file. 载入配置文件。 Save 保存 Save changes to configuration file. 保存更改到配置文件。 Save As 另存为 Save changes to a new configuration file. 保存更改到新的配置文件。 Sets 设置 Copy from Set 从设置复制 Settings 设置 Set 1 设置1 Set 2 设置2 Set 3 设置3 Set 4 设置4 Set 5 设置5 Set 6 设置6 Set 7 设置7 Set 8 设置8 Stick/Pad Assign 摇杆/十字键分配 Controller Mapping 游戏控制器映射 Quick Set 快速设置 Names 名称 Toggle button name displaying. 开关按钮名称显示。 Pref 偏好设置 Change global profile settings. 改变全局配置文件设置。 Reset 重置 Revert changes to the configuration. Reload configuration file. 还原设置的更改。重新加载配置文件。 Open Config 打开配置文件 Config Files (*.amgp *.xml) 配置文件 (*.amgp *.xml) Config File (*.%1.amgp) 配置文件 (*.%1.amgp) Do you really want to reset buttons settings for joystick? Save Profile Changes? 保存配置文件更改? Changes to the new profile have not been saved. Would you like to save or discard the current profile? 新配置文件的更改尚未保存。您想保存还是放弃修改当前的配置文件? Changes to the profile "%1" have not been saved. Would you like to save or discard changes to the current profile? 配置文件“%1”的更改尚未保存。您想保存还是放弃修改此配置文件? Sticks 摇杆 DPads 十字键 No buttons have been assigned. Please use Quick Set to assign keys to buttons or disable hiding empty buttons. 按钮未被分配。请使用“快速设置”来将按键分配到按钮,或取消隐藏空白按钮。 Set %1: %2 设置%1:%2 Set %1 设置%1 Copy Set Assignments 复制设置分配信息 Are you sure you want to copy the assignments and device properties from %1? 您确定要从 %1 复制分配信息和设备属性吗? Save Config 保存配置文件 Set 设置 Joystick Joystick 摇杆 JoystickStatusWindow Properties 属性 Details 详细信息 Name: 名称: %1 %1 Number: 编号: Axes: 轴数: Buttons: 按钮数: Hats: 帽子开关数: Battery: Unknown 未知 GUID: 全局唯一标识符: Game Controller: 是否为手柄: Axes Buttons 按钮 Hats 帽子开关 %1 (#%2) Properties %1 (#%2) 属性 Axis %1 轴%1 Hat %1 帽子开关%1 No Yes MainSettingsDialog Edit Settings 编辑设置 General 常规 Controller Mappings 游戏控制器映射 Language 语言 Auto Profile 自动配置文件 Mouse 鼠标 Advanced 高级选项 <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> <html><head/><body><p>指定本程序在加载或保存一个配置文件时,文件对话框中默认使用的路径。</p></body></html> Recent Profile Count: 最近使用的配置文件数: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> <html><head/><body><p>最近使用的配置文件列表中配置文件的数量。设为0将显示所有最近使用的配置文件。</p></body></html> Gamepad Poll Rate: 手柄轮询速率: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. 改变轮询速率来发现新的手柄事件。默认10毫秒。 降低轮询速率可能会导致本程序使用更多的处理器资源。请在以无人值守方式使用前测试此选项。 Hide main window when the main window close button is clicked instead of quitting the program. 点击关闭按钮时,最小化主窗口到系统托盘而不是退出程序。 Close To Tray 关闭时最小化到系统托盘 Launch At Windows Startup Windows 开机自启动 Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. 在系统托盘菜单中以单一列表显示所有游戏控制器的最近使用的配置文件。 默认是使用子菜单。 Single Profile List in Tray 系统托盘菜单中使用单一配置文件列表 Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. 使本程序最小化到任务栏。 如果可能,默认情况下本程序将最小化到系统托盘。 Minimize to Taskbar 最小化到任务栏 This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. 此选项将使本程序隐藏所有未分配槽的按钮。 您需要使用“快速设置”对话框来打开手柄按钮的编辑对话框。 Hide Empty Buttons 隐藏空白按钮 When the program is launched, open the last known profile that was opened during the previous session. 本程序启动时,打开上次使用的配置文件。 Auto Load Last Opened Profile 自动加载上次打开的配置文件 Only show the system tray icon when the program first launches. 首次启动本程序时只显示系统托盘。 Launch in Tray 启动时最小化到系统托盘 Associate Profiles 关联配置文件 Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs Attach the numeric keypad Combination of keys for quitting app Choose keys combination ! restart is needed after choice of combination Key Repeat 键重复 Active keys will be repeatedly pressed when this option is enabled. 此选项启用后,处于活动状态的按键将一直被重复按下。 Enable 启用 Português do Brasil 巴西葡萄牙语 Français 法语 Deutsch 德语 Italiano 意大利语 日本語 日本语 Русский 俄语 српски / srpski 塞尔维亚语 Español 西班牙语 українська 乌克兰语 Polski History Si&ze: Weight Modi&fier: Log File: 日志文件: Log Level: 日志级别: None Error 错误 Warning 警告 Info 信息 Debug 调试 Note: To see the change of log level in console output (not in log file), application restart is required Reset 重置 Class Pro&file Directory: Title 标题 Program 程序 Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. 在 AntiMicroX 运行时禁用 Windows 的“提高指针精确度”选项。 禁用“提高指针精确度”可使鼠标在开启 AntiMicroX 的情况下更精准地移动。 Disable Enhance Pointer Precision 禁用提高指针精确度 Smoothing 平滑 Refresh Rate: 刷新率: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. 刷新率是鼠标事件之间间隔的时间。 请小心修改此选项,因为它可能会导致本程序使用更多的处理器资源。 此选项的值过低可能会导致系统不稳定。 请在以无人值守方式使用前测试此选项。 Accel Numerator: 加速度分子: 0 0 Accel Denominator: 加速度分母: Accel Threshold: 加速度阈值: If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. 如果虚拟鼠标的加速度值被另一个进程改变,尤其是在退出老游戏的时候,您可能需要重置虚拟鼠标使用的加速度值。 Reset Acceleration 重置加速度 Delay: 延迟: Profi&le Directory: 配置文件目录 (&l): Have Windows start AntiMicroX at system startup. 在 Windows 启动时运行本程序。 Associate .amgp files with AntiMicroX in Windows Explorer. 在 Windows 资源管理器中将 .amgp 文件关联到 AntiMicroX。 Specifies how much time should elapse before key repeating begins. 指定开始键重复之前的延迟时间。 ms 毫秒 Rate: 频率: Specifies how many times key presses will be performed per seconds. 指定每秒按键多少次。 times/s 次/秒 Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. 下面是已保存的自定义映射。您可以使用下表删除或临时禁用一个映射。您还可以禁用 SDL 中包含的映射。您只需要插入新的一行,指定摇杆的全局统一标识符,然后勾选禁用。 设置仅在您刷新所有摇杆或者拔出那个被禁用的摇杆之后生效。 GUID 全局唯一标识符 Mapping String 映射字符串 Disable? 禁用? Delete 删除 Insert 插入 <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> <html><head/><body><p>AntiMicroX 已被贡献者翻译为多种语言。默认情况下,本程序将根据您系统的区域设置选择相应的语言。然而,您也可以让 AntiMicroX 加载以下列表中的任意语言。</p></body></html> Default 默认 English 英语 简体中文 简体中文 Active 启用 Devices: 设备: All 所有 Device 设备 Profile 配置文件 Default? 默认? Add 添加 Edit 编辑 Histor&y Size: 历史缓冲大小 (&y): Weight &Modifier: 权重修饰因数 (&M): Spring 弹簧 Screen: 屏幕: Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. 在弹簧模式中使用指定的屏幕。 在 Linux 系统上,默认使用主屏幕。 在 Windows 系统上,默认使用所有可用屏幕。 Also, Windows users who want to use a low value should also check the "Disable Enhance Pointer Precision" checkbox if you haven't disabled the option in Windows. 另外,对于希望使用较低值的 Windows 用户,如果您未禁用 Windows 的“提高指针精确度”选项,请勾选本程序中的“禁用提高指针精确度”复选框。 Select Default Profile Directory 选择默认配置文件目录 Are you sure you want to delete the profile? 您确认要删除这个配置文件吗? Save Log File As 日志文件另存为 Log Files (*.log) 日志文件 (*.log) Do you really want to reset setting? Would you like to reset mappings too? [NO KEY] MainWindow AntiMicroX AntiMicroX No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu 未找到摇杆。 请插入一个摇杆然后选择“选项”菜单下的“更新摇杆” If events are not seen by a game, please click here to run this application as Administrator. 如果游戏无法检测到事件,请单击这里以管理员身份运行。 &App 程序 (&A) &Options 选项 (&O) &Help 帮助 (&H) He&lp &Quit 退出 (&Q) Ctrl+Q Ctrl+Q &Update Joysticks 更新摇杆 (&U) Ctrl+U Ctrl+U &Hide 隐藏 (&H) Ctrl+H Ctrl+H &About 关于 (&A) Ctrl+A Ctrl+A About &Qt Ctrl+T &Properties Ctrl+P &Key Checker Ctrl+K &GitHub Page Ctrl+G &Game Controller Mapping Ctrl+M S&ettings Ctrl+S &Stick/Pad Assign Ctrl+X &Wiki Ctrl+W &Issues Ctrl+I &Calibration Ctrl+C About Qt 关于 Qt Properties 属性 Key Checker 按键检查器 Home Page 主页 GitHub Page GitHub 页面 Game Controller Mapping 游戏控制器映射 Settings 设置 Stick/Pad Assign 摇杆/十字键分配 Wiki 维基页面 Could not find a proper controller identifier. Exiting. 无法找到合适的游戏控制器标识符。正在退出。 (%1) (%1) Open File 打开文件 %1 battery Battery level is less than %1 Device number: %1 Device name: %2 Reading old profile This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for use in identical gamecontrollers? Such old file cannot be loaded in AntiMicroX since version 2.25 &Restore 还原 (&R) Calibration couldn't be opened You must connect at least one controller to open the window Run as Administrator? 以管理员权限运行? Are you sure that you want to run this program as Adminstrator? Some games run as Administrator which will cause events generated by AntiMicroX to not be used by those games unless AntiMicroX is also run as the Adminstrator. This is due to permission problems caused by User Account Control (UAC) options in Windows Vista and later. 您确定要使用管理员权限运行本程序吗? 有些以管理员权限运行的游戏无法识别 AntiMicroX 生成的事件,除非 AntiMicroX 也使用管理员权限运行。这是由于 Windows Vista 及以后系统中用户帐户控制 (UAC) 导致的权限问题。 Failed to elevate program 无法提升本程序权限 Failed to restart this program as the Administrator 无法以管理员权限重新运行本程序 Could not find controller. Exiting. 无法找到游戏控制器。正在退出。 MouseAxisSettingsDialog Mouse Settings - 鼠标设置 - Set %1 设置%1 MouseButtonSettingsDialog Mouse Settings - 鼠标设置 - Set %1 设置%1 MouseControlStickSettingsDialog Mouse Settings 鼠标设置 Set %1 设置%1 MouseDPadSettingsDialog Mouse Settings 鼠标设置 Set %1 设置%1 MouseSettingsDialog Mouse Settings 鼠标设置 Mouse Mode: 鼠标模式: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. 光标:移动时,鼠标光标以当前位置为基准,移动距离取决于您移动轴或按下按钮的幅度。 弹簧:移动时,鼠标光标以屏幕中心为基准,移动距离取决于您移动轴的幅度。轴移回不灵敏区之后,鼠标光标将回到屏幕中心。 Cursor 光标 Spring 弹簧 Acceleration: 加速模式: Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. 增强精度:三级曲线使得鼠标光标在轴移动幅度较小时移动慢,轴移动幅度较大时移动快。 线性:鼠标移动速度和轴移动幅度成比例。 平方:鼠标光标在轴移动幅度较小时缓慢加速。 立方:鼠标加速度比平方模式慢。 极限平方:轴移动距离达到95%后提升1.5倍鼠标速度。 指数函数:允许更多自定义曲线选项。 平方缓动:轴移动幅度较大时,鼠标速度随时间以平方曲线增加。 立方缓动:轴移动幅度较大时,鼠标速度随时间以立方曲线增加。 Enhanced Precision 增强精度 Linear 线性 Quadratic 平方 Cubic 立方 Quadratic Extreme 极限平方 Power Function 指数函数 Easing Quadratic 平方缓动 Easing Cubic 立方缓动 Mouse Speed Settings 鼠标速度设置 Enable to change the horizontal and vertical speed boxes at the same time. 同时改变水平和垂直速度。 Change Together 同时更改 Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. 在加速曲线之上为鼠标移动增添额外加速。 加速度基于手柄在一次采样时间内轴移动的速度。 这些选项是为了绕过某些由于手柄模拟摇杆的输入范围有限所带来的问题。 Delta Acceleration 额外加速 &Multiplier: 倍数 (&M): Mi&n Threshold: 最小阈值 (&N): E&xtra Duration: 额外加速时长 (&X): 1 = 20 pps 1级=20像素/秒 Wheel Hori. Speed: 滚轮水平速度: Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. 根据每秒模拟滚动凹槽数设置鼠标滚轮水平滚动速度。 Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. 根据每秒模拟滚动凹槽数设置鼠标滚轮垂直滚动速度。 Sensitivit&y: 灵敏度 (&Y): For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. 仅用于指数函数加速曲线。 指定曲线敏感度系数。当该值大于1.0时,增大轴移动幅度较小时的鼠标加速度。 Easing Duration: 缓动时长: Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. 轴移动幅度达到最大后,鼠标在此时长(以秒为单位)内加速到最大速度。 s Highest value to accelerate mouse movement by 鼠标速度的最大加速值 x x Start %: 起始百分比: Acceleration begins at this percentage of the base multiplier 加速以基础倍数的此百分比速率开始 % % Minimum amount of axis travel required for acceleration to begin 轴的移动幅度大于此最小阈值之后加速才开始 Max Threshold: 最大阈值: Maximum axis travel before acceleration has reached the multiplier value 轴的移动幅度达到此最大阈值时加速达到上述倍数值 Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. 此期间内额外加速生效。 轴的移动幅度考虑在内。缓慢的轴移动将减小实际的额外加速生效时间。 Curve: 曲线: Ease Out Sine 正弦滑出缓动 Ease Out Quad 平方滑出缓动 Ease Out Cubic 立方滑出缓动 Release Radius: 释放半径: Specifies that the spring area will be relative to the mouse position set by a non-relative spring. 弹簧区域将相对于鼠标指针的位置。鼠标指针的位置可由其它非弹簧模式指定。 Relative 相对 Mouse Status 鼠标状态 X: X轴: 0 (0 pps) 0(0像素/秒) Y: Y轴: 1 = 1 notch(es)/s 1级=1凹槽/秒 Hori&zontal Speed: 水平速度 (&Z): &Vertical Speed: 垂直速度 (&V): Wheel Vert. Speed: 滚轮垂直速度: Spring Settings 弹簧设置 Spring Width: 弹簧区域宽度: Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. 设置鼠标以弹簧模式移动的区域的宽度。设为0时将使用您整个屏幕的宽度。 Spring Height: 弹簧区域高度: Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. 设置鼠标以弹簧模式移动的区域的高度。设为0时将使用您整个屏幕的高度。 %n notch(es)/s %n凹槽/秒 ProfileImporter Form Import profile from: &JoyToKey Pinnacle &Game Profiler &XPadder Imported file Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings Imported settings Find configuration file... Remember about connection of gamecontrollers before profiles importing Cancel 取消 OK Extension of file is incorrect. Choose one type of profile and define full path of file. Incorrect extension JoyToKey profiles (*.cfg) XPadder profiles (*.xpaddercontroller) Pinnacle Game profiles (*.pin) Find Could not import profile. Choose profile type and profile's file. Insufficient data Could not define file's extension. Choose profile's type first above. Choose game profile Could not choose a file. Find a file with proper extension. Incorrect filename Choose app settings file Settings file (*.ini) QKeyDisplayDialog Key Checker 按键检查器 <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> <html><head/><body><p>按下您键盘上的一个键来观察本程序如何检测按键。本窗口将显示系统原生键值、Qt 原始键值(如果可用)和 AntiMicroX 使用的自定义键值。</p><p>AntiMicroX 键值和 Qt 键值通常是一样的。如果可能,AntiMicroX 将优先使用 Qt 中已定义的键值。如果想了解 Qt 中已定义的键值列表,请查看页面 <a href="https://doc.qt.io/qt-4.8/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">https://doc.qt.io/qt-4.8/qt.html#Key-enum</span></a>。如果您发现某个键没有被本程序原生支持,请将问题报告至 AntiMicroX 的 <a href="https://github.com/AntiMicroX/AntiMicroX"><span style=" text-decoration: underline; color:#0057ae;">GitHub 页面</span></a>,以便我们修改程序后直接支持这个键。如您所见,未知的键值将被附加一个自定义前缀。这样一来,它们就能被使用了,不过最大的问题是含有这个键的配置文件将无法在其它地方使用。</p></body></html> <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/AntiMicroX/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Event Handler: 事件处理程序: Native Key Value: 系统原生键值: 0x00000000 0x00000000 Qt Key Value: Qt 原始键值: antimicro Key Value: AntiMicroX Key Value: AntiMicroX 自定义键值: QObject Super Super Menu Menu Mute Mute Vol+ Vol+ Vol- Vol- Play/Pause Play/Pause Play Play Pause Pause Prev Prev Next Next Mail Mail Home Home Media Media Search Search Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. Daemon launched 后台服务已启动 Failed to launch daemon 无法启动后台服务 Launching daemon 正在启动后台服务 Display string "%1" is not valid. 显示字符串“%1”无效。 Failed to set a signature id for the daemon 无法为后台服务设置签名ID Failed to change working directory to / 无法切换工作路径到根目录 Quitting Program 正在退出程序 # of joysticks found: %1 已发现摇杆数:%1 List Joysticks: 摇杆列表: --------------- --------------- Joystick %1: 摇杆%1: Index: %1 编号:%1 GUID: %1 全局唯一标识符:%1 UniqueID: %1 VendorID: %1 ProductID: %1 Product Version: %1 Name: %1 名称:%1 Yes No Game Controller: %1 游戏控制器:%1 # of Axes: %1 轴数:%1 # of Buttons: %1 按钮数:%1 # of Hats: %1 帽子开关数:%1 Attempting to use fallback option %1 for event generation. 尝试为事件生成使用后备选项 %1。 Failed to open event generator. Exiting. 无法打开事件发生器。正在退出。 Using %1 as the event generator. 使用 %1 作为事件发生器。 Could not raise process priority. 无法提升进程优先级。 Auto-switching to profile "%1". 自动切换到配置文件“%1”。 Auto-switching to nullptr profile! Auto-switching to NULL profile! 自动切换到空配置文件! Logging started 日志记录已开始 Active window changed to: Title = "%1", Class = "%2", Program = "%3" or "%4". 活动窗口已更改至:标题 = “%1”,类 = “%2”,程序 = “%3”或“%4”。 Last button There isn't a last button pressed from gamepad in data. Did you set at least one button from gamepad for keyboard? Profile location %1 is not an XML file. 配置文件 %1 不是一个 XML 文件。 Profile location %1 does not exist. 配置文件 %1 不存在。 Controller identifier is not a valid value. 游戏控制器标识符无效。 An invalid set number '%1' was specified. 指定的设置编号 "%1" 无效。 Controller identifier '%s'' is not a valid value. 游戏控制器标识符 "%s" 无效。 No set number was specified. 未指定设置编号。 No controller was specified. 未指定游戏控制器。 No display string was specified. 未指定显示字符串。 An invalid event generator was specified. 指定的事件发生器无效。 No event generator string was specified. 未指定事件发生器字符串。 Qt style flag was detected but no style was specified. 检测到 Qt 样式标识,但未指定样式。 No log file specified. 未指定日志文件。 AntiMicroX version AntiMicroX 版本 Usage: AntiMicroX [options...] [profile] 用法:AntiMicroX [选项] [配置文件] Options 选项 Print help text. 打印帮助文本。 Print version information. 打印版本信息。 Launch program in system tray only. 启动后最小化到系统托盘。 Launch program with the tray menu disabled. 启动后禁用系统托盘菜单。 Launch program without the main window displayed. 启动后不显示主窗口。 Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers. 启动后将指定的配置文件作为默认配置文件。默认应用到所有游戏控制器。 Apply configuration file to a specific controller. Value can be a controller index, name, or GUID. 应用配置文件到指定的游戏控制器。值可以是编号、名称或全局唯一标识符。 Unload currently enabled profile(s). Value can be a controller index, name, or GUID. 卸载当前生效的配置文件。值可以是控制器编号、名称或全局唯一标识符。 Start joysticks on a specific set. Value can be a controller index, name, or GUID. 为摇杆指定设置编号。值可以是控制器编号、名称或全局唯一标识符。 Advance profile loading set options. 切换到下一个配置文件载入选项。 Launch program as a daemon. 以后台服务方式启动程序。 Enable logging. 开启日志。 Use specified display for X11 calls. Useful for ssh. 为 X11 调用指定显示设备。对 ssh 尤其有用。 Choose between using XTest support and uinput support for event generation. Default: xtest. 为事件发生器选择 XTest 支持或 uinput 支持。默认:XTest。 Choose between using SendInput and vmulti support for event generation. Default: sendinput. 为事件发生器选择使用 SendInput 或 vmulti 支持。默认:SendInput。 Print information about joysticks detected by SDL. 打印 SDL 检测到的摇杆。 Open game controller mapping window of selected controller. Value can be a controller index or GUID. 为所选的游戏控制器打开游戏控制器映射窗口。值可以是控制器编号或全局唯一标识符。 xinput version must be at least 2.0. No mouse acceleration changes will occur. XInput 版本必需至少为2.0。鼠标加速选项将无效。 QuickSetDialog Quick Set 快速设置 <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> <html><head/><body><p>请在 %1(<span style=" font-weight:600;">%2</span>)上按任意键或移动任意轴。<br/>之后一个对话框会弹出并允许您设置按键分配。</p></body></html> Quick Set %1 快速设置 %1 SetAxisThrottleDialog Throttle Change 阀设置改变 The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? 轴%1的阀设置已改变。 您想将这个阀设置的改变应用到所有设置吗? SetJoystick Set %1: %2 设置%1:%2 Set %1 设置%1 SetNamesDialog Set Name Settings 指定设置名称 Set 1 设置1 Set 2 设置2 Set 3 设置3 Set 4 设置4 Set 5 设置5 Set 6 设置6 Set 7 设置7 Set 8 设置8 Name 名称 SimpleKeyGrabberButton Mouse 鼠标 SpringModeRegionPreview Spring Mode Preview 弹簧模式预览 UInputEventHandler Could not find a valid uinput device file. Please check that you have the uinput module loaded. lsmod | grep uinput 无法找到任何有效的 uinput 设备文件。 请确认您加载了 uinput 模块: lsmod | grep uinput Could not open uinput device file Please check that you have permission to write to the device 无法打开 uinput 设备文件 请确认您有写入该设备的权限 Using uinput device file %1 使用 uinput 设备文件%1 UInputHelper a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z Esc Esc F1 F1 F2 F2 F3 F3 F4 F4 F5 F5 F6 F6 F7 F7 F8 F8 F9 F9 F10 F10 F11 F11 F12 F12 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 ` ` 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 - - = = BackSpace BackSpace Tab Tab [ [ ] ] \ \ CapsLock CapsLock ; ; ' ' Enter Enter Shift_L Shift_L , , . . / / Ctrl_L Ctrl_L Super_L Super_L Alt_L Alt_L Space Space Alt_R Alt_R Menu Menu Ctrl_R Ctrl_R Shift_R Shift_R Up Up Left Left Down Down Right Right PrtSc PrtSc Ins Ins Del Del Home Home End End PgUp PgUp PgDn PgDn NumLock NumLock * * + + KP_Enter KP_Enter KP_1 KP_1 KP_2 KP_2 KP_3 KP_3 KP_4 KP_4 KP_5 KP_5 KP_6 KP_6 KP_7 KP_7 KP_8 KP_8 KP_9 KP_9 KP_0 KP_0 SCLK SCLK Pause Pause Super_R Super_R Mute Mute VolDn VolDn VolUp VolUp Play Play Stop Stop Prev Prev Next Next [NO KEY] [NO KEY] UnixWindowInfoDialog Captured Window Properties 捕获的窗口属性 Information About Window 窗口信息 Class: 类: TextLabel 文本标签 Title: 标题: Path: 路径: Match By Properties 根据属性匹配 Class Title 标题 Path 路径 VDPad VDPad 虚拟十字键 VirtualKeyPushButton Space Space Tab Tab Shift (L) Shift (L) Shift (R) Shift (R) Ctrl (L) Ctrl (L) Ctrl (R) Ctrl (R) Alt (L) Alt (L) Alt (R) Alt (R) Alt Gr ` ` ~ ~ - - = = [ [ ] ] \ \ Caps Caps ; ; ' ' , , . . / / ESC ESC PRTSC PRTSC SCLK SCLK INS INS PGUP PGUP DEL DEL PGDN PGDN 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 NUM LK NUM LK * * + + Enter Enter Del Del E N T E R E N T E R < < : : Super (L) Super (L) Menu Menu Up Up Down Down Left Left Right Right VirtualKeyboardMouseWidget Keyboard 键盘 Mouse 鼠标 Mouse Settings 鼠标设置 Left Mouse Up Mouse Left Button Mouse 左键 Middle Button Mouse 中键 Right Button Mouse 右键 Wheel Up Mouse 滚轮向上 Wheel Left Mouse 滚轮向左 Wheel Right Mouse 滚轮向右 Wheel Down Mouse 滚轮向下 Down Mouse Right Mouse Button 4 Mouse 按钮4 Mouse 8 Mouse 按钮8 Button 5 Mouse 按钮5 Mouse 9 Mouse 按钮9 NONE [NO KEY] Last button Slots for button couldn't be cleared, because there was not any set button from keyboard for gamepad. Map at least one button from keyboard to gamepad Others Applications 应用程序 Browser Back 浏览器后退 Browser Favorites 浏览器收藏 Browser Forward 浏览器前进 Browser Home 浏览器主页 Browser Refresh 浏览器刷新 Browser Search 浏览器搜索 Browser Stop 浏览器停止 Calc 计算器 Email 邮件 F13 F13 F14 F14 F15 F15 F16 F16 F17 F17 F18 F18 F19 F19 F20 F20 F21 F21 F22 F22 F23 F23 F24 F24 Media 多媒体 Media Next 多媒体下一首 Media Play 多媒体播放 Media Previous 多媒体上一首 Media Stop 多媒体停止 Search 搜索 Volume Down 音量减小 Volume Mute 静音 Volume Up 音量增加 VirtualMousePushButton INVALID 无效 WinAppProfileTimerDialog Capture Application 捕捉应用程序 After pressing the "Capture Application" button, please select the application window that you want to have a profile associated with. The active application will be captured after the selected number of seconds. 按下“捕捉应用程序”按钮之后,请选择您想要关联配置文件的应用程序窗口。活动的应用程序将在指定的秒数之后被捕捉。 Timer: 计时器: Seconds Cancel 取消 WinExtras [NO KEY] [无按键] AntiMicroX Profile AntiMicroX 配置文件 X11Extras ESC ESC Tab Tab Space Space DEL DEL Return Return KP_Enter KP_Enter Backspace Backspace Alt Gr xinput extension was not found. No mouse acceleration changes will occur. 未找到 XInput 扩展。鼠标加速选项将无效。 xinput version must be at least 2.0. No mouse acceleration changes will occur. XInput 版本必需至少为2.0。鼠标加速选项将无效。 Virtual pointer found with id=%1. 发现虚拟指针 ID=%1。 PtrFeedbackClass was not found for virtual pointer.No change to mouse acceleration will occur for device with id=%1 未找到虚拟指针的 PtrFeedbackClass。鼠标加速选项在 ID=%1 的设备上将无效 Changing mouse acceleration for device with id=%1 正在改变 ID=%1 的设备上的鼠标加速选项 XMLConfigReader Could not write updated profile XML to file %1. 无法将更新后的配置 XML 写入文件 %1。 XMLConfigWriter Could not write to profile at %1. 无法写入配置文件 %1。 AntiMicroX Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. main Launch program in system tray only. 启动后最小化到系统托盘。 Launch program with the tray menu disabled Launch program without the main window displayed Launch program with the configuration file selected as the default for selected controllers. Defaults to all controllers location Apply configuration file to a specific controller. Value can be a controller index, name, or GUID value Unload currently enabled profile(s) value(s) Start joysticks on a specific set. Value can be a controller index, name, or GUID number value Launch program as a daemon. Use only on Linux. Enable logging log-type Choose a file for logs writing filename Choose between using XTest support and uinput support for event generation. Use only if you have enabled xtest and uinput options on Linux or vmulti on Windows. Default: xtest. event-generation-type Print information about joysticks detected by SDL. Use only if you have sdl library. You can check your controller index, name or even GUID. AntiMicroX-antimicrox-2888bf6/src/000077500000000000000000000000001377703515000170525ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/aboutdialog.cpp000066400000000000000000000074301377703515000220540ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "aboutdialog.h" #include "ui_aboutdialog.h" #include "common.h" #include "eventhandlerfactory.h" #include "messagehandler.h" #include #include #include #include #include #include #include #include #include AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::AboutDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); ui->versionLabel->setText(PadderCommon::programVersion); fillInfoTextBrowser(); } AboutDialog::~AboutDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void AboutDialog::fillInfoTextBrowser() { qInstallMessageHandler(MessageHandler::myMessageOutput); QStringList finalInfoText = QStringList(); finalInfoText.append(tr("Program Version %1").arg(PadderCommon::programVersion)); finalInfoText.append(tr("Program Compiled on %1 at %2").arg(__DATE__).arg(__TIME__)); QString sdlCompiledVersionNumber("%1.%2.%3"); QString sdlLinkedVersionNumber("%1.%2.%3"); SDL_version compiledver; SDL_version linkedver; SDL_VERSION(&compiledver); SDL_GetVersion(&linkedver); sdlCompiledVersionNumber = sdlCompiledVersionNumber.arg(compiledver.major).arg(compiledver.minor).arg(compiledver.patch); finalInfoText.append(tr("Built Against SDL %1").arg(sdlCompiledVersionNumber)); sdlLinkedVersionNumber = sdlLinkedVersionNumber.arg(linkedver.major).arg(linkedver.minor).arg(linkedver.patch); finalInfoText.append(tr("Running With SDL %1").arg(sdlLinkedVersionNumber)); finalInfoText.append(tr("Using Qt %1").arg(qVersion())); BaseEventHandler *handler = nullptr; EventHandlerFactory *factory = EventHandlerFactory::getInstance(); if (factory != nullptr) { handler = factory->handler(); } if (handler != nullptr) { finalInfoText.append(tr("Using Event Handler: %1").arg(handler->getName())); } ui->infoTextBrowser->setText(finalInfoText.join("\n")); // Read Changelog text from resource and put text in text box. QResource changelogFile(":/CHANGELOG.md"); QFile temp(changelogFile.absoluteFilePath()); temp.open(QIODevice::Text | QIODevice::ReadOnly); QTextStream changelogStream(&temp); QString changelogText = changelogStream.readAll(); temp.close(); #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) ui->changelogTextEdit->setMarkdown(changelogText); #else ui->changelogTextEdit->setPlainText(changelogText); #endif } void AboutDialog::changeEvent(QEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (event->type() == QEvent::LanguageChange) retranslateUi(); QDialog::changeEvent(event); } void AboutDialog::retranslateUi() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->retranslateUi(this); ui->versionLabel->setText(PadderCommon::programVersion); } AntiMicroX-antimicrox-2888bf6/src/aboutdialog.h000066400000000000000000000023451377703515000215210ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ABOUTDIALOG_H #define ABOUTDIALOG_H #include class QEvent; namespace Ui { class AboutDialog; } class AboutDialog : public QDialog { Q_OBJECT public: explicit AboutDialog(QWidget *parent = nullptr); ~AboutDialog(); private: Ui::AboutDialog *ui; protected: void fillInfoTextBrowser(); virtual void changeEvent(QEvent *event); void retranslateUi(); }; #endif // ABOUTDIALOG_H AntiMicroX-antimicrox-2888bf6/src/aboutdialog.ui000066400000000000000000002255021377703515000217110ustar00rootroot00000000000000 AboutDialog 0 0 640 480 640 480 About 10 6 50 110 0 0 64 64 64 64 :/images/antimicrox.png true false 0 0 14 75 true AntiMicroX Qt::AlignHCenter|Qt::AlignTop 0 -1 0 0 11 Version Qt::AlignCenter 4 false Credits 0 0 IBeamCursor <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Cantarell'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Originally developed by Travis Nickles &lt;nickles.travis@gmail.com&gt;. </p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Next maintained by the AntiMicro group at https://github.com/AntiMicro.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Then by juliagoda at https://github.com/juliagoda.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Now maintained at https://github.com/AntiMicroX/antimicrox.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Contributors:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">https://github.com/AntiMicroX/antimicrox/graphs/contributors</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">Translators:</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-weight:600;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">VaGNaroK &lt;vagnarokalkimist@gmail.com&gt; - Brazilian Portuguese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">zzpxyx - Chinese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Belleguic Terence &lt;hizo@free.fr&gt; - French</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:9pt;">Leonard Koenig &lt;leonard.r.koenig@googlemail.com&gt; - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">phob - German</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">tou omiya - Japanese</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Dmitriy Koshel &lt;form.eater@gmail.com&gt; - Russian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Jay Alexander Fleming &lt;tito.nehru.naser@gmail.com&gt; - Serbian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">burunduk - Ukrainian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Flavio HR &lt;flavio.hrx@gmail.com&gt; - Spanish</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">WAZAAAAA - wazaaaaa00&lt;@&gt;gmail&lt;.&gt;com - Italian</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">juliagoda &lt;juliagoda.pl@protonmail.com&gt; - Polish</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></body></html> true Info License 0 0 IBeamCursor <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">GNU GENERAL PUBLIC LICENSE</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Version 3, 29 June 2007</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Copyright (C) 2007 Free Software Foundation, Inc. &lt;http://fsf.org/&gt;</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Preamble</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Developers that use the GNU GPL protect your rights with two steps:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">(1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The precise terms and conditions for copying, distribution and modification follow.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">TERMS AND CONDITIONS</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">0. Definitions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;This License&quot; refers to version 3 of the GNU General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Copyright&quot; also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;The Program&quot; refers to any copyrightable work licensed under this License. Each licensee is addressed as &quot;you&quot;. &quot;Licensees&quot; and &quot;recipients&quot; may be individuals or organizations.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;modify&quot; a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a &quot;modified version&quot; of the earlier work or a work &quot;based on&quot; the earlier work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;covered work&quot; means either the unmodified Program or a work based on the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;propagate&quot; a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">To &quot;convey&quot; a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An interactive user interface displays &quot;Appropriate Legal Notices&quot; to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">1. Source Code.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;source code&quot; for a work means the preferred form of the work for making modifications to it. &quot;Object code&quot; means any non-source form of a work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;Standard Interface&quot; means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;System Libraries&quot; of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A &quot;Major Component&quot;, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The &quot;Corresponding Source&quot; for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Corresponding Source for a work in source code form is that same work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">2. Basic Permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">3. Protecting Users' Legal Rights From Anti-Circumvention Law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">4. Conveying Verbatim Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">5. Conveying Modified Source Versions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) The work must carry prominent notices stating that you modified it, and giving a relevant date.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to &quot;keep intact all notices&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an &quot;aggregate&quot; if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">6. Conveying Non-Source Forms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;User Product&quot; is either (1) a &quot;consumer product&quot;, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, &quot;normally used&quot; refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Installation Information&quot; for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">7. Additional Terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">&quot;Additional permissions&quot; are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">d) Limiting the use for publicity purposes of names of licensors or authors of the material; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">All other non-permissive additional terms are considered &quot;further restrictions&quot; within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">8. Termination.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">9. Acceptance Not Required for Having Copies.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">10. Automatic Licensing of Downstream Recipients.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">An &quot;entity transaction&quot; is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">11. Patents.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A &quot;contributor&quot; is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's &quot;contributor version&quot;.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A contributor's &quot;essential patent claims&quot; are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, &quot;control&quot; includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">In the following three paragraphs, a &quot;patent license&quot; is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To &quot;grant&quot; such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. &quot;Knowingly relying&quot; means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">A patent license is &quot;discriminatory&quot; if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">12. No Surrender of Others' Freedom.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">13. Use with the GNU Affero General Public License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">14. Revised Versions of this License.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License &quot;or any later version&quot; applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">15. Disclaimer of Warranty.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">16. Limitation of Liability.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">17. Interpretation of Sections 15 and 16.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.</span></p></body></html> false Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse true Changelog true About Development 30 true "pktiuk" (since August 2020) I just want to ensure, that this very useful piece of software will not be abandoned, I decided to conticue providing support for this project and make it as widely accessible as possible. "juliagoda" (since March, 2018 until 2020) Wanting only to play my favourite old games that din't support gamepads, I found this project (which map keyboard keys and mouse buttons to connected gamepads on Linux) as most proper and recent. But because of poor choices of such application on the internet and since it didn't compile properly, I decided to rescue the project. However, once I finished my work (enough to enjoy playing games) I thought about sharing this code with others. Of course all informations about past programmers will be held. "Ryochan7" (since December 30, 2012 until 2017), I have been working on AntiMicro in my spare time. What originally started as a fork of QJoyPad and a way to learn proper event-driven programming has turned into something much bigger than I originally intended. Although I have spent a lot of time learning new techniques, finding out more about the domain of KB+M emulation, and spending Friday nights bashing my head against my keyboard, it has been a fun and enriching experience overall. The need for this program came from me using similar programs on Windows to play several games that did not provide native controller support. Although some alternatives existed on Linux, there wasn't really anything that I felt was good enough in terms of functionality or in-game controls in order to really enjoy games that I wanted to play with using KB+M emulation. QJoyPad was the main program that I had used in the past although it had aged a lot and it didn't provide some basic functionality that I thought was essential. The project was dead as it had not been updated in several years so I decided to make my own. Since then, I have tried to find out what the other programs do right and then improve upon it. I have also discovered some neat tricks along the way and I have learned more about how native gamepad controls are implemented in some games than I ever really wanted to know. Although there are definitely areas where this program could improve, I find that this program offers the best in-game control experience for playing older, and some newer, games that do not provide native controller support. Development of this program is not as high of a priority for me anymore. This is mainly due to the fact that the Steam Controller works pretty well for the task of playing PC games compared to using an Xbox 360 controller. However, it does look like there is still a reason for this program to exist for a while. --- As of May 24, 2016, this project has moved to https://github.com/AntiMicro/antimicro. Additionally, project management has passed from Travis (Ryochan7) to the AntiMicro organization due to Travis having other interests and priorities. As next, project has been continued since 2018 by juliagoda on antimicroX project. Later project has been once more moved to https://github.com/AntiMicroX/antimicrox and it's its maintenance is continued by organisation AntiMicroX created by pktiuk. Copyright: 2013 - 2020 Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing -1 Qt::Horizontal 40 20 QDialogButtonBox::Close buttonBox accepted() AboutDialog accept() 63 473 319 239 buttonBox rejected() AboutDialog reject() 478 462 319 239 AntiMicroX-antimicrox-2888bf6/src/addeditautoprofiledialog.cpp000066400000000000000000000417301377703515000246130ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "addeditautoprofiledialog.h" #include "ui_addeditautoprofiledialog.h" #include "antimicrosettings.h" #include "autoprofileinfo.h" #include "common.h" #include "inputdevice.h" #include "messagehandler.h" #ifdef WITH_X11 #include "capturedwindowinfodialog.h" #include "unixcapturewindowutility.h" #include "x11extras.h" #endif #include #include #include #include #include #include #include AddEditAutoProfileDialog::AddEditAutoProfileDialog(AutoProfileInfo *info, AntiMicroSettings *settings, QList *devices, QList &reservedUniques, bool edit, QWidget *parent) : QDialog(parent) , ui(new Ui::AddEditAutoProfileDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->info = info; this->settings = settings; this->editForm = edit; this->devices = devices; this->originalUniqueID = info->getUniqueID(); this->originalExe = info->getExe(); this->originalWindowClass = info->getWindowClass(); this->originalWindowName = info->getWindowName(); if (info->isPartialState()) ui->setPartialCheckBox->setChecked(true); else ui->setPartialCheckBox->setChecked(false); QListIterator iterUniques(reservedUniques); while (iterUniques.hasNext()) { QString uniqueID = iterUniques.next(); if (!getReservedUniques().contains(uniqueID)) this->reservedUniques.append(uniqueID); } ui->devicesComboBox->addItem("all"); QListIterator iter(*devices); int found = -1; int numItems = 1; while (iter.hasNext()) { InputDevice *device = iter.next(); ui->devicesComboBox->addItem(device->getSDLName(), QVariant::fromValue(device)); if (device->getUniqueIDString() == info->getUniqueID()) found = numItems; numItems++; } if (!info->getUniqueID().isEmpty() && (info->getUniqueID() != "all")) { if (found >= 0) { ui->devicesComboBox->setCurrentIndex(found); } else { ui->devicesComboBox->addItem(tr("Current (%1)").arg(info->getDeviceName())); ui->devicesComboBox->setCurrentIndex(ui->devicesComboBox->count() - 1); } } ui->profileLineEdit->setText(info->getProfileLocation()); ui->applicationLineEdit->setText(info->getExe()); ui->winClassLineEdit->setText(info->getWindowClass()); ui->winNameLineEdit->setText(info->getWindowName()); ui->selectWindowPushButton->setVisible(false); ui->asDefaultCheckBox->setEnabled(info->isCurrentDefault()); connect(ui->profileBrowsePushButton, &QPushButton::clicked, this, &AddEditAutoProfileDialog::openProfileBrowseDialog); connect(ui->applicationPushButton, &QPushButton::clicked, this, &AddEditAutoProfileDialog::openApplicationBrowseDialog); connect(ui->devicesComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AddEditAutoProfileDialog::checkForReservedUniques); connect(ui->devicesComboBox, static_cast(&QComboBox::currentTextChanged), this, &AddEditAutoProfileDialog::checkDefaultCheckbox); connect(ui->applicationLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); connect(ui->winClassLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); connect(ui->winNameLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); connect(ui->detectWinPropsSelectWindowPushButton, &QPushButton::clicked, this, &AddEditAutoProfileDialog::showCaptureHelpWindow); connect(this, &AddEditAutoProfileDialog::accepted, this, &AddEditAutoProfileDialog::saveAutoProfileInformation); ui->asDefaultCheckBox->setChecked(info->isCurrentDefault()); } // created for tests AddEditAutoProfileDialog::AddEditAutoProfileDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::AddEditAutoProfileDialog) { } AddEditAutoProfileDialog::~AddEditAutoProfileDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void AddEditAutoProfileDialog::openProfileBrowseDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString lookupDir = PadderCommon::preferredProfileDir(settings); QString filename = QFileDialog::getOpenFileName(this, tr("Open Config"), lookupDir, QString("Config Files (*.amgp *.xml)")); if (!filename.isNull() && !filename.isEmpty()) ui->profileLineEdit->setText(QDir::toNativeSeparators(filename)); } void AddEditAutoProfileDialog::openApplicationBrowseDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString filename = QFileDialog::getOpenFileName(this, tr("Select Program"), QDir::homePath(), QString()); if (!filename.isNull() && !filename.isEmpty()) { QFileInfo exe(filename); if (exe.exists() && exe.isExecutable()) ui->applicationLineEdit->setText(filename); } } AutoProfileInfo *AddEditAutoProfileDialog::getAutoProfile() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return info; } void AddEditAutoProfileDialog::saveAutoProfileInformation() { qInstallMessageHandler(MessageHandler::myMessageOutput); info->setProfileLocation(ui->profileLineEdit->text()); int deviceIndex = ui->devicesComboBox->currentIndex(); if (deviceIndex > 0) { // Assume that if the following is not true, the GUID should // not be changed. if (!ui->devicesComboBox->itemData(deviceIndex, Qt::UserRole).isNull()) { InputDevice *device = ui->devicesComboBox->itemData(deviceIndex, Qt::UserRole).value(); info->setUniqueID(device->getUniqueIDString()); info->setDeviceName(device->getSDLName()); } } else { info->setUniqueID("all"); info->setDeviceName(""); } info->setExe(ui->applicationLineEdit->text()); info->setWindowClass(ui->winClassLineEdit->text()); info->setWindowName(ui->winNameLineEdit->text()); info->setDefaultState(ui->asDefaultCheckBox->isChecked()); info->setPartialState(ui->setPartialCheckBox->isChecked()); } void AddEditAutoProfileDialog::checkForReservedUniques(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); QVariant data = ui->devicesComboBox->itemData(index); if (index == 0) { ui->asDefaultCheckBox->setChecked(false); ui->asDefaultCheckBox->setEnabled(false); QMessageBox::warning(this, tr("Main Profile"), tr("Please use the main default profile selection.")); } else if (!data.isNull() && getReservedUniques().contains(data.value()->getUniqueIDString())) { ui->asDefaultCheckBox->setChecked(false); ui->asDefaultCheckBox->setEnabled(false); QMessageBox::warning(this, tr("Already selected"), tr("A different profile is already selected as the default for this device.")); } else { ui->asDefaultCheckBox->setEnabled(true); QMessageBox::information(this, tr("Chosen Profile"), tr("The selection will be used instead\nof the all default profile option.")); } } QString AddEditAutoProfileDialog::getOriginalUniqueID() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return originalUniqueID; } QString AddEditAutoProfileDialog::getOriginalExe() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return originalExe; } QString AddEditAutoProfileDialog::getOriginalWindowClass() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return originalWindowClass; } QString AddEditAutoProfileDialog::getOriginalWindowName() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return originalWindowName; } /** * @brief Display a simple message box and attempt to capture a window using the mouse */ void AddEditAutoProfileDialog::showCaptureHelpWindow() { qInstallMessageHandler(MessageHandler::myMessageOutput); #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { QMessageBox *box = new QMessageBox(this); box->setText(tr("Please select a window by using the mouse. Press Escape if you want to cancel.")); box->setWindowTitle(tr("Capture Application Window")); box->setStandardButtons(QMessageBox::NoButton); box->setModal(true); box->show(); UnixCaptureWindowUtility *util = new UnixCaptureWindowUtility(); QThread *thread = new QThread; // QTHREAD(this) util->moveToThread(thread); connect(thread, &QThread::started, util, &UnixCaptureWindowUtility::attemptWindowCapture); connect(util, &UnixCaptureWindowUtility::captureFinished, thread, &QThread::quit); connect(util, &UnixCaptureWindowUtility::captureFinished, box, &QMessageBox::hide); connect( util, &UnixCaptureWindowUtility::captureFinished, this, [this, util]() { checkForGrabbedWindow(util); }, Qt::QueuedConnection); connect(thread, &QThread::finished, box, &QMessageBox::deleteLater); connect(util, &UnixCaptureWindowUtility::destroyed, thread, &QThread::deleteLater); thread->start(); } #endif } /** * @brief Check if there is a program path saved in an UnixCaptureWindowUtility * object */ void AddEditAutoProfileDialog::checkForGrabbedWindow(UnixCaptureWindowUtility *util) { qInstallMessageHandler(MessageHandler::myMessageOutput); #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { long targetWindow = util->getTargetWindow(); bool escaped = !util->hasFailed(); bool failed = false; if (targetWindow != None) { // Attempt to find the appropriate window below the root window // that was clicked. qDebug() << "ORIGINAL: " << QString::number(targetWindow, 16); long tempWindow = X11Extras::getInstance()->findClientWindow(targetWindow); if (tempWindow > 0) { targetWindow = tempWindow; } qDebug() << "ADJUSTED: " << QString::number(targetWindow, 16); } if (targetWindow != None) { CapturedWindowInfoDialog *dialog = new CapturedWindowInfoDialog(targetWindow, this); connect(dialog, &CapturedWindowInfoDialog::accepted, [this, dialog]() { windowPropAssignment(dialog); }); dialog->show(); } else if (!escaped) { failed = true; } // Ensure that the operation was not cancelled (Escape wasn't pressed). if (failed) { QMessageBox box; box.setText(tr("Could not obtain information for the selected window.")); box.setWindowTitle(tr("Application Capture Failed")); box.setStandardButtons(QMessageBox::Close); box.raise(); box.exec(); } util->deleteLater(); } #endif } void AddEditAutoProfileDialog::windowPropAssignment(CapturedWindowInfoDialog *dialog) { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(ui->applicationLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); disconnect(ui->winClassLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); disconnect(ui->winNameLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); #ifdef WITH_X11 if (dialog->useFullWindowPath() && dialog->getSelectedOptions() & CapturedWindowInfoDialog::WindowPath) { ui->applicationLineEdit->setText(dialog->getWindowPath()); } else if (!dialog->useFullWindowPath() && dialog->getSelectedOptions() & CapturedWindowInfoDialog::WindowPath) { ui->applicationLineEdit->setText(QFileInfo(dialog->getWindowPath()).fileName()); } else { #endif ui->applicationLineEdit->clear(); #ifdef WITH_X11 } #endif #ifdef WITH_X11 if (dialog->getSelectedOptions() & CapturedWindowInfoDialog::WindowClass) { ui->winClassLineEdit->setText(dialog->getWindowClass()); } else { #endif ui->winClassLineEdit->clear(); #ifdef WITH_X11 } #endif #ifdef WITH_X11 if (dialog->getSelectedOptions() & CapturedWindowInfoDialog::WindowName) { ui->winNameLineEdit->setText(dialog->getWindowName()); } else { #endif ui->winNameLineEdit->clear(); #ifdef WITH_X11 } #endif checkForDefaultStatus(); connect(ui->applicationLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); connect(ui->winClassLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); connect(ui->winNameLineEdit, &QLineEdit::textChanged, this, &AddEditAutoProfileDialog::checkForDefaultStatus); } void AddEditAutoProfileDialog::checkForDefaultStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool status = ui->applicationLineEdit->text().length() > 0; status = status ? status : (ui->winClassLineEdit->text().length() > 0); status = status ? status : (ui->winNameLineEdit->text().length() > 0); if (status) { ui->asDefaultCheckBox->setChecked(false); ui->asDefaultCheckBox->setEnabled(false); } else { ui->asDefaultCheckBox->setEnabled(true); } } /** * @brief Validate the form that is contained in this window */ void AddEditAutoProfileDialog::accept() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool validForm = true; bool propertyFound = false; QString errorString = QString(); if (ui->profileLineEdit->text().length() > 0) { QFileInfo profileFileName(ui->profileLineEdit->text()); if (!profileFileName.exists()) { validForm = false; errorString = tr("Profile file path is invalid."); } } if (validForm && (ui->applicationLineEdit->text().isEmpty() && ui->winClassLineEdit->text().isEmpty() && ui->winNameLineEdit->text().isEmpty())) { validForm = false; errorString = tr("No window matching property was specified."); } else { propertyFound = true; } if (validForm && !ui->applicationLineEdit->text().isEmpty()) { QString exeFileName = ui->applicationLineEdit->text(); QFileInfo info(exeFileName); if (info.isAbsolute() && (!info.exists() || !info.isExecutable())) { validForm = false; errorString = tr("Program path is invalid or not executable."); } } if (validForm && !propertyFound && !ui->asDefaultCheckBox->isChecked()) { validForm = false; errorString = tr("No window matching property was selected."); } if (validForm) { QDialog::accept(); } else { QMessageBox msgBox; msgBox.setText(errorString); msgBox.setStandardButtons(QMessageBox::Close); msgBox.exec(); } } QList *AddEditAutoProfileDialog::getDevices() const { return devices; } AntiMicroSettings *AddEditAutoProfileDialog::getSettings() const { return settings; } bool AddEditAutoProfileDialog::getEditForm() const { return editForm; } bool AddEditAutoProfileDialog::getDefaultInfo() const { return defaultInfo; } QList const &AddEditAutoProfileDialog::getReservedUniques() { return reservedUniques; } void AddEditAutoProfileDialog::on_setPartialCheckBox_stateChanged(int arg1) { if (arg1 == 0) ui->winNameLineEdit->setEnabled(false); else ui->winNameLineEdit->setEnabled(true); } void AddEditAutoProfileDialog::checkDefaultCheckbox(const QString &text) { if (text == "all") { ui->asDefaultCheckBox->setChecked(false); ui->asDefaultCheckBox->setDisabled(true); } else { ui->asDefaultCheckBox->setDisabled(false); } } AntiMicroX-antimicrox-2888bf6/src/addeditautoprofiledialog.h000066400000000000000000000054551377703515000242640ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ADDEDITAUTOPROFILEDIALOG_H #define ADDEDITAUTOPROFILEDIALOG_H #include class AutoProfileInfo; class AntiMicroSettings; class InputDevice; class CapturedWindowInfoDialog; class UnixCaptureWindowUtility; namespace Ui { class AddEditAutoProfileDialog; } class AddEditAutoProfileDialog : public QDialog { Q_OBJECT public: explicit AddEditAutoProfileDialog(AutoProfileInfo *info, AntiMicroSettings *settings, QList *devices, QList &reservedUniques, bool edit = false, QWidget *parent = nullptr); AddEditAutoProfileDialog(QWidget *parent = nullptr); ~AddEditAutoProfileDialog(); AutoProfileInfo *getAutoProfile() const; QString getOriginalUniqueID() const; QString getOriginalExe() const; QString getOriginalWindowClass() const; QString getOriginalWindowName() const; QList *getDevices() const; AntiMicroSettings *getSettings() const; bool getEditForm() const; bool getDefaultInfo() const; QList const &getReservedUniques(); protected: virtual void accept(); signals: void captureFinished(); private slots: void openProfileBrowseDialog(); void openApplicationBrowseDialog(); void saveAutoProfileInformation(); void checkForReservedUniques(int index); void checkForDefaultStatus(); void windowPropAssignment(CapturedWindowInfoDialog *dialog); void showCaptureHelpWindow(); void checkForGrabbedWindow(UnixCaptureWindowUtility *util); void on_setPartialCheckBox_stateChanged(int arg1); void checkDefaultCheckbox(const QString &text); private: Ui::AddEditAutoProfileDialog *ui; AutoProfileInfo *info; QList *devices; AntiMicroSettings *settings; bool editForm; bool defaultInfo; QList reservedUniques; QString originalUniqueID; QString originalExe; QString originalWindowClass; QString originalWindowName; }; #endif // ADDEDITAUTOPROFILEDIALOG_H AntiMicroX-antimicrox-2888bf6/src/addeditautoprofiledialog.ui000066400000000000000000000150611377703515000244440ustar00rootroot00000000000000 AddEditAutoProfileDialog 0 0 478 461 Auto Profile Dialog true Pro&file: profileLineEdit Browse Window: false false 6 4 Select Window. Click on the appropriate application window and the application file path will be populated in the form. Detect Window Properties &Class: applicationLineEdit T&itle: applicationLineEdit set partial title Application: applicationLineEdit Browse Select Window. Click on the appropriate application window and the application file path will be populated in the form. Select De&vices: devicesComboBox false Select this profile to be the default loaded for the specified device. The selection will be used instead of the all default profile option. Set as Default for Controller Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() AddEditAutoProfileDialog accept() 254 401 157 274 buttonBox rejected() AddEditAutoProfileDialog reject() 322 401 286 274 AntiMicroX-antimicrox-2888bf6/src/advancebuttondialog.cpp000066400000000000000000002007761377703515000236070ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "advancebuttondialog.h" #include "ui_advancebuttondialog.h" #include "event.h" #include "globalvariables.h" #include "inputdevice.h" #include "joybutton.h" #include "joytabwidget.h" #include "messagehandler.h" #include "simplekeygrabberbutton.h" //#include "logger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include AdvanceButtonDialog::AdvanceButtonDialog(JoyButton *button, QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::AdvanceButtonDialog) , helper(button) { ui->setupUi(this); ui->stackedWidget->setCurrentWidget(ui->page); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); PadderCommon::inputDaemonMutex.lock(); // ui->splitSlotButton->hide(); m_button = button; oldRow = 0; int interval = m_button->getTurboInterval() / 10; getHelperLocal().moveToThread(button->thread()); if (m_button->getToggleState()) ui->toggleCheckbox->setChecked(true); if (m_button->isUsingTurbo()) { ui->turboCheckbox->setChecked(true); ui->turboSlider->setEnabled(true); } if (interval < GlobalVariables::AdvanceButtonDialog::MINIMUMTURBO) interval = GlobalVariables::JoyButton::ENABLEDTURBODEFAULT / 10; ui->turboSlider->setValue(interval); this->changeTurboText(interval); QListIterator iter(*(m_button->getAssignedSlots())); while (iter.hasNext()) { JoyButtonSlot *buttonslot = iter.next(); qDebug() << "slot string for grab btn is: " << buttonslot->getSlotString(); SimpleKeyGrabberButton *existingCode = new SimpleKeyGrabberButton(this); existingCode->setText(buttonslot->getSlotString()); switch (static_cast(buttonslot->getSlotMode())) { case 11: if (!buttonslot->getTextData().isEmpty()) { existingCode->setValue(buttonslot->getTextData(), JoyButtonSlot::JoyLoadProfile); existingCode->setToolTip(buttonslot->getTextData()); } break; case 13: if (!buttonslot->getTextData().isEmpty()) { existingCode->setValue(buttonslot->getTextData(), JoyButtonSlot::JoyTextEntry); existingCode->setToolTip(buttonslot->getTextData()); } break; case 14: if (!buttonslot->getTextData().isEmpty()) { existingCode->setValue(buttonslot->getTextData(), JoyButtonSlot::JoyExecute); existingCode->setToolTip(buttonslot->getTextData()); if (buttonslot->getExtraData().canConvert()) existingCode->getValue()->setExtraData(buttonslot->getExtraData().toString()); } break; // JoyMix case 15: qDebug() << "text data for joy mix is: " << buttonslot->getTextData(); qDebug() << "slot string for joy mix is: " << buttonslot->getSlotString(); qDebug() << "amount of mini slots: " << buttonslot->getMixSlots()->count(); if (!buttonslot->getTextData().isEmpty()) { existingCode->setValues(buttonslot->getTextData(), buttonslot->getMixSlots(), JoyButtonSlot::JoySlotInputAction::JoyMix); existingCode->setToolTip(buttonslot->getTextData()); // try again if (existingCode->text() == tr("[NO KEY]")) { existingCode->setValues(buttonslot->getTextData(), buttonslot->getMixSlots(), JoyButtonSlot::JoySlotInputAction::JoyMix); existingCode->setToolTip(buttonslot->getTextData()); existingCode->setText(buttonslot->getSlotString()); } qDebug() << "Existing code for Joy Mix: " << existingCode->text(); } break; default: existingCode->setValue(buttonslot->getSlotCode(), buttonslot->getSlotCodeAlias(), buttonslot->getSlotMode()); break; } QListWidgetItem *item = new QListWidgetItem(ui->slotListWidget); item->setData(Qt::UserRole, QVariant::fromValue(existingCode)); QHBoxLayout *layout = new QHBoxLayout(); layout->setContentsMargins(10, 0, 10, 0); layout->addWidget(existingCode); QWidget *widget = new QWidget(); widget->setLayout(layout); item->setSizeHint(widget->sizeHint()); ui->slotListWidget->setItemWidget(item, widget); connectButtonEvents(existingCode); } appendBlankKeyGrabber(); populateSetSelectionComboBox(); populateSlotSetSelectionComboBox(); if ((m_button->getSetSelection() > -1) && (m_button->getChangeSetCondition() != JoyButton::SetChangeDisabled)) { int selectIndex = m_button->getChangeSetCondition(); selectIndex += m_button->getSetSelection() * 3; if (m_button->getOriginSet() < m_button->getSetSelection()) selectIndex -= 3; ui->setSelectionComboBox->setCurrentIndex(selectIndex); } fillTimeComboBoxes(); ui->actionTenthsComboBox->setCurrentIndex(1); updateActionTimeLabel(); changeTurboForSequences(); if (button->isCycleResetActive()) { ui->autoResetCycleCheckBox->setEnabled(true); ui->autoResetCycleCheckBox->setChecked(true); checkCycleResetWidgetStatus(true); } if (button->getCycleResetTime() != 0) populateAutoResetInterval(); updateWindowTitleButtonName(); if (m_button->isPartRealAxis() && m_button->isUsingTurbo()) { ui->turboModeComboBox->setEnabled(true); } else if (!m_button->isPartRealAxis()) { ui->turboModeComboBox->setVisible(false); ui->turboModeLabel->setVisible(false); } findTurboModeComboIndex(); // Don't show Set Selector page for modifier buttons if (m_button->isModifierButton()) delete ui->listWidget->item(3); changeSlotHelpText(ui->slotTypeComboBox->currentIndex()); PadderCommon::inputDaemonMutex.unlock(); ui->resetCycleDoubleSpinBox->setMaximum(GlobalVariables::JoyButton::MAXCYCLERESETTIME * 0.001); // static_cast connect(ui->turboCheckbox, &QCheckBox::clicked, ui->turboSlider, &QSlider::setEnabled); connect(ui->turboSlider, &QSlider::valueChanged, this, &AdvanceButtonDialog::checkTurboIntervalValue); connect(ui->insertSlotButton, &QPushButton::clicked, this, &AdvanceButtonDialog::insertSlot); connect(ui->joinSlotButton, &QPushButton::clicked, this, &AdvanceButtonDialog::joinSlot); connect(ui->splitSlotButton, &QPushButton::clicked, this, &AdvanceButtonDialog::splitSlot); connect(ui->deleteSlotButton, &QPushButton::clicked, this, &AdvanceButtonDialog::deleteSlot); connect(ui->clearAllPushButton, &QPushButton::clicked, this, &AdvanceButtonDialog::clearAllSlots); connect(ui->slotTypeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::changeSlotTypeDisplay); connect(ui->slotTypeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::changeSlotHelpText); connect(ui->actionHundredthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->actionSecondsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->actionMinutesComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->actionTenthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->toggleCheckbox, &QCheckBox::clicked, button, &JoyButton::setToggle); connect(ui->turboCheckbox, &QCheckBox::clicked, this, &AdvanceButtonDialog::checkTurboSetting); connect(ui->setSelectionComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateSetSelection); connect(ui->slotListWidget, &SlotItemListWidget::itemClicked, this, &AdvanceButtonDialog::performStatsWidgetRefresh); connect(ui->actionHundredthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); connect(ui->actionTenthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); connect(ui->actionSecondsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); connect(ui->actionMinutesComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); connect(ui->slotSetChangeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotSetChangeUpdate); connect(ui->distanceSpinBox, static_cast(&QSpinBox::valueChanged), this, &AdvanceButtonDialog::checkSlotDistanceUpdate); connect(ui->mouseSpeedModSpinBox, static_cast(&QSpinBox::valueChanged), this, &AdvanceButtonDialog::checkSlotMouseModUpdate); connect(ui->autoResetCycleCheckBox, &QCheckBox::clicked, this, &AdvanceButtonDialog::checkCycleResetWidgetStatus); connect(ui->autoResetCycleCheckBox, &QCheckBox::clicked, this, &AdvanceButtonDialog::setButtonCycleReset); connect(ui->resetCycleDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &AdvanceButtonDialog::setButtonCycleResetInterval); connect(button, &JoyButton::toggleChanged, ui->toggleCheckbox, &QCheckBox::setChecked); connect(button, &JoyButton::turboChanged, this, &AdvanceButtonDialog::checkTurboSetting); connect(ui->turboModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::setButtonTurboMode); connect(ui->loadProfilePushButton, &QPushButton::clicked, this, &AdvanceButtonDialog::showSelectProfileWindow); connect(ui->execToolButton, &QToolButton::clicked, this, &AdvanceButtonDialog::showFindExecutableWindow); } // for tests AdvanceButtonDialog::AdvanceButtonDialog(QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::AdvanceButtonDialog) , helper(nullptr) { } AdvanceButtonDialog::~AdvanceButtonDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void AdvanceButtonDialog::changeTurboText(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value >= GlobalVariables::AdvanceButtonDialog::MINIMUMTURBO) { double delay = value / 100.0; double clicks = 100.0 / value; QString delaytext = QString::number(delay, 'g', 3).append(" ").append(tr("sec.")); QString labeltext = QString::number(clicks, 'g', 2).append(" ").append(tr("/sec.")); ui->delayValueLabel->setText(delaytext); ui->rateValueLabel->setText(labeltext); } } void AdvanceButtonDialog::updateSlotsScrollArea(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->currentRow(); int itemcount = ui->slotListWidget->count(); if ((index == (itemcount - 1)) && (value >= 0)) { // New slot added on the old blank button. Append // new blank button to the end of the list. appendBlankKeyGrabber(); } // Go through all grabber buttons in list and possibly resize widgets. for (int i = 0; i < ui->slotListWidget->count(); i++) { QListWidgetItem *item = ui->slotListWidget->item(i); QWidget *widget = ui->slotListWidget->itemWidget(item); item->setSizeHint(widget->sizeHint()); } // Alter interface if turbo cannot be used. changeTurboForSequences(); emit slotsChanged(); } void AdvanceButtonDialog::connectButtonEvents(SimpleKeyGrabberButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(button, &SimpleKeyGrabberButton::clicked, [this, button]() { bool leave = false; for (int i = 0; (i < ui->slotListWidget->count()) && !leave; i++) { QListWidgetItem *item = ui->slotListWidget->item(i); SimpleKeyGrabberButton *tempbutton = item->data(Qt::UserRole).value(); if (button == tempbutton) { ui->slotListWidget->setCurrentRow(i); leave = true; oldRow = i; } } }); connect(button, &SimpleKeyGrabberButton::buttonCodeChanged, [this, button](int value) { JoyButtonSlot *tempbuttonslot = button->getValue(); int index = ui->slotListWidget->currentRow(); if (tempbuttonslot->getSlotMode() == JoyButtonSlot::JoySlotInputAction::JoyMix) { QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(JoyButtonSlot *, tempbuttonslot), Q_ARG(int, index)); } else { QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, tempbuttonslot->getSlotCode()), Q_ARG(int, tempbuttonslot->getSlotCodeAlias()), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, tempbuttonslot->getSlotMode())); updateSlotsScrollArea(value); } }); } void AdvanceButtonDialog::deleteSlot(bool showWarning) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ui->slotListWidget->selectedItems().count() == 0) { if (showWarning) QMessageBox::warning(this, tr("Not checked slots"), tr("To delete slots, you need to select at least one")); } else { for (auto item : ui->slotListWidget->selectedItems()) { int index = ui->slotListWidget->row(item); int itemcount = ui->slotListWidget->count(); delete ui->slotListWidget->takeItem(index); // Deleted last button. Replace with new blank button if (index == (itemcount - 1)) appendBlankKeyGrabber(); changeTurboForSequences(); #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) QTimer::singleShot(0, &helper, [this, index]() { (&helper)->removeAssignedSlot(index); }); #else QMetaObject::invokeMethod(&helper, "removeAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, index)); #endif index = qMax(0, index - 1); performStatsWidgetRefresh(ui->slotListWidget->item(index)); emit slotsChanged(); } } } void AdvanceButtonDialog::appendBlankKeyGrabber() { qInstallMessageHandler(MessageHandler::myMessageOutput); SimpleKeyGrabberButton *blankButton = new SimpleKeyGrabberButton(this); QListWidgetItem *item = new QListWidgetItem(ui->slotListWidget); item->setData(Qt::UserRole, QVariant::fromValue(blankButton)); QHBoxLayout *layout = new QHBoxLayout(); layout->setContentsMargins(10, 0, 10, 0); layout->addWidget(blankButton); QWidget *widget = new QWidget(); widget->setLayout(layout); item->setSizeHint(widget->sizeHint()); ui->slotListWidget->setItemWidget(item, widget); ui->slotListWidget->setCurrentItem(item); connectButtonEvents(blankButton); ui->slotTypeComboBox->setCurrentIndex(static_cast(KBMouseSlot)); } void AdvanceButtonDialog::insertSlot() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ui->slotListWidget->selectedItems().count() == 0) { QMessageBox::warning(this, tr("Not checked slots"), tr("To insert slots, you need to select at least one")); } else { QStringList firstChoiceExec = QStringList(); QString firstChoiceProfile = QString(); for (auto item : ui->slotListWidget->selectedItems()) { int current = ui->slotListWidget->row(item); int count = ui->slotListWidget->count(); int slotTypeIndex = ui->slotTypeComboBox->currentIndex(); switch (slotTypeIndex) { case 0: if (current != (count - 1)) { SimpleKeyGrabberButton *blankButton = new SimpleKeyGrabberButton(this); QListWidgetItem *itemListWidget = new QListWidgetItem(); ui->slotListWidget->insertItem(current, itemListWidget); itemListWidget->setData(Qt::UserRole, QVariant::fromValue(blankButton)); QHBoxLayout *layout = new QHBoxLayout(); layout->addWidget(blankButton); QWidget *widget = new QWidget(); widget->setLayout(layout); itemListWidget->setSizeHint(widget->sizeHint()); ui->slotListWidget->setItemWidget(itemListWidget, widget); ui->slotListWidget->setCurrentItem(itemListWidget); connectButtonEvents(blankButton); blankButton->refreshButtonLabel(); QMetaObject::invokeMethod(&helper, "insertAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, 0), Q_ARG(uint, 0), Q_ARG(int, current)); updateSlotsScrollArea(0); } break; case 1: insertCycleSlot(item); break; case 2: insertKindOfSlot(item, actionTimeConvert(), JoyButtonSlot::JoyDelay); break; case 3: insertKindOfSlot(item, ui->distanceSpinBox->value(), JoyButtonSlot::JoyDistance); break; case 4: insertExecuteSlot(item, firstChoiceExec); break; case 5: insertKindOfSlot(item, actionTimeConvert(), JoyButtonSlot::JoyHold); break; case 6: showSelectProfileWind(item, firstChoiceProfile); break; case 7: insertKindOfSlot(item, ui->mouseSpeedModSpinBox->value(), JoyButtonSlot::JoyMouseSpeedMod); break; case 8: insertKindOfSlot(item, actionTimeConvert(), JoyButtonSlot::JoyPause); break; case 9: insertKindOfSlot(item, actionTimeConvert(), JoyButtonSlot::JoyKeyPress); break; case 10: insertKindOfSlot(item, actionTimeConvert(), JoyButtonSlot::JoyRelease); break; case 11: insertKindOfSlot(item, ui->slotSetChangeComboBox->itemData(ui->slotSetChangeComboBox->currentIndex()).toInt(), JoyButtonSlot::JoySetChange); break; case 12: insertTextEntrySlot(item); break; } } } } void AdvanceButtonDialog::joinSlot() { QReadLocker tempAssignLocker(&joinLock); joinLock.lockForRead(); if (ui->slotListWidget->currentRow() == -1) { QMessageBox::warning(this, tr("Unknown current slot"), tr("Click on chosen slots before joining them")); } else if (ui->slotListWidget->count() < 3) { QMessageBox::warning(this, tr("Not enough slots"), tr("It's impossible to join slots. Add at least one other slot.")); } else if (ui->slotListWidget->selectedItems().count() < 2) { QMessageBox::warning(this, tr("Not selected slots"), tr("It's impossible to join slots. Select at least two slots before joining them")); } else if (anySelectedNotKeybSlot()) { QMessageBox::warning(this, tr("Only keyboard slots"), tr("It's only possible to join simple and mix keyboard slots")); } else { qDebug() << "Chosen " << ui->slotListWidget->selectedItems().count() << " slots" << endl; QListWidgetItem *firstSelected = ui->slotListWidget->selectedItems().at(0); QString text = ""; int index = ui->slotListWidget->row(firstSelected); bool firstTime = true; SimpleKeyGrabberButton *blankButton = new SimpleKeyGrabberButton(this); QList listItems = ui->slotListWidget->selectedItems(); for (auto item : listItems) { if (!firstTime) text += "+"; firstTime = false; SimpleKeyGrabberButton *firstGrabBtn = item->data(Qt::UserRole).value(); if (firstGrabBtn->getValue()->getMixSlots()->count() > 0) { QList slotsList; for (auto mini : *firstGrabBtn->getValue()->getMixSlots()) slotsList.append(new JoyButtonSlot(mini->getSlotCode(), mini->getSlotCodeAlias(), mini->getSlotMode())); // Q_ASSERT(blankButton->getValue() != nullptr); blankButton->getValue()->appendMiniSlot>(slotsList); } else { JoyButtonSlot *slotmini = new JoyButtonSlot(firstGrabBtn->getValue()->getSlotCode(), firstGrabBtn->getValue()->getSlotCodeAlias(), firstGrabBtn->getValue()->getSlotMode()); // Q_ASSERT(blankButton->getValue() != nullptr); blankButton->getValue()->appendMiniSlot(slotmini); } text += firstGrabBtn->getValue()->getSlotString(); } blankButton->getValue()->setTextData(text); blankButton->getValue()->setSlotMode(JoyButtonSlot::JoyMix); blankButton->getValue()->setSlotCode(-1); deleteSlot(false); // Q_ASSERT(blankButton->getValue()->getMixSlots() != nullptr); // Q_ASSERT(blankButton->getValue()->getMixSlots()->count() > 0); for (auto x : *blankButton->getValue()->getMixSlots()) { // Q_ASSERT(x->getSlotMode() == 0); // Q_ASSERT(!x->getSlotString().isEmpty()); qDebug() << "JOINED MINI: " << x->getSlotCode() << " - " << x->getSlotMode() << " - " << x->getSlotString(); } QListWidgetItem *joinedItem = new QListWidgetItem(); ui->slotListWidget->insertItem(qMax(0, index), joinedItem); joinedItem->setData(Qt::UserRole, QVariant::fromValue(blankButton)); QHBoxLayout *layout = new QHBoxLayout(); layout->addWidget(blankButton); QWidget *widget = new QWidget(); widget->setLayout(layout); joinedItem->setSizeHint(widget->sizeHint()); ui->slotListWidget->setItemWidget(joinedItem, widget); ui->slotListWidget->setCurrentItem(joinedItem); // blankButton->setValues(text, blankButton->getValue()->getMixSlots(), JoyButtonSlot::JoyMix); connectButtonEvents(blankButton); blankButton->refreshButtonLabel(); // instead of blankButton->setText(text); QMetaObject::invokeMethod(&helper, "insertAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(JoyButtonSlot *, blankButton->getValue()), Q_ARG(int, index), Q_ARG(bool, false)); } joinLock.unlock(); } void AdvanceButtonDialog::splitSlot() { int index = ui->slotListWidget->currentRow(); if (index == -1) { QMessageBox::warning(this, tr("Unknown current slot"), tr("Click on chosen slots before joining them")); } else if (ui->slotListWidget->count() < 2) { QMessageBox::warning(this, tr("Not enough slots"), tr("It's impossible to split slots. Add at least one other slot.")); } else if (ui->slotListWidget->selectedItems().count() < 1) { QMessageBox::warning(this, tr("Not selected slot"), tr("Select your slot before splitting.")); } else if (ui->slotListWidget->selectedItems().count() > 1) { QMessageBox::warning(this, tr("Too many mix slots"), tr("Select one mix slot.")); } else if (selectedNotMixSlot()) { QMessageBox::warning(this, tr("Only mix slots"), tr("It's only possible to split mix slot.")); } else { QReadLocker tempAssignLocker(&joinLock); joinLock.lockForRead(); QListWidgetItem *mixSlot = ui->slotListWidget->selectedItems().at(0); int indexMixSlot = ui->slotListWidget->row(mixSlot); int indexKeyboardSlot = indexMixSlot; QList minislots = *mixSlot->data(Qt::UserRole).value()->getValue()->getMixSlots(); for (auto minislot : minislots) { qDebug() << "MINISLOT SPLITTED NAME: " << minislot->getSlotString(); QListWidgetItem *splittedItem = new QListWidgetItem(); SimpleKeyGrabberButton *blankButton = new SimpleKeyGrabberButton(this); JoyButtonSlot *slotmini = new JoyButtonSlot(minislot->getSlotCode(), minislot->getSlotCodeAlias(), minislot->getSlotMode()); ui->slotListWidget->insertItem(qMax(0, indexKeyboardSlot), splittedItem); blankButton->setValue(slotmini); delete slotmini; slotmini = nullptr; splittedItem->setData(Qt::UserRole, QVariant::fromValue(blankButton)); QHBoxLayout *layout = new QHBoxLayout(); layout->addWidget(blankButton); QWidget *widget = new QWidget(); widget->setLayout(layout); splittedItem->setSizeHint(widget->sizeHint()); ui->slotListWidget->setItemWidget(splittedItem, widget); // ui->slotListWidget->setCurrentItem(splittedItem); connectButtonEvents(blankButton); blankButton->refreshButtonLabel(); // instead of blankButton->setText(text); QMetaObject::invokeMethod(&helper, "insertAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, blankButton->getValue()->getSlotCode()), Q_ARG(int, blankButton->getValue()->getSlotCodeAlias()), Q_ARG(int, indexKeyboardSlot), Q_ARG(JoyButtonSlot::JoySlotInputAction, blankButton->getValue()->getSlotMode())); indexKeyboardSlot++; } // it can be used as reusable code deleteSlot(false); joinLock.unlock(); } } void AdvanceButtonDialog::insertKindOfSlot(QListWidgetItem *item, int slotProperty, JoyButtonSlot::JoySlotInputAction inputAction) { int index = ui->slotListWidget->row(item); int actionTime = slotProperty; SimpleKeyGrabberButton *tempbutton = item->data(Qt::UserRole).value(); int tempDistance = 0; bool slotPropertyAboveLimit = actionTime >= 0; if (inputAction == JoyButtonSlot::JoyDistance) { for (int i = 0; i < ui->slotListWidget->count(); i++) { SimpleKeyGrabberButton *button = ui->slotListWidget->item(i)->data(Qt::UserRole).value(); JoyButtonSlot *tempbuttonslot = button->getValue(); if (tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyDistance) { tempDistance += tempbuttonslot->getSlotCode(); } else if (tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyCycle) { tempDistance = 0; } } tempDistance += actionTime; slotPropertyAboveLimit = tempDistance <= 100; } if (slotPropertyAboveLimit) { tempbutton->setValue(actionTime, inputAction); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, actionTime), Q_ARG(int, 0), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, inputAction)); updateSlotsScrollArea(actionTime); } } int AdvanceButtonDialog::actionTimeConvert() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempMilliSeconds = ui->actionMinutesComboBox->currentIndex() * 1000 * 60; tempMilliSeconds += ui->actionSecondsComboBox->currentIndex() * 1000; tempMilliSeconds += ui->actionTenthsComboBox->currentIndex() * 100; tempMilliSeconds += ui->actionHundredthsComboBox->currentIndex() * 10; return tempMilliSeconds; } void AdvanceButtonDialog::refreshTimeComboBoxes(JoyButtonSlot *slot) { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnectTimeBoxesEvents(); int slottime = slot->getSlotCode(); ui->actionMinutesComboBox->setCurrentIndex(slottime / 1000 / 60); ui->actionSecondsComboBox->setCurrentIndex(slottime / 1000 % 60); ui->actionTenthsComboBox->setCurrentIndex((slottime % 1000) / 100); ui->actionHundredthsComboBox->setCurrentIndex((slottime % 1000 % 100) / 10); updateActionTimeLabel(); connectTimeBoxesEvents(); } void AdvanceButtonDialog::updateActionTimeLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); int actionTime = actionTimeConvert(); int minutes = actionTime / 1000 / 60; double hundredths = actionTime % 1000 / 1000.0; double seconds = (actionTime / 1000 % 60) + hundredths; QString actionTimeLabel = QString(); actionTimeLabel.append(QString::number(minutes)).append("m "); actionTimeLabel.append(QString::number(seconds, 'f', 2)).append("s"); ui->actionTimeLabel->setText(actionTimeLabel); } void AdvanceButtonDialog::clearAllSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->slotListWidget->clear(); appendBlankKeyGrabber(); changeTurboForSequences(); QMetaObject::invokeMethod(m_button, "clearSlotsEventReset", Qt::BlockingQueuedConnection); performStatsWidgetRefresh(ui->slotListWidget->currentItem()); emit slotsChanged(); } void AdvanceButtonDialog::changeTurboForSequences() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool containsSequences = false; for (int i = 0; (i < ui->slotListWidget->count()) && !containsSequences; i++) { SimpleKeyGrabberButton *button = ui->slotListWidget->item(i)->data(Qt::UserRole).value(); JoyButtonSlot *tempbuttonslot = button->getValue(); if ((tempbuttonslot->getSlotCode() > 0) && ((tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyPause) || (tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyHold) || (tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyDistance))) { containsSequences = true; } } if (containsSequences) { if (ui->turboCheckbox->isChecked()) { ui->turboCheckbox->setChecked(false); m_button->setUseTurbo(false); emit turboChanged(false); } if (ui->turboCheckbox->isEnabled()) { ui->turboCheckbox->setEnabled(false); emit turboButtonEnabledChange(false); } } else if (!ui->turboCheckbox->isEnabled()) { ui->turboCheckbox->setEnabled(true); emit turboButtonEnabledChange(true); } } void AdvanceButtonDialog::insertCycleSlot(QListWidgetItem *item) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->row(item); SimpleKeyGrabberButton *tempbutton = item->data(Qt::UserRole).value(); tempbutton->setValue(1, JoyButtonSlot::JoyCycle); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, 1), Q_ARG(int, 0), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, JoyButtonSlot::JoyCycle)); updateSlotsScrollArea(1); } void AdvanceButtonDialog::placeNewSlot(JoyButtonSlot *slot) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->currentRow(); SimpleKeyGrabberButton *tempbutton = ui->slotListWidget->currentItem()->data(Qt::UserRole).value(); tempbutton->setValue(slot->getSlotCode(), slot->getSlotCodeAlias(), slot->getSlotMode()); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, slot->getSlotCode()), Q_ARG(int, slot->getSlotCodeAlias()), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, slot->getSlotMode())); updateSlotsScrollArea(slot->getSlotCode()); slot->deleteLater(); } void AdvanceButtonDialog::updateTurboIntervalValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value >= GlobalVariables::AdvanceButtonDialog::MINIMUMTURBO) { m_button->setTurboInterval(value * 10); } } void AdvanceButtonDialog::checkTurboSetting(bool state) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->turboCheckbox->setChecked(state); ui->turboSlider->setEnabled(state); if (m_button->isPartRealAxis()) ui->turboModeComboBox->setEnabled(state); changeTurboForSequences(); m_button->setUseTurbo(state); if ((m_button->getTurboInterval() / 10) >= GlobalVariables::AdvanceButtonDialog::MINIMUMTURBO) { ui->turboSlider->setValue(m_button->getTurboInterval() / 10); } } void AdvanceButtonDialog::updateSetSelection() { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); int chosen_set = -1; JoyButton::SetChangeCondition set_selection_condition = JoyButton::SetChangeDisabled; if (ui->setSelectionComboBox->currentIndex() > 0) { int condition_choice = (ui->setSelectionComboBox->currentIndex() + 2) % 3; chosen_set = (ui->setSelectionComboBox->currentIndex() - 1) / 3; if (m_button->getOriginSet() > chosen_set) // Above removed rows { chosen_set = (ui->setSelectionComboBox->currentIndex() - 1) / 3; } else // Below removed rows { chosen_set = (ui->setSelectionComboBox->currentIndex() + 2) / 3; } qDebug() << "CONDITION: " << QString::number(condition_choice) << endl; switch (condition_choice) { case 0: set_selection_condition = JoyButton::SetChangeOneWay; break; case 1: set_selection_condition = JoyButton::SetChangeTwoWay; break; case 2: set_selection_condition = JoyButton::SetChangeWhileHeld; break; } qDebug() << "CHOSEN SET: " << chosen_set << endl; } else { chosen_set = -1; set_selection_condition = JoyButton::SetChangeDisabled; } if ((chosen_set > -1) && (set_selection_condition != JoyButton::SetChangeDisabled)) { // First, remove old condition for the button in both sets. // After that, make the new assignment. m_button->setChangeSetCondition(JoyButton::SetChangeDisabled); m_button->setChangeSetSelection(chosen_set); m_button->setChangeSetCondition(set_selection_condition); } else { m_button->setChangeSetCondition(JoyButton::SetChangeDisabled); } PadderCommon::inputDaemonMutex.unlock(); } void AdvanceButtonDialog::checkTurboIntervalValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value >= GlobalVariables::AdvanceButtonDialog::MINIMUMTURBO) { changeTurboText(value); updateTurboIntervalValue(value); } else { ui->turboSlider->setValue(GlobalVariables::AdvanceButtonDialog::MINIMUMTURBO); } } void AdvanceButtonDialog::fillTimeComboBoxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->actionMinutesComboBox->clear(); ui->actionSecondsComboBox->clear(); ui->actionHundredthsComboBox->clear(); ui->actionTenthsComboBox->clear(); for (int i = 0; i <= 10; i++) { QString minText = QString::number(i, 'g', 2).append("m"); ui->actionMinutesComboBox->addItem(minText); } for (int i = 0; i <= 59; i++) { QString secsText = QString::number(i, 'g', 2); ui->actionSecondsComboBox->addItem(secsText); } for (int i = 0; i < 10; i++) { QString tenthsText = QString(".%1").arg(i, 1, 10, QChar('0')); ui->actionTenthsComboBox->addItem(tenthsText); } for (int i = 0; i < 10; i++) { QString hundrText = QString("%1s").arg(i, 1, 10, QChar('0')); ui->actionHundredthsComboBox->addItem(hundrText); } } void AdvanceButtonDialog::insertTextEntrySlot(QListWidgetItem *item) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->row(item); QString entryText = ui->textEntryLineEdit->text(); SimpleKeyGrabberButton *textEntryButton = item->data(Qt::UserRole).value(); if (!entryText.isEmpty()) { textEntryButton->setValue(entryText, JoyButtonSlot::JoyTextEntry); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(JoyButtonSlot *, textEntryButton->getValue()), Q_ARG(int, index)); textEntryButton->setToolTip(entryText); updateSlotsScrollArea(0); } } void AdvanceButtonDialog::insertExecuteSlot(QListWidgetItem *item, QStringList &prevExecAndArgs) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->row(item); QString execSlotName, argsExecSlot; QFile execFile; QFileInfo execSlotNameInfo; if (prevExecAndArgs.empty()) // the first time when we choose script { execSlotName = ui->execLineEdit->text(); argsExecSlot = ui->execArgumentsLineEdit->text(); } else // when we want to apply changes to many slots at once { execSlotName = prevExecAndArgs.first(); if (prevExecAndArgs.length() == 2) argsExecSlot = prevExecAndArgs.last(); } execFile.setFileName(execSlotName); execSlotNameInfo.setFile(execSlotName); SimpleKeyGrabberButton *execbutton = item->data(Qt::UserRole).value(); if (execSlotName.isEmpty()) QMessageBox::warning( this, tr("Empty execution path"), tr("Line for execution file path is empty. Fill the first line before you are going to add a slot.")); else if (!execSlotNameInfo.exists()) QMessageBox::warning(this, tr("File doesn't exist"), tr("There is no such file locally, that could be executed. Check the file on your system")); else { prevExecAndArgs.clear(); execbutton->setValue(execSlotName, JoyButtonSlot::JoyExecute); prevExecAndArgs << execSlotName; if (!argsExecSlot.isEmpty()) { execbutton->getValue()->setExtraData(QVariant(argsExecSlot)); prevExecAndArgs << argsExecSlot; } QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(JoyButtonSlot *, execbutton->getValue()), Q_ARG(int, index)); execbutton->setToolTip(execSlotName); updateSlotsScrollArea(0); } } void AdvanceButtonDialog::performStatsWidgetRefresh(QListWidgetItem *item) { qInstallMessageHandler(MessageHandler::myMessageOutput); SimpleKeyGrabberButton *button = item->data(Qt::UserRole).value(); JoyButtonSlot *slot = button->getValue(); if ((slot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (slot->getSlotCode() != 0)) { ui->slotTypeComboBox->setCurrentIndex(0); } else if ((slot->getSlotMode() == JoyButtonSlot::JoyMouseButton) || (slot->getSlotMode() == JoyButtonSlot::JoyMouseMovement)) { ui->slotTypeComboBox->setCurrentIndex(0); } else if (slot->getSlotMode() == JoyButtonSlot::JoyCycle) { ui->slotTypeComboBox->setCurrentIndex(1); } else if (slot->getSlotMode() == JoyButtonSlot::JoyDelay) { ui->slotTypeComboBox->setCurrentIndex(2); refreshTimeComboBoxes(slot); } else if (slot->getSlotMode() == JoyButtonSlot::JoyDistance) { ui->slotTypeComboBox->setCurrentIndex(3); disconnect(ui->distanceSpinBox, static_cast(&QSpinBox::valueChanged), this, &AdvanceButtonDialog::checkSlotDistanceUpdate); ui->distanceSpinBox->setValue(slot->getSlotCode()); connect(ui->distanceSpinBox, static_cast(&QSpinBox::valueChanged), this, &AdvanceButtonDialog::checkSlotDistanceUpdate); } else if (slot->getSlotMode() == JoyButtonSlot::JoyHold) { ui->slotTypeComboBox->setCurrentIndex(5); refreshTimeComboBoxes(slot); } else if (slot->getSlotMode() == JoyButtonSlot::JoyLoadProfile) { ui->slotTypeComboBox->setCurrentIndex(6); } else if (slot->getSlotMode() == JoyButtonSlot::JoyMouseSpeedMod) { ui->slotTypeComboBox->setCurrentIndex(7); disconnect(ui->mouseSpeedModSpinBox, static_cast(&QSpinBox::valueChanged), this, &AdvanceButtonDialog::checkSlotMouseModUpdate); ui->mouseSpeedModSpinBox->setValue(slot->getSlotCode()); connect(ui->mouseSpeedModSpinBox, static_cast(&QSpinBox::valueChanged), this, &AdvanceButtonDialog::checkSlotMouseModUpdate); } else if (slot->getSlotMode() == JoyButtonSlot::JoyPause) { ui->slotTypeComboBox->setCurrentIndex(8); refreshTimeComboBoxes(slot); } else if (slot->getSlotMode() == JoyButtonSlot::JoyKeyPress) { ui->slotTypeComboBox->setCurrentIndex(9); refreshTimeComboBoxes(slot); } else if (slot->getSlotMode() == JoyButtonSlot::JoyRelease) { ui->slotTypeComboBox->setCurrentIndex(10); refreshTimeComboBoxes(slot); } else if (slot->getSlotMode() == JoyButtonSlot::JoySetChange) { disconnect(ui->slotSetChangeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotSetChangeUpdate); ui->slotTypeComboBox->setCurrentIndex(11); int chooseIndex = slot->getSlotCode(); int foundIndex = ui->slotSetChangeComboBox->findData(QVariant(chooseIndex)); if (foundIndex >= 0) ui->slotSetChangeComboBox->setCurrentIndex(foundIndex); connect(ui->slotSetChangeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotSetChangeUpdate); } else if (slot->getSlotMode() == JoyButtonSlot::JoyTextEntry) { ui->slotTypeComboBox->setCurrentIndex(12); ui->textEntryLineEdit->setText(slot->getTextData()); } else if (slot->getSlotMode() == JoyButtonSlot::JoyExecute) { ui->slotTypeComboBox->setCurrentIndex(4); ui->execLineEdit->setText(slot->getTextData()); ui->execArgumentsLineEdit->setText(slot->getExtraData().toString()); } } void AdvanceButtonDialog::checkSlotTimeUpdate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int actionTime = actionTimeConvert(); int index = ui->slotListWidget->currentRow(); SimpleKeyGrabberButton *button = ui->slotListWidget->currentItem()->data(Qt::UserRole).value(); JoyButtonSlot *buttonSlot = button->getValue(); if ((buttonSlot->getSlotMode() == JoyButtonSlot::JoyPause) || (buttonSlot->getSlotMode() == JoyButtonSlot::JoyHold) || (buttonSlot->getSlotMode() == JoyButtonSlot::JoyRelease) || (buttonSlot->getSlotMode() == JoyButtonSlot::JoyKeyPress) || (buttonSlot->getSlotMode() == JoyButtonSlot::JoyDelay)) { if (actionTime > 0) { button->setValue(actionTime, buttonSlot->getSlotMode()); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, actionTime), Q_ARG(int, 0), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, buttonSlot->getSlotMode())); updateSlotsScrollArea(actionTime); } } } void AdvanceButtonDialog::checkSlotMouseModUpdate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempMouseMod = ui->mouseSpeedModSpinBox->value(); int index = ui->slotListWidget->currentRow(); SimpleKeyGrabberButton *tempbutton = ui->slotListWidget->currentItem()->data(Qt::UserRole).value(); JoyButtonSlot *tempbuttonslot = tempbutton->getValue(); if ((tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyMouseSpeedMod) && (tempMouseMod > 0)) { tempbutton->setValue(tempMouseMod, tempbuttonslot->getSlotMode()); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, tempMouseMod), Q_ARG(int, 0), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, tempbuttonslot->getSlotMode())); updateSlotsScrollArea(tempMouseMod); } } void AdvanceButtonDialog::checkSlotSetChangeUpdate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->currentRow(); SimpleKeyGrabberButton *tempbutton = ui->slotListWidget->currentItem()->data(Qt::UserRole).value(); JoyButtonSlot *buttonslot = tempbutton->getValue(); if (buttonslot->getSlotMode() == JoyButtonSlot::JoySetChange && (ui->slotSetChangeComboBox->itemData(ui->slotSetChangeComboBox->currentIndex()).toInt() >= 0)) { int comboIndex = ui->slotSetChangeComboBox->currentIndex(); int setIndex = ui->slotSetChangeComboBox->itemData(comboIndex).toInt(); tempbutton->setValue(setIndex, buttonslot->getSlotMode()); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, setIndex), Q_ARG(int, 0), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, buttonslot->getSlotMode())); updateSlotsScrollArea(setIndex); } } void AdvanceButtonDialog::checkSlotDistanceUpdate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->currentRow(); SimpleKeyGrabberButton *tempbutton = ui->slotListWidget->currentItem()->data(Qt::UserRole).value(); JoyButtonSlot *buttonslot = tempbutton->getValue(); if (buttonslot->getSlotMode() == JoyButtonSlot::JoyDistance) { int tempDistance = 0; for (int i = 0; i < ui->slotListWidget->count(); i++) { SimpleKeyGrabberButton *button = ui->slotListWidget->item(i)->data(Qt::UserRole).value(); JoyButtonSlot *tempbuttonslot = button->getValue(); if (tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyDistance) { tempDistance += tempbuttonslot->getSlotCode(); } else if (tempbuttonslot->getSlotMode() == JoyButtonSlot::JoyCycle) { tempDistance = 0; } } int testDistance = ui->distanceSpinBox->value(); tempDistance += testDistance - buttonslot->getSlotCode(); if (tempDistance <= 100) { tempbutton->setValue(testDistance, buttonslot->getSlotMode()); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, testDistance), Q_ARG(int, 0), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, buttonslot->getSlotMode())); updateSlotsScrollArea(testDistance); } } } void AdvanceButtonDialog::updateWindowTitleButtonName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString windTitleBtnName = QString().append(tr("Advanced").append(": ")).append(m_button->getPartialName(false, true)); if (m_button->getParentSet()->getIndex() != 0) { int setIndex = m_button->getParentSet()->getRealIndex(); windTitleBtnName.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = m_button->getParentSet()->getName(); if (!setName.isEmpty()) windTitleBtnName.append(": ").append(setName); windTitleBtnName.append("]"); } setWindowTitle(windTitleBtnName); } void AdvanceButtonDialog::checkCycleResetWidgetStatus(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (enabled) ui->resetCycleDoubleSpinBox->setEnabled(true); else ui->resetCycleDoubleSpinBox->setEnabled(false); } void AdvanceButtonDialog::setButtonCycleResetInterval(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int milliseconds = (value * 1000) + (fmod(value, 1.0) * 1000); m_button->setCycleResetTime(milliseconds); } void AdvanceButtonDialog::populateAutoResetInterval() { qInstallMessageHandler(MessageHandler::myMessageOutput); double seconds = m_button->getCycleResetTime() / 1000.0; ui->resetCycleDoubleSpinBox->setValue(seconds); } void AdvanceButtonDialog::setButtonCycleReset(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (enabled) { m_button->setCycleResetStatus(true); if ((m_button->getCycleResetTime() == 0) && (ui->resetCycleDoubleSpinBox->value() > 0.0)) { double current = ui->resetCycleDoubleSpinBox->value(); setButtonCycleResetInterval(current); } } else { m_button->setCycleResetStatus(false); } } void AdvanceButtonDialog::resetTimeBoxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnectTimeBoxesEvents(); ui->actionMinutesComboBox->setCurrentIndex(0); ui->actionSecondsComboBox->setCurrentIndex(0); ui->actionTenthsComboBox->setCurrentIndex(1); ui->actionHundredthsComboBox->setCurrentIndex(0); updateActionTimeLabel(); connectTimeBoxesEvents(); } void AdvanceButtonDialog::disconnectTimeBoxesEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(ui->actionSecondsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); disconnect(ui->actionHundredthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); disconnect(ui->actionMinutesComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); disconnect(ui->actionTenthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); disconnect(ui->actionHundredthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); disconnect(ui->actionSecondsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); disconnect(ui->actionMinutesComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); disconnect(ui->actionTenthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); } void AdvanceButtonDialog::connectTimeBoxesEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(ui->actionSecondsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->actionHundredthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->actionMinutesComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->actionTenthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::updateActionTimeLabel); connect(ui->actionHundredthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); connect(ui->actionSecondsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); connect(ui->actionMinutesComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); connect(ui->actionTenthsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceButtonDialog::checkSlotTimeUpdate); } void AdvanceButtonDialog::populateSetSelectionComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->setSelectionComboBox->clear(); ui->setSelectionComboBox->insertItem(0, tr("Disabled")); int currentIndex = 1; QHash::iterator set; int originset = 0; for (set = m_button->getParentSet()->getInputDevice()->getJoystick_sets().begin(); set != m_button->getParentSet()->getInputDevice()->getJoystick_sets().end(); ++set) { if (m_button->getOriginSet() != originset) { QString selectedSetText = QString(tr("Select Set %1").arg(originset + 1)); QString setName = set.value()->getName(); if (!setName.isEmpty()) { selectedSetText.append(" ").append("["); selectedSetText.append(setName).append("]").append(" "); } QString oneWayText = QString(selectedSetText).append(" ").append(tr("One Way")); QString twoWayText = QString(selectedSetText).append(" ").append(tr("Two Way")); QString whileHeldText = QString(selectedSetText).append(" ").append(tr("While Held")); QStringList setChoices = QStringList(); setChoices.append(oneWayText); setChoices.append(twoWayText); setChoices.append(whileHeldText); ui->setSelectionComboBox->insertItems(currentIndex, setChoices); currentIndex += 3; } originset++; } } void AdvanceButtonDialog::populateSlotSetSelectionComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->slotSetChangeComboBox->clear(); int currentIndex = 0; QHash::iterator set; int originset = 0; for (set = m_button->getParentSet()->getInputDevice()->getJoystick_sets().begin(); set != m_button->getParentSet()->getInputDevice()->getJoystick_sets().end(); ++set) { if (m_button->getOriginSet() != originset) { QString selectedSetSlotText = QString(tr("Select Set %1").arg(originset + 1)); QString setName = set.value()->getName(); if (!setName.isEmpty()) { selectedSetSlotText.append(" ").append("["); selectedSetSlotText.append(setName).append("]").append(" "); } ui->slotSetChangeComboBox->insertItem(currentIndex, selectedSetSlotText, QVariant(originset)); currentIndex++; } originset++; } } void AdvanceButtonDialog::findTurboModeComboIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::TurboMode currentTurboMode = m_button->getTurboMode(); switch (static_cast(currentTurboMode)) { case 0: ui->turboModeComboBox->setCurrentIndex(0); break; case 1: ui->turboModeComboBox->setCurrentIndex(1); break; case 2: ui->turboModeComboBox->setCurrentIndex(2); break; } } void AdvanceButtonDialog::setButtonTurboMode(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (value) { case 0: m_button->setTurboMode(JoyButton::NormalTurbo); break; case 1: m_button->setTurboMode(JoyButton::GradientTurbo); break; case 2: m_button->setTurboMode(JoyButton::PulseTurbo); break; } } void AdvanceButtonDialog::showSelectProfileWindow() { qInstallMessageHandler(MessageHandler::myMessageOutput); // It can be used as reusable code insertSlot(); } void AdvanceButtonDialog::showSelectProfileWind(QListWidgetItem *item, QString &firstChoiceProfile) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->slotListWidget->row(item); AntiMicroSettings *settings = m_button->getParentSet()->getInputDevice()->getSettings(); QString preferredDir, profileName; if (firstChoiceProfile.size() <= 0) { preferredDir = PadderCommon::preferredProfileDir(settings); profileName = QFileDialog::getOpenFileName(this, tr("Choose Profile"), preferredDir, tr("Config Files (*.amgp *.xml)")); } else { profileName = firstChoiceProfile; } if (!profileName.isEmpty()) { firstChoiceProfile = profileName; SimpleKeyGrabberButton *button = item->data(Qt::UserRole).value(); button->setValue(profileName, JoyButtonSlot::JoyLoadProfile); QMetaObject::invokeMethod(&helper, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(JoyButtonSlot *, button->getValue()), Q_ARG(int, index)); button->setToolTip(profileName); updateSlotsScrollArea(0); } } bool AdvanceButtonDialog::anySelectedNotKeybSlot() { for (auto item : ui->slotListWidget->selectedItems()) { auto slotMode = item->data(Qt::UserRole).value()->getValue()->getSlotMode(); if ((slotMode != JoyButtonSlot::JoySlotInputAction::JoyMix) && (slotMode != JoyButtonSlot::JoySlotInputAction::JoyKeyboard)) { return true; } } return false; } bool AdvanceButtonDialog::selectedNotMixSlot() { for (auto item : ui->slotListWidget->selectedItems()) { auto slotMode = item->data(Qt::UserRole).value()->getValue()->getSlotMode(); if (slotMode != JoyButtonSlot::JoySlotInputAction::JoyMix) { return true; } } return false; } void AdvanceButtonDialog::showFindExecutableWindow(bool) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString preferredPath = QDir::homePath(); QString execWindFilepath = QFileDialog::getOpenFileName(this, tr("Choose Executable"), preferredPath); ui->execLineEdit->setText(execWindFilepath); } void AdvanceButtonDialog::changeSlotTypeDisplay(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (index) { case 0: case 2: case 5: case 8: case 9: case 10: ui->slotControlsStackedWidget->setCurrentIndex(0); break; case 1: ui->slotControlsStackedWidget->setCurrentIndex(3); break; case 3: ui->slotControlsStackedWidget->setCurrentIndex(2); break; case 4: ui->slotControlsStackedWidget->setCurrentIndex(7); break; case 6: ui->slotControlsStackedWidget->setCurrentIndex(4); break; case 7: ui->slotControlsStackedWidget->setCurrentIndex(1); break; case 11: ui->slotControlsStackedWidget->setCurrentIndex(5); break; case 12: ui->slotControlsStackedWidget->setCurrentIndex(6); break; } } void AdvanceButtonDialog::changeSlotHelpText(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (index) { case 0: ui->slotTypeHelpLabel->setText(tr("Insert a new blank slot.")); break; case 1: ui->slotTypeHelpLabel->setText(tr("Slots past a Cycle action will be executed " "on the next button press. Multiple cycles can be added " "in order to create partitions in a sequence.")); break; case 2: ui->slotTypeHelpLabel->setText(tr("Delays the time that the next slot is activated " "by the time specified. Slots activated before the " "delay will remain active after the delay time " "has passed.")); break; case 3: ui->slotTypeHelpLabel->setText(tr("Distance action specifies that the slots afterwards " "will only be executed when an axis is moved " "a certain range past the designated dead zone.")); break; case 4: ui->slotTypeHelpLabel->setText(tr("Execute program when slot is activated.")); break; case 5: ui->slotTypeHelpLabel->setText(tr("Insert a hold action. Slots after the action will only be " "executed if the button is held past the interval specified.")); break; case 6: ui->slotTypeHelpLabel->setText(tr("Chose a profile to load when this slot is activated.")); break; case 7: ui->slotTypeHelpLabel->setText(tr("Mouse mod action will modify all mouse speed settings " "by a specified percentage while the action is being processed. " "This can be useful for slowing down the mouse while " "sniping.")); break; case 8: ui->slotTypeHelpLabel->setText(tr("Insert a pause that occurs in between key presses.")); break; case 9: ui->slotTypeHelpLabel->setText(tr("Specify the time that keys past this slot should be " "held down.")); break; case 10: ui->slotTypeHelpLabel->setText(tr("Insert a release action. Slots after the action will only be " "executed after a button release if the button was held " "past the interval specified.")); break; case 11: ui->slotTypeHelpLabel->setText(tr("Change to selected set once slot is activated.")); break; case 12: ui->slotTypeHelpLabel->setText(tr("Full string will be typed when a " "slot is activated.")); break; } } int AdvanceButtonDialog::getOldRow() const { return oldRow; } JoyButton *AdvanceButtonDialog::getButton() const { return m_button; } AdvanceButtonDialogHelper const &AdvanceButtonDialog::getHelper() { return helper; } AdvanceButtonDialogHelper &AdvanceButtonDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/advancebuttondialog.h000066400000000000000000000125451377703515000232470ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ADVANCEBUTTONDIALOG_H #define ADVANCEBUTTONDIALOG_H #include "uihelpers/advancebuttondialoghelper.h" #include #include class JoyButton; class SimpleKeyGrabberButton; class QListWidgetItem; namespace Ui { class AdvanceButtonDialog; } class AdvanceButtonDialog : public QDialog { Q_OBJECT public: explicit AdvanceButtonDialog(JoyButton *button, QWidget *parent = 0); AdvanceButtonDialog(QWidget *parent = 0); ~AdvanceButtonDialog(); int getOldRow() const; JoyButton *getButton() const; AdvanceButtonDialogHelper const &getHelper(); protected: void connectButtonEvents(SimpleKeyGrabberButton *button); // AdvanceBtnDlgAssign class void appendBlankKeyGrabber(); // AdvanceBtnDlgAssign class int actionTimeConvert(); // AdvanceBtnDlgAssign class void changeTurboForSequences(); void fillTimeComboBoxes(); // AdvanceBtnDlgAssign class void refreshTimeComboBoxes(JoyButtonSlot *slot); // AdvanceBtnDlgAssign class void updateWindowTitleButtonName(); // AdvanceBtnDlgAssign class void populateAutoResetInterval(); // AdvanceBtnDlgAssign class void disconnectTimeBoxesEvents(); // AdvanceBtnDlgAssign class void connectTimeBoxesEvents(); // AdvanceBtnDlgAssign class void resetTimeBoxes(); // AdvanceBtnDlgAssign class void populateSetSelectionComboBox(); void populateSlotSetSelectionComboBox(); void findTurboModeComboIndex(); void showSelectProfileWind(QListWidgetItem *item, QString &firstChoiceProfile); bool anySelectedNotKeybSlot(); bool selectedNotMixSlot(); signals: void toggleChanged(bool state); void turboChanged(bool state); void slotsChanged(); // AdvanceBtnDlgAssign class void turboButtonEnabledChange(bool state); public slots: void placeNewSlot(JoyButtonSlot *slot); // AdvanceBtnDlgAssign class void clearAllSlots(); // AdvanceBtnDlgAssign class private slots: void changeTurboText(int value); void updateTurboIntervalValue(int value); void checkTurboSetting(bool state); void updateSlotsScrollArea(int value); // AdvanceBtnDlgAssign class void deleteSlot(bool showWarning = true); // AdvanceBtnDlgAssign class void insertSlot(); // AdvanceBtnDlgAssign class void joinSlot(); // AdvanceBtnDlgAssign class void splitSlot(); // AdvanceBtnDlgAssign class void insertCycleSlot(QListWidgetItem *item); // AdvanceBtnDlgAssign class void insertTextEntrySlot(QListWidgetItem *item); // AdvanceBtnDlgAssign class void insertExecuteSlot(QListWidgetItem *item, QStringList &prevExecAndArgs); // AdvanceBtnDlgAssign class void updateActionTimeLabel(); void updateSetSelection(); void checkTurboIntervalValue(int value); void performStatsWidgetRefresh(QListWidgetItem *item); void checkSlotTimeUpdate(); // AdvanceBtnDlgAssign class void checkSlotMouseModUpdate(); // AdvanceBtnDlgAssign class void checkSlotDistanceUpdate(); // AdvanceBtnDlgAssign class void checkSlotSetChangeUpdate(); // AdvanceBtnDlgAssign class void checkCycleResetWidgetStatus(bool enabled); // AdvanceBtnDlgAssign class void setButtonCycleResetInterval(double value); // AdvanceBtnDlgAssign class void setButtonCycleReset(bool enabled); // AdvanceBtnDlgAssign class void setButtonTurboMode(int value); void showSelectProfileWindow(); void showFindExecutableWindow(bool); // AdvanceBtnDlgAssign class void changeSlotTypeDisplay(int index); // AdvanceBtnDlgAssign class void changeSlotHelpText(int index); // AdvanceBtnDlgAssign class private: Ui::AdvanceButtonDialog *ui; AdvanceButtonDialogHelper &getHelperLocal(); enum SlotTypeComboIndex { KBMouseSlot = 0, CycleSlot, DelaySlot, DistanceSlot, ExecuteSlot, HoldSlot, LoadSlot, MouseModSlot, PauseSlot, PressTimeSlot, ReleaseSlot, SetChangeSlot, TextEntry }; int oldRow; JoyButton *m_button; AdvanceButtonDialogHelper helper; QReadWriteLock joinLock; void insertKindOfSlot(QListWidgetItem *item, int slotProperty, JoyButtonSlot::JoySlotInputAction inputAction); // AdvanceBtnDlgAssign class }; #endif // ADVANCEBUTTONDIALOG_H AntiMicroX-antimicrox-2888bf6/src/advancebuttondialog.ui000066400000000000000000001251741377703515000234400ustar00rootroot00000000000000 AdvanceButtonDialog Qt::NonModal 0 0 750 480 0 0 750 480 Advanced false 6 4 0 true 0 0 200 16777215 0 Assignments Toggle Turbo Set Selector 0 0 0 0 0 0 100 16777215 100 false QFrame::StyledPanel QFrame::Sunken 1 0 Qt::ScrollBarAlwaysOff QAbstractItemView::ExtendedSelection QListView::LeftToRight 0 QListView::ListMode false Qt::Vertical QSizePolicy::Fixed 20 10 0 Qt::Horizontal QSizePolicy::Fixed 50 20 Blank or KB/M Cycle Delay Distance Execute Hold Load Mouse Mod Pause Press Time Release Set Change Text Entry Qt::Horizontal QSizePolicy::Fixed 50 20 4 0 20 Insert a new blank slot. Insert .. 0 20 Delete a slot. Delete 0 20 Join :/icons/actions/join_slots.png:/icons/actions/join_slots.png 0 20 Split :/icons/actions/split_slot.png:/icons/actions/split_slot.png 0 20 Clear all currently assigned slots. Clear All .. Qt::Vertical QSizePolicy::Fixed 20 2 Placeholder true 0 Qt::Vertical QSizePolicy::Fixed 20 20 40 0 0 75 true Specify the duration of an inserted Pause or Hold slot. Time: 50 false 0.01s 10 0m 0 0 0 0 11 0 0 0 0 0 0 0 0s 75 true &Mouse Speed Mod: mouseSpeedModSpinBox 81 0 Set the percentage that mouse speeds will be modified by. % 1 400 1 100 20 75 true Specify the range past an axis dead zone in which a sequence of actions will execute. Distance: distanceSpinBox 81 0 Specify the range past an axis dead zone in which a sequence of actions will execute. % 1 100 1 10 true 75 true Auto Reset Cycle After false 60.000000000000000 0.500000000000000 1.000000000000000 true 75 true seconds Choose Profile Executable: ... Arguments: Qt::Vertical QSizePolicy::Expanding 20 10 20 Enabled Qt::Vertical 20 302 0 0 Enabled 0 0 Mode: false <html><head/><body><p>Normal: Repeatedly press and release a button by the chosen rate.</p><p>Gradient: Modify the button press and button release delay based on how far an axis has been moved. The rate will remain the same.</p><p>Pulse: Modify how many times a button is pressed and released per second. The button delay will remain the same.</p></body></html> Normal Gradient Pulse Qt::Vertical QSizePolicy::Fixed 20 20 6 0 0 0 0 0 16777215 20 Delay: 0 0 0 0 16777215 20 0.10s false 0 0 0 400 10 10 true Qt::Horizontal false false QSlider::TicksBelow 10 Qt::Vertical QSizePolicy::Fixed 20 20 Rate: 10.0/s 30 Enabled 0 30 Disabled Select Set 1 One Way Select Set 1 Two Way Select Set 1 While Held Select Set 2 One Way Select Set 2 Two Way Select Set 2 While Held Select Set 3 One Way Select Set 3 Two Way Select Set 3 While Held Select Set 4 One Way Select Set 4 Two Way Select Set 4 While Held Select Set 5 One Way Select Set 5 Two Way Select Set 5 While Held Select Set 6 One Way Select Set 6 Two Way Select Set 6 While Held Select Set 7 One Way Select Set 7 Two Way Select Set 7 While Held Select Set 8 One Way Select Set 8 Two Way Select Set 8 While Held Qt::Vertical 20 289 Qt::Horizontal Qt::Horizontal QDialogButtonBox::Close SlotItemListWidget QListWidget

slotitemlistwidget.h
buttonBox accepted() AdvanceButtonDialog accept() 222 406 157 274 buttonBox rejected() AdvanceButtonDialog reject() 290 412 286 274 listWidget currentRowChanged(int) stackedWidget setCurrentIndex(int) 119 90 573 14 AntiMicroX-antimicrox-2888bf6/src/advancestickassignmentdialog.cpp000066400000000000000000001401661377703515000254760ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "advancestickassignmentdialog.h" #include "ui_advancestickassignmentdialog.h" #include "globalvariables.h" #include "joycontrolstick.h" #include "joystick.h" #include "messagehandler.h" #include "vdpad.h" #include #include #include #include #include #include #include #include AdvanceStickAssignmentDialog::AdvanceStickAssignmentDialog(Joystick *joystick, QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::AdvanceStickAssignmentDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->joystick = joystick; joystick->getActiveSetJoystick()->setIgnoreEventState(true); joystick->getActiveSetJoystick()->release(); joystick->resetButtonDownCount(); QString tempHeaderLabel = ui->joystickNumberLabel->text(); tempHeaderLabel = tempHeaderLabel.arg(joystick->getSDLName()).arg(joystick->getRealJoyNumber()); ui->joystickNumberLabel->setText(tempHeaderLabel); ui->joystickNumberLabel2->setText(tempHeaderLabel); tempHeaderLabel = ui->hatNumberLabel->text(); tempHeaderLabel = tempHeaderLabel.arg(joystick->getNumberHats()); ui->hatNumberLabel->setText(tempHeaderLabel); ui->xAxisOneComboBox->addItem("", QVariant(0)); ui->yAxisOneComboBox->addItem("", QVariant(0)); ui->xAxisTwoComboBox->addItem("", QVariant(0)); ui->yAxisTwoComboBox->addItem("", QVariant(0)); for (int i = 0; i < joystick->getNumberAxes(); i++) { ui->xAxisOneComboBox->addItem(tr("Axis %1").arg(i + 1), QVariant(i)); ui->yAxisOneComboBox->addItem(tr("Axis %1").arg(i + 1), QVariant(i)); ui->xAxisTwoComboBox->addItem(tr("Axis %1").arg(i + 1), QVariant(i)); ui->yAxisTwoComboBox->addItem(tr("Axis %1").arg(i + 1), QVariant(i)); } JoyControlStick *stick1 = joystick->getActiveSetJoystick()->getJoyStick(0); JoyControlStick *stick2 = joystick->getActiveSetJoystick()->getJoyStick(1); refreshStickConfiguration(stick1, stick2); populateDPadComboBoxes(); refreshVDPadsConfiguration(); ui->versionTwoMessageLabel->setVisible(false); connect(ui->enableOneCheckBox, &QCheckBox::clicked, this, &AdvanceStickAssignmentDialog::changeStateStickOneWidgets); connect(ui->enableTwoCheckBox, &QCheckBox::clicked, this, &AdvanceStickAssignmentDialog::changeStateStickTwoWidgets); connect(ui->vdpadEnableCheckBox, &QCheckBox::clicked, this, &AdvanceStickAssignmentDialog::changeStateVDPadWidgets); connect(ui->xAxisOneComboBox, static_cast(&QComboBox::currentIndexChanged), [this]() { this->checkForAxisAssignmentStickOne(ui->xAxisOneComboBox); }); connect(ui->yAxisOneComboBox, static_cast(&QComboBox::currentIndexChanged), [this]() { this->checkForAxisAssignmentStickOne(ui->yAxisOneComboBox); }); connect(ui->xAxisTwoComboBox, static_cast(&QComboBox::currentIndexChanged), [this]() { this->checkForAxisAssignmentStickTwo(ui->xAxisTwoComboBox); }); connect(ui->yAxisTwoComboBox, static_cast(&QComboBox::currentIndexChanged), [this]() { this->checkForAxisAssignmentStickTwo(ui->yAxisTwoComboBox); }); connect(ui->quickAssignStick1PushButton, &QPushButton::clicked, this, &AdvanceStickAssignmentDialog::openQuickAssignDialogStick1); connect(ui->quickAssignStick2PushButton, &QPushButton::clicked, this, &AdvanceStickAssignmentDialog::openQuickAssignDialogStick2); enableVDPadComboBoxes(); connect(this, &AdvanceStickAssignmentDialog::stickConfigurationChanged, this, &AdvanceStickAssignmentDialog::disableVDPadComboBoxes); connect(this, &AdvanceStickAssignmentDialog::stickConfigurationChanged, this, &AdvanceStickAssignmentDialog::populateDPadComboBoxes); connect(this, &AdvanceStickAssignmentDialog::stickConfigurationChanged, this, &AdvanceStickAssignmentDialog::refreshVDPadsConfiguration); connect(this, &AdvanceStickAssignmentDialog::stickConfigurationChanged, this, &AdvanceStickAssignmentDialog::enableVDPadComboBoxes); connect(ui->vdpadUpPushButton, &QPushButton::clicked, this, &AdvanceStickAssignmentDialog::openAssignVDPadUp); connect(ui->vdpadDownPushButton, &QPushButton::clicked, this, &AdvanceStickAssignmentDialog::openAssignVDPadDown); connect(ui->vdpadLeftPushButton, &QPushButton::clicked, this, &AdvanceStickAssignmentDialog::openAssignVDPadLeft); connect(ui->vdpadRightPushButton, &QPushButton::clicked, this, &AdvanceStickAssignmentDialog::openAssignVDPadRight); connect(this, &AdvanceStickAssignmentDialog::finished, this, &AdvanceStickAssignmentDialog::reenableButtonEvents); } // for tests AdvanceStickAssignmentDialog::AdvanceStickAssignmentDialog(QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::AdvanceStickAssignmentDialog) { } AdvanceStickAssignmentDialog::~AdvanceStickAssignmentDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void AdvanceStickAssignmentDialog::checkForAxisAssignmentStickOne(QWidget *comboBox) { qInstallMessageHandler(MessageHandler::myMessageOutput); checkForAxisAssignmentSticks(comboBox, ui->xAxisTwoComboBox, ui->yAxisTwoComboBox, 0); } void AdvanceStickAssignmentDialog::checkForAxisAssignmentStickTwo(QWidget *comboBox) { qInstallMessageHandler(MessageHandler::myMessageOutput); checkForAxisAssignmentSticks(comboBox, ui->xAxisTwoComboBox, ui->yAxisTwoComboBox, 1); } void AdvanceStickAssignmentDialog::checkForAxisAssignmentSticks(QWidget *comboBox, QComboBox *xAxisComboBox, QComboBox *yAxisComboBox, int controlStickNumber) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((xAxisComboBox->currentIndex() > 0) && (yAxisComboBox->currentIndex() > 0)) { if (xAxisComboBox->currentIndex() != yAxisComboBox->currentIndex()) { QHash::iterator set; int originset = 0; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); JoyAxis *axis1 = currentset->getJoyAxis(xAxisComboBox->currentIndex() - 1); JoyAxis *axis2 = currentset->getJoyAxis(yAxisComboBox->currentIndex() - 1); if ((axis1 != nullptr) && (axis2 != nullptr) && (currentset->getJoyStick(controlStickNumber) != nullptr)) { currentset->getJoyStick(controlStickNumber)->replaceAxes(axis1, axis2); } else if ((axis1 != nullptr) && (axis2 != nullptr) && (currentset->getJoyStick(controlStickNumber) == nullptr)) { JoyControlStick *controlstick = new JoyControlStick(axis1, axis2, controlStickNumber, originset, currentset); currentset->addControlStick(controlStickNumber, controlstick); } originset++; } JoyControlStick *stick1 = joystick->getActiveSetJoystick()->getJoyStick(0); JoyControlStick *stick2 = joystick->getActiveSetJoystick()->getJoyStick(1); refreshStickConfiguration(stick1, stick2); emit stickConfigurationChanged(); } else if (comboBox == xAxisComboBox) { yAxisComboBox->setCurrentIndex(0); } else if (comboBox == yAxisComboBox) { xAxisComboBox->setCurrentIndex(0); } } } void AdvanceStickAssignmentDialog::changeStateVDPadWidgets(bool enabledVDPads) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->vdpadUpComboBox->setEnabled(enabledVDPads); ui->vdpadDownComboBox->setEnabled(enabledVDPads); ui->vdpadLeftComboBox->setEnabled(enabledVDPads); ui->vdpadRightComboBox->setEnabled(enabledVDPads); ui->vdpadUpPushButton->setEnabled(enabledVDPads); ui->vdpadDownPushButton->setEnabled(enabledVDPads); ui->vdpadLeftPushButton->setEnabled(enabledVDPads); ui->vdpadRightPushButton->setEnabled(enabledVDPads); QHash::iterator set; int originset = 0; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); if (!currentset->getVDPad(0) && enabledVDPads) { currentset->addVDPad(0, new VDPad(0, originset, currentset, currentset)); } else { currentset->removeVDPad(0); } originset++; } } void AdvanceStickAssignmentDialog::changeStateStickOneWidgets(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (enabled) { ui->xAxisOneComboBox->setEnabled(true); ui->yAxisOneComboBox->setEnabled(true); ui->enableTwoCheckBox->setEnabled(true); ui->quickAssignStick1PushButton->setEnabled(true); } else { ui->xAxisOneComboBox->setEnabled(false); ui->xAxisOneComboBox->setCurrentIndex(0); ui->yAxisOneComboBox->setEnabled(false); ui->yAxisOneComboBox->setCurrentIndex(0); ui->xAxisTwoComboBox->setEnabled(false); ui->yAxisTwoComboBox->setEnabled(false); ui->xAxisTwoComboBox->setCurrentIndex(0); ui->yAxisTwoComboBox->setCurrentIndex(0); ui->enableTwoCheckBox->setEnabled(false); ui->enableTwoCheckBox->setChecked(false); ui->quickAssignStick1PushButton->setEnabled(false); if (joystick->getActiveSetJoystick()->getJoyStick(1) != nullptr) joystick->removeControlStick(1); if (joystick->getActiveSetJoystick()->getJoyStick(0) != nullptr) joystick->removeControlStick(0); } } void AdvanceStickAssignmentDialog::changeStateStickTwoWidgets(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (enabled) { ui->xAxisTwoComboBox->setEnabled(true); ui->yAxisTwoComboBox->setEnabled(true); ui->quickAssignStick2PushButton->setEnabled(true); } else { ui->xAxisTwoComboBox->setEnabled(false); ui->xAxisTwoComboBox->setCurrentIndex(0); ui->yAxisTwoComboBox->setEnabled(false); ui->yAxisTwoComboBox->setCurrentIndex(0); ui->quickAssignStick2PushButton->setEnabled(false); if (joystick->getActiveSetJoystick()->getJoyStick(1) != nullptr) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { set.value()->removeControlStick(1); } } } } void AdvanceStickAssignmentDialog::refreshStickConfiguration(JoyControlStick *stick1, JoyControlStick *stick2) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((stick1 != nullptr) && (stick1->getAxisX() != nullptr) && (stick1->getAxisY() != nullptr)) { refreshSticksForAxes(true, stick1->getAxisX()->getRealJoyIndex(), stick1->getAxisY()->getRealJoyIndex(), ui->xAxisOneComboBox, ui->yAxisOneComboBox, ui->enableOneCheckBox, ui->quickAssignStick1PushButton); } else { refreshSticksForAxes(false, 0, 0, ui->xAxisOneComboBox, ui->yAxisOneComboBox, ui->enableOneCheckBox, ui->quickAssignStick1PushButton); } if ((stick2 != nullptr) && (stick2->getAxisX() != nullptr) && (stick2->getAxisY() != nullptr)) { refreshSticksForAxes(true, stick2->getAxisX()->getRealJoyIndex(), stick2->getAxisY()->getRealJoyIndex(), ui->xAxisTwoComboBox, ui->yAxisTwoComboBox, ui->enableTwoCheckBox, ui->quickAssignStick2PushButton); } else { refreshSticksForAxes(false, 0, 0, ui->xAxisTwoComboBox, ui->yAxisTwoComboBox, ui->enableTwoCheckBox, ui->quickAssignStick2PushButton); } } void AdvanceStickAssignmentDialog::refreshSticksForAxes(bool axesExist, int xAxisComboBoxIndex, int yAxisComboBoxIndex, QComboBox *xAxisComboBox, QComboBox *yAxisComboBox, QCheckBox *enabledSticksCheckbox, QPushButton *quickAssignBtn) { xAxisComboBox->setCurrentIndex(xAxisComboBoxIndex); yAxisComboBox->setCurrentIndex(yAxisComboBoxIndex); xAxisComboBox->setEnabled(axesExist); yAxisComboBox->setEnabled(axesExist); enabledSticksCheckbox->setEnabled(axesExist); enabledSticksCheckbox->setChecked(axesExist); quickAssignBtn->setEnabled(axesExist); } void AdvanceStickAssignmentDialog::refreshVDPadsConfiguration() { qInstallMessageHandler(MessageHandler::myMessageOutput); VDPad *vdpad = joystick->getActiveSetJoystick()->getVDPad(0); if (vdpad != nullptr) { ui->vdpadEnableCheckBox->setChecked(true); ui->vdpadUpComboBox->setEnabled(true); ui->vdpadDownComboBox->setEnabled(true); ui->vdpadLeftComboBox->setEnabled(true); ui->vdpadRightComboBox->setEnabled(true); ui->vdpadUpPushButton->setEnabled(true); ui->vdpadDownPushButton->setEnabled(true); ui->vdpadLeftPushButton->setEnabled(true); ui->vdpadRightPushButton->setEnabled(true); JoyButton *upButton = vdpad->getVButton(JoyDPadButton::DpadUp); refreshVDPadConf(upButton, ui->vdpadUpComboBox); JoyButton *downButton = vdpad->getVButton(JoyDPadButton::DpadDown); refreshVDPadConf(downButton, ui->vdpadDownComboBox); JoyButton *leftButton = vdpad->getVButton(JoyDPadButton::DpadLeft); refreshVDPadConf(leftButton, ui->vdpadLeftComboBox); JoyButton *rightButton = vdpad->getVButton(JoyDPadButton::DpadRight); refreshVDPadConf(rightButton, ui->vdpadRightComboBox); } else { ui->vdpadEnableCheckBox->setChecked(false); ui->vdpadUpComboBox->setCurrentIndex(0); ui->vdpadUpComboBox->setEnabled(false); ui->vdpadDownComboBox->setCurrentIndex(0); ui->vdpadDownComboBox->setEnabled(false); ui->vdpadLeftComboBox->setCurrentIndex(0); ui->vdpadLeftComboBox->setEnabled(false); ui->vdpadRightComboBox->setCurrentIndex(0); ui->vdpadRightComboBox->setEnabled(false); ui->vdpadUpPushButton->setEnabled(false); ui->vdpadDownPushButton->setEnabled(false); ui->vdpadLeftPushButton->setEnabled(false); ui->vdpadRightPushButton->setEnabled(false); } } void AdvanceStickAssignmentDialog::refreshVDPadConf(JoyButton *vdpadButton, QComboBox *vpadComboBox) { if (vdpadButton != nullptr) { int buttonindex = 0; if (typeid(*vdpadButton) == typeid(JoyAxisButton)) { JoyAxisButton *axisbutton = qobject_cast(vdpadButton); JoyAxis *axis = axisbutton->getAxis(); QList templist; templist.append(QVariant(axis->getRealJoyIndex())); templist.append(QVariant(axisbutton->getJoyNumber())); buttonindex = vpadComboBox->findData(templist); } else { QList templist; templist.append(QVariant(0)); templist.append(QVariant(vdpadButton->getRealJoyNumber())); buttonindex = vpadComboBox->findData(templist); } if (buttonindex == -1) vdpadButton->getVDPad()->removeVButton(vdpadButton); else vpadComboBox->setCurrentIndex(buttonindex); } } void AdvanceStickAssignmentDialog::populateDPadComboBoxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->vdpadUpComboBox->clear(); ui->vdpadDownComboBox->clear(); ui->vdpadLeftComboBox->clear(); ui->vdpadRightComboBox->clear(); ui->vdpadUpComboBox->addItem("", QVariant(0)); ui->vdpadDownComboBox->addItem("", QVariant(0)); ui->vdpadLeftComboBox->addItem("", QVariant(0)); ui->vdpadRightComboBox->addItem("", QVariant(0)); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (!axis->isPartControlStick()) { QList templist; templist.append(QVariant(i + 1)); templist.append(QVariant(0)); ui->vdpadUpComboBox->addItem(tr("Axis %1 -").arg(QString::number(i + 1)), templist); ui->vdpadDownComboBox->addItem(tr("Axis %1 -").arg(QString::number(i + 1)), templist); ui->vdpadLeftComboBox->addItem(tr("Axis %1 -").arg(QString::number(i + 1)), templist); ui->vdpadRightComboBox->addItem(tr("Axis %1 -").arg(QString::number(i + 1)), templist); templist.clear(); templist.append(QVariant(i + 1)); templist.append(QVariant(1)); ui->vdpadUpComboBox->addItem(tr("Axis %1 +").arg(QString::number(i + 1)), templist); ui->vdpadDownComboBox->addItem(tr("Axis %1 +").arg(QString::number(i + 1)), templist); ui->vdpadLeftComboBox->addItem(tr("Axis %1 +").arg(QString::number(i + 1)), templist); ui->vdpadRightComboBox->addItem(tr("Axis %1 +").arg(QString::number(i + 1)), templist); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { QList templist; templist.append(QVariant(0)); templist.append(QVariant(i + 1)); ui->vdpadUpComboBox->addItem(tr("Button %1").arg(QString::number(i + 1)), templist); ui->vdpadDownComboBox->addItem(tr("Button %1").arg(QString::number(i + 1)), templist); ui->vdpadLeftComboBox->addItem(tr("Button %1").arg(QString::number(i + 1)), templist); ui->vdpadRightComboBox->addItem(tr("Button %1").arg(QString::number(i + 1)), templist); } } void AdvanceStickAssignmentDialog::changeVDPadUpButton(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index > 0) { if (ui->vdpadDownComboBox->currentIndex() == index) { ui->vdpadDownComboBox->setCurrentIndex(0); } else if (ui->vdpadLeftComboBox->currentIndex() == index) { ui->vdpadLeftComboBox->setCurrentIndex(0); } else if (ui->vdpadRightComboBox->currentIndex() == index) { ui->vdpadRightComboBox->setCurrentIndex(0); } QVariant temp = ui->vdpadUpComboBox->itemData(index); QList templist = temp.toList(); if (templist.size() == 2) { int axis = templist.at(0).toInt(); int button = templist.at(1).toInt(); if ((axis > 0) && (button >= 0)) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyAxis *currentaxis = currentset->getJoyAxis(axis - 1); JoyButton *currentbutton = nullptr; if (button == 0) { currentbutton = currentaxis->getNAxisButton(); } else if (button == 1) { currentbutton = currentaxis->getPAxisButton(); } vdpad->addVButton(JoyDPadButton::DpadUp, currentbutton); } } else if (button > 0) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyButton *currentbutton = currentset->getJoyButton(button - 1); if (currentbutton != nullptr) { vdpad->addVButton(JoyDPadButton::DpadUp, currentbutton); } } } } } else { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); if ((vdpad != nullptr) && vdpad->getVButton(JoyDPadButton::DpadUp)) { vdpad->removeVButton(JoyDPadButton::DpadUp); } } } } void AdvanceStickAssignmentDialog::changeVDPadDownButton(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index > 0) { if (ui->vdpadUpComboBox->currentIndex() == index) { ui->vdpadUpComboBox->setCurrentIndex(0); } else if (ui->vdpadLeftComboBox->currentIndex() == index) { ui->vdpadLeftComboBox->setCurrentIndex(0); } else if (ui->vdpadRightComboBox->currentIndex() == index) { ui->vdpadRightComboBox->setCurrentIndex(0); } QVariant temp = ui->vdpadDownComboBox->itemData(index); QList templist = temp.toList(); if (templist.size() == 2) { int axis = templist.at(0).toInt(); int button = templist.at(1).toInt(); if ((axis > 0) && (button >= 0)) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyAxis *currentaxis = currentset->getJoyAxis(axis - 1); JoyButton *currentbutton = nullptr; if (button == 0) { currentbutton = currentaxis->getNAxisButton(); } else if (button == 1) { currentbutton = currentaxis->getPAxisButton(); } vdpad->addVButton(JoyDPadButton::DpadDown, currentbutton); } } else if (button > 0) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyButton *currentbutton = currentset->getJoyButton(button - 1); if (currentbutton != nullptr) { vdpad->addVButton(JoyDPadButton::DpadDown, currentbutton); } } } } } else { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); if ((vdpad != nullptr) && vdpad->getVButton(JoyDPadButton::DpadDown)) { vdpad->removeVButton(JoyDPadButton::DpadDown); } } } } void AdvanceStickAssignmentDialog::changeVDPadLeftButton(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index > 0) { if (ui->vdpadUpComboBox->currentIndex() == index) { ui->vdpadUpComboBox->setCurrentIndex(0); } else if (ui->vdpadDownComboBox->currentIndex() == index) { ui->vdpadDownComboBox->setCurrentIndex(0); } else if (ui->vdpadRightComboBox->currentIndex() == index) { ui->vdpadRightComboBox->setCurrentIndex(0); } QVariant temp = ui->vdpadLeftComboBox->itemData(index); QList templist = temp.toList(); if (templist.size() == 2) { int axis = templist.at(0).toInt(); int button = templist.at(1).toInt(); if ((axis > 0) && (button >= 0)) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyAxis *currentaxis = currentset->getJoyAxis(axis - 1); JoyButton *currentbutton = nullptr; if (button == 0) { currentbutton = currentaxis->getNAxisButton(); } else if (button == 1) { currentbutton = currentaxis->getPAxisButton(); } vdpad->addVButton(JoyDPadButton::DpadLeft, currentbutton); } } else if (button > 0) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyButton *currentbutton = currentset->getJoyButton(button - 1); if (currentbutton != nullptr) { vdpad->addVButton(JoyDPadButton::DpadLeft, currentbutton); } } } } } else { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); if ((vdpad != nullptr) && vdpad->getVButton(JoyDPadButton::DpadLeft)) { vdpad->removeVButton(JoyDPadButton::DpadLeft); } } } } void AdvanceStickAssignmentDialog::changeVDPadRightButton(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index > 0) { if (ui->vdpadUpComboBox->currentIndex() == index) { ui->vdpadUpComboBox->setCurrentIndex(0); } else if (ui->vdpadDownComboBox->currentIndex() == index) { ui->vdpadDownComboBox->setCurrentIndex(0); } else if (ui->vdpadLeftComboBox->currentIndex() == index) { ui->vdpadLeftComboBox->setCurrentIndex(0); } QVariant temp = ui->vdpadRightComboBox->itemData(index); QList templist = temp.toList(); if (templist.size() == 2) { int axis = templist.at(0).toInt(); int button = templist.at(1).toInt(); if ((axis > 0) && (button >= 0)) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyAxis *currentaxis = currentset->getJoyAxis(axis - 1); JoyButton *currentbutton = nullptr; if (button == 0) { currentbutton = currentaxis->getNAxisButton(); } else if (button == 1) { currentbutton = currentaxis->getPAxisButton(); } vdpad->addVButton(JoyDPadButton::DpadRight, currentbutton); } } else if (button > 0) { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); JoyButton *currentbutton = currentset->getJoyButton(button - 1); if (currentbutton != nullptr) { vdpad->addVButton(JoyDPadButton::DpadRight, currentbutton); } } } } } else { QHash::iterator set; for (set = joystick->getJoystick_sets().begin(); set != joystick->getJoystick_sets().end(); ++set) { SetJoystick *currentset = set.value(); VDPad *vdpad = currentset->getVDPad(0); if ((vdpad != nullptr) && vdpad->getVButton(JoyDPadButton::DpadRight)) { vdpad->removeVButton(JoyDPadButton::DpadRight); } } } } void AdvanceStickAssignmentDialog::enableVDPadComboBoxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(ui->vdpadUpComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadUpButton); connect(ui->vdpadDownComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadDownButton); connect(ui->vdpadLeftComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadLeftButton); connect(ui->vdpadRightComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadRightButton); } void AdvanceStickAssignmentDialog::disableVDPadComboBoxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(ui->vdpadUpComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadUpButton); disconnect(ui->vdpadDownComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadDownButton); disconnect(ui->vdpadLeftComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadLeftButton); disconnect(ui->vdpadRightComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AdvanceStickAssignmentDialog::changeVDPadRightButton); } void AdvanceStickAssignmentDialog::openQuickAssignDialogStick1() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msgBox; msgBox.setText(tr("Move stick 1 along the X axis")); msgBox.setStandardButtons(QMessageBox::Close); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (axis != nullptr) { connect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); connect(axis, &JoyAxis::active, this, [this, axis] { ui->xAxisOneComboBox->setCurrentIndex(axis->getRealJoyIndex()); }); } } msgBox.exec(); msgBox.setText(tr("Move stick 1 along the Y axis")); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (axis != nullptr) { disconnect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); disconnect(axis, &JoyAxis::active, this, nullptr); connect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); connect(axis, &JoyAxis::active, this, [this, axis] { ui->yAxisOneComboBox->setCurrentIndex(axis->getRealJoyIndex()); }); } } msgBox.exec(); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (axis != nullptr) { disconnect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); disconnect(axis, &JoyAxis::active, this, nullptr); } } } void AdvanceStickAssignmentDialog::openQuickAssignDialogStick2() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msgBox; msgBox.setText(tr("Move stick 2 along the X axis")); msgBox.setStandardButtons(QMessageBox::Close); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (axis != nullptr) { connect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); connect(axis, &JoyAxis::active, this, [this, axis] { ui->xAxisTwoComboBox->setCurrentIndex(axis->getRealJoyIndex()); }); } } msgBox.exec(); msgBox.setText(tr("Move stick 2 along the Y axis")); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (axis != nullptr) { disconnect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); disconnect(axis, &JoyAxis::active, this, nullptr); connect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); connect(axis, &JoyAxis::active, this, [this, axis] { ui->yAxisTwoComboBox->setCurrentIndex(axis->getRealJoyIndex()); }); } } msgBox.exec(); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (axis != nullptr) { disconnect(axis, &JoyAxis::active, &msgBox, &QMessageBox::close); disconnect(axis, &JoyAxis::active, this, nullptr); } } } void AdvanceStickAssignmentDialog::reenableButtonEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); joystick->getActiveSetJoystick()->setIgnoreEventState(false); joystick->getActiveSetJoystick()->release(); } void AdvanceStickAssignmentDialog::openAssignVDPadUp() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msgBox; msgBox.setText(tr("Press a button or move an axis")); msgBox.setStandardButtons(QMessageBox::Close); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { JoyAxisButton *axbtn = axis->getNAxisButton(); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, [this, axbtn] { quickAssignVDPadUp(axbtn); }); JoyAxisButton *axbtnp = axis->getPAxisButton(); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, [this, axbtnp] { quickAssignVDPadUp(axbtnp); }); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { connect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); connect(button, &JoyButton::clicked, this, [this, button]() { quickAssignVDPadUpBtn(button); }); } } msgBox.exec(); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, nullptr); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, nullptr); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { disconnect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); disconnect(button, &JoyButton::clicked, this, nullptr); } } } void AdvanceStickAssignmentDialog::openAssignVDPadDown() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msgBox; msgBox.setText(tr("Press a button or move an axis")); msgBox.setStandardButtons(QMessageBox::Close); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { JoyAxisButton *axbtn = axis->getNAxisButton(); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, [this, axbtn] { quickAssignVDPadDown(axbtn); }); JoyAxisButton *axbtnP = axis->getPAxisButton(); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, [this, axbtnP] { quickAssignVDPadDown(axbtnP); }); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { connect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); connect(button, &JoyButton::clicked, this, [this, button] { quickAssignVDPadDownJbtn(button); }); } } msgBox.exec(); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, nullptr); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, nullptr); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { disconnect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); disconnect(button, &JoyButton::clicked, this, nullptr); } } } void AdvanceStickAssignmentDialog::openAssignVDPadLeft() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msgBox; msgBox.setText(tr("Press a button or move an axis")); msgBox.setStandardButtons(QMessageBox::Close); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { JoyAxisButton *joyaxisN = axis->getNAxisButton(); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, [this, joyaxisN]() { quickAssignVDPadLeft(joyaxisN); }); JoyAxisButton *joyaxisP = axis->getPAxisButton(); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, [this, joyaxisP]() { quickAssignVDPadLeft(joyaxisP); }); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { connect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); connect(button, &JoyButton::clicked, this, [this, button] { quickAssignVDPadLeftJbtn(button); }); } } msgBox.exec(); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, nullptr); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, nullptr); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { disconnect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); disconnect(button, &JoyButton::clicked, this, nullptr); } } } void AdvanceStickAssignmentDialog::openAssignVDPadRight() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msgBox; msgBox.setText(tr("Press a button or move an axis")); msgBox.setStandardButtons(QMessageBox::Close); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { JoyAxisButton *joyaxisbtnN = axis->getNAxisButton(); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, [this, joyaxisbtnN] { quickAssignVDPadRight(joyaxisbtnN); }); JoyAxisButton *joyaxisbtnP = axis->getPAxisButton(); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); connect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, [this, joyaxisbtnP] { quickAssignVDPadRight(joyaxisbtnP); }); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { connect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); connect(button, &JoyButton::clicked, this, [this, button] { quickAssignVDPadRightJbtn(button); }); } } msgBox.exec(); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && !axis->isPartControlStick()) { disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getNAxisButton(), &JoyAxisButton::clicked, this, nullptr); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, &msgBox, &QMessageBox::close); disconnect(axis->getPAxisButton(), &JoyAxisButton::clicked, this, nullptr); } } for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { disconnect(button, &JoyButton::clicked, &msgBox, &QMessageBox::close); disconnect(button, &JoyButton::clicked, this, nullptr); } } } void AdvanceStickAssignmentDialog::quickAssignVDPadUp(JoyAxisButton *joyaxisbtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); QList templist; templist.append(QVariant(joyaxisbtn->getAxis()->getRealJoyIndex())); if (joyaxisbtn->getAxis()->getNAxisButton() == joyaxisbtn) templist.append(QVariant(0)); else templist.append(QVariant(1)); int index = ui->vdpadUpComboBox->findData(templist); if (index > 0) { ui->vdpadUpComboBox->setCurrentIndex(index); } } void AdvanceStickAssignmentDialog::quickAssignVDPadUpBtn(JoyButton *joybtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); QList templist; templist.append(QVariant(0)); templist.append(QVariant(joybtn->getJoyNumber() + 1)); int index = ui->vdpadUpComboBox->findData(templist); if (index > 0) { ui->vdpadUpComboBox->setCurrentIndex(index); } } void AdvanceStickAssignmentDialog::quickAssignVDPadDown(JoyAxisButton *axbtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); QList templist; templist.append(QVariant(axbtn->getAxis()->getRealJoyIndex())); if (axbtn->getAxis()->getNAxisButton() == axbtn) templist.append(QVariant(0)); else templist.append(QVariant(1)); int index = ui->vdpadDownComboBox->findData(templist); if (index > 0) ui->vdpadDownComboBox->setCurrentIndex(index); } void AdvanceStickAssignmentDialog::quickAssignVDPadDownJbtn(JoyButton *joybtn) { QList templist; templist.append(QVariant(0)); templist.append(QVariant(joybtn->getJoyNumber() + 1)); int index = ui->vdpadDownComboBox->findData(templist); if (index > 0) ui->vdpadDownComboBox->setCurrentIndex(index); } void AdvanceStickAssignmentDialog::quickAssignVDPadLeft(JoyAxisButton *joyaxisbtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); QList templist; templist.append(QVariant(joyaxisbtn->getAxis()->getRealJoyIndex())); if (joyaxisbtn->getAxis()->getNAxisButton() == joyaxisbtn) templist.append(QVariant(0)); else templist.append(QVariant(1)); int index = ui->vdpadLeftComboBox->findData(templist); if (index > 0) ui->vdpadLeftComboBox->setCurrentIndex(index); } void AdvanceStickAssignmentDialog::quickAssignVDPadLeftJbtn(JoyButton *joybtn) { QList templist; templist.append(QVariant(0)); templist.append(QVariant(joybtn->getJoyNumber() + 1)); int index = ui->vdpadLeftComboBox->findData(templist); if (index > 0) ui->vdpadLeftComboBox->setCurrentIndex(index); } void AdvanceStickAssignmentDialog::quickAssignVDPadRight(JoyAxisButton *joyaxisbtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); QList templist; templist.append(QVariant(joyaxisbtn->getAxis()->getRealJoyIndex())); if (joyaxisbtn->getAxis()->getNAxisButton() == joyaxisbtn) templist.append(QVariant(0)); else templist.append(QVariant(1)); int index = ui->vdpadRightComboBox->findData(templist); if (index > 0) ui->vdpadRightComboBox->setCurrentIndex(index); } void AdvanceStickAssignmentDialog::quickAssignVDPadRightJbtn(JoyButton *joybtn) { QList templist; templist.append(QVariant(0)); templist.append(QVariant(joybtn->getJoyNumber() + 1)); int index = ui->vdpadRightComboBox->findData(templist); if (index > 0) ui->vdpadRightComboBox->setCurrentIndex(index); } Joystick *AdvanceStickAssignmentDialog::getJoystick() const { return joystick; } AntiMicroX-antimicrox-2888bf6/src/advancestickassignmentdialog.h000066400000000000000000000066161377703515000251440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ADVANCESTICKASSIGNMENTDIALOG_H #define ADVANCESTICKASSIGNMENTDIALOG_H #include class Joystick; class JoyAxisButton; class JoyButton; class QComboBox; class QCheckBox; class JoyControlStick; namespace Ui { class AdvanceStickAssignmentDialog; } class AdvanceStickAssignmentDialog : public QDialog { Q_OBJECT public: explicit AdvanceStickAssignmentDialog(Joystick *joystick, QWidget *parent = nullptr); AdvanceStickAssignmentDialog(QWidget *parent = nullptr); ~AdvanceStickAssignmentDialog(); Joystick *getJoystick() const; signals: void stickConfigurationChanged(); void vdpadConfigurationChanged(); private slots: void refreshStickConfiguration(JoyControlStick *stick1, JoyControlStick *stick2); void refreshVDPadsConfiguration(); void checkForAxisAssignmentStickOne(QWidget *comboBox); void checkForAxisAssignmentStickTwo(QWidget *comboBox); void changeStateStickOneWidgets(bool enabled); void changeStateStickTwoWidgets(bool enabled); void changeStateVDPadWidgets(bool enabledVDPads); void populateDPadComboBoxes(); void changeVDPadUpButton(int index); void changeVDPadDownButton(int index); void changeVDPadLeftButton(int index); void changeVDPadRightButton(int index); void disableVDPadComboBoxes(); void enableVDPadComboBoxes(); void openQuickAssignDialogStick1(); void openQuickAssignDialogStick2(); void openAssignVDPadUp(); void openAssignVDPadDown(); void openAssignVDPadLeft(); void openAssignVDPadRight(); void quickAssignVDPadUp(JoyAxisButton *joyaxisbtn); void quickAssignVDPadUpBtn(JoyButton *joybtn); void quickAssignVDPadDown(JoyAxisButton *axbtn); void quickAssignVDPadDownJbtn(JoyButton *axbtn); void quickAssignVDPadLeft(JoyAxisButton *joyaxisbtn); void quickAssignVDPadLeftJbtn(JoyButton *joybtn); void quickAssignVDPadRight(JoyAxisButton *joyaxisbtn); void quickAssignVDPadRightJbtn(JoyButton *joybtn); void reenableButtonEvents(); private: Ui::AdvanceStickAssignmentDialog *ui; Joystick *joystick; void checkForAxisAssignmentSticks(QWidget *comboBox, QComboBox *xAxisComboBox, QComboBox *yAxisComboBox, int controlStickNumber); void refreshSticksForAxes(bool axesExist, int xAxisComboBoxIndex, int yAxisComboBoxIndex, QComboBox *xAxisComboBox, QComboBox *yAxisComboBox, QCheckBox *enabledSticksCheckbox, QPushButton *quickAssignBtn); void refreshVDPadConf(JoyButton *vdpadButton, QComboBox *vpadComboBox); }; #endif // ADVANCESTICKASSIGNMENTDIALOG_H AntiMicroX-antimicrox-2888bf6/src/advancestickassignmentdialog.ui000066400000000000000000000505131377703515000253250ustar00rootroot00000000000000 AdvanceStickAssignmentDialog 0 0 770 440 0 0 Stick/Pad Assignment true 0 0 0 Sticks DPads Qt::Horizontal QSizePolicy::Fixed 20 20 0 50 false Note: This window is meant for backwards compatibility with profiles made before antimicro 2.0. Since version 2.0, use of the Game Controller Mapping window is preferred. true 75 true %1 (Joystick %2) -1 -1 75 true Stick 1 true Enabled Qt::Vertical QSizePolicy::Fixed 20 20 Qt::Horizontal 40 20 false Assign X Axis: false Y Axis: false Qt::Horizontal QSizePolicy::Fixed 40 10 75 true Stick 2 false Enabled Qt::Vertical QSizePolicy::Fixed 20 20 Qt::Horizontal 40 20 false Assign X Axis: false Y Axis: false 75 true %1 (Joystick %2) 75 true Number of Physical DPads: %1 Qt::Vertical 20 40 -1 75 true Virtual DPad 1 Qt::Vertical QSizePolicy::Fixed 20 11 Enabled Qt::Vertical QSizePolicy::Fixed 20 20 41 20 false Down: false Left: false Right: Up: false false Assign false Assign false Assign false Assign Qt::Vertical QSizePolicy::Fixed 20 20 Qt::Horizontal Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() AdvanceStickAssignmentDialog accept() 252 369 157 274 buttonBox rejected() AdvanceStickAssignmentDialog reject() 320 369 286 274 listWidget currentRowChanged(int) stackedWidget setCurrentIndex(int) 91 116 291 105 AntiMicroX-antimicrox-2888bf6/src/antimicrosettings.cpp000066400000000000000000000053461377703515000233340ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "antimicrosettings.h" #include "messagehandler.h" #include AntiMicroSettings::AntiMicroSettings(const QString &fileName, Format format, QObject *parent) : QSettings(fileName, format, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } /** * @brief Get the currently used value such as an setting overridden * with a command line argument. * @param Setting key * @param Default value to use if key does not exist * @return Stored value or the default value passed */ QVariant AntiMicroSettings::runtimeValue(const QString &key, const QVariant &defaultValue) const { qInstallMessageHandler(MessageHandler::myMessageOutput); QVariant settingValue; QString inGroup = group(); QString fullKey = QString(inGroup).append("/").append(key); if (cmdSettings.contains(fullKey)) settingValue = cmdSettings.value(fullKey, defaultValue); else settingValue = value(key, defaultValue); return settingValue; } /** * @brief Import relevant options given on the command line into a QSettings * instance. Used to override any options that might be present in the * main settings file. Keys will have to be changed to the appropriate * config key. * @param Interpreted options set on the command line. */ void AntiMicroSettings::importFromCommandLine(CommandLineUtility &cmdutility) { qInstallMessageHandler(MessageHandler::myMessageOutput); getCmdSettings().clear(); if (cmdutility.isLaunchInTrayEnabled()) { getCmdSettings().setValue("LaunchInTray", 1); } if (cmdutility.shouldMapController()) { getCmdSettings().setValue("DisplaySDLMapping", 1); } } QMutex *AntiMicroSettings::getLock() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &lock; } QSettings &AntiMicroSettings::getCmdSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); return cmdSettings; } AntiMicroX-antimicrox-2888bf6/src/antimicrosettings.h000066400000000000000000000026011377703515000227700ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ANTIMICROSETTINGS_H #define ANTIMICROSETTINGS_H #include "commandlineutility.h" #include class AntiMicroSettings : public QSettings { Q_OBJECT public: explicit AntiMicroSettings(const QString &fileName, Format format, QObject *parent = nullptr); QVariant runtimeValue(const QString &key, const QVariant &defaultValue = QVariant()) const; void importFromCommandLine(CommandLineUtility &cmdutility); QMutex *getLock(); QSettings &getCmdSettings(); protected: QSettings cmdSettings; QMutex lock; }; #endif // ANTIMICROSETTINGS_H AntiMicroX-antimicrox-2888bf6/src/antkeymapper.cpp000066400000000000000000000065521377703515000222660ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "antkeymapper.h" #include "eventhandlerfactory.h" #include "messagehandler.h" #include #include #include AntKeyMapper *AntKeyMapper::_instance = nullptr; static QStringList buildEventGeneratorList() { qInstallMessageHandler(MessageHandler::myMessageOutput); QStringList temp = QStringList(); #ifdef WITH_XTEST temp.append("xtest"); #endif #ifdef WITH_UINPUT temp.append("uinput"); #endif return temp; } AntKeyMapper::AntKeyMapper(QString handler, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); internalMapper = nullptr; #if defined(Q_OS_UNIX) #ifdef WITH_XTEST if (handler == "xtest") { internalMapper = &x11Mapper; nativeKeyMapper = nullptr; } #endif #ifdef WITH_UINPUT if (handler == "uinput") { internalMapper = &uinputMapper; #ifdef WITH_XTEST nativeKeyMapper = &x11Mapper; #else nativeKeyMapper = nullptr; #endif } #endif #endif } AntKeyMapper *AntKeyMapper::getInstance(QString handler) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (_instance == nullptr) { Q_ASSERT(!handler.isEmpty()); QStringList temp = buildEventGeneratorList(); Q_ASSERT(temp.contains(handler)); _instance = new AntKeyMapper(handler); } return _instance; } void AntKeyMapper::deleteInstance() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (_instance != nullptr) { delete _instance; _instance = nullptr; } } int AntKeyMapper::returnQtKey(int key, int scancode) { qInstallMessageHandler(MessageHandler::myMessageOutput); return internalMapper->returnQtKey(key, scancode); } int AntKeyMapper::returnVirtualKey(int qkey) { qInstallMessageHandler(MessageHandler::myMessageOutput); return internalMapper->returnVirtualKey(qkey); } bool AntKeyMapper::isModifierKey(int qkey) { qInstallMessageHandler(MessageHandler::myMessageOutput); return internalMapper->isModifier(qkey); } QtKeyMapperBase *AntKeyMapper::getNativeKeyMapper() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return nativeKeyMapper; } QtKeyMapperBase *AntKeyMapper::getKeyMapper() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return internalMapper; } bool AntKeyMapper::hasNativeKeyMapper() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = (nativeKeyMapper != nullptr); return result; } AntiMicroX-antimicrox-2888bf6/src/antkeymapper.h000066400000000000000000000033701377703515000217260ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ANTKEYMAPPER_H #define ANTKEYMAPPER_H #include #if defined(WITH_XTEST) #include "qtx11keymapper.h" #endif #if defined(WITH_UINPUT) #include "qtuinputkeymapper.h" #endif class AntKeyMapper : public QObject { Q_OBJECT public: static AntKeyMapper *getInstance(QString handler = ""); void deleteInstance(); int returnVirtualKey(int qkey); int returnQtKey(int key, int scancode = 0); bool isModifierKey(int qkey); QtKeyMapperBase *getNativeKeyMapper() const; QtKeyMapperBase *getKeyMapper() const; bool hasNativeKeyMapper(); protected: static AntKeyMapper *_instance; private: explicit AntKeyMapper(QString handler = "", QObject *parent = nullptr); QtKeyMapperBase *internalMapper; QtKeyMapperBase *nativeKeyMapper; #if defined(WITH_XTEST) QtX11KeyMapper x11Mapper; #endif #if defined(WITH_UINPUT) QtUInputKeyMapper uinputMapper; #endif }; #endif // ANTKEYMAPPER_H AntiMicroX-antimicrox-2888bf6/src/applaunchhelper.cpp000066400000000000000000000166701377703515000227430ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "applaunchhelper.h" #include "antimicrosettings.h" #include "globalvariables.h" #include "inputdevice.h" #include "joybutton.h" #include "messagehandler.h" #include #include #include #include #include AppLaunchHelper::AppLaunchHelper(AntiMicroSettings *settings, bool graphical, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->settings = settings; this->graphical = graphical; } void AppLaunchHelper::initRunMethods() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (graphical) { establishMouseTimerConnections(); enablePossibleMouseSmoothing(); changeMouseRefreshRate(); changeSpringModeScreen(); changeGamepadPollRate(); } } void AppLaunchHelper::enablePossibleMouseSmoothing() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool smoothingEnabled = settings->value("Mouse/Smoothing", false).toBool(); if (smoothingEnabled) { int historySize = settings->value("Mouse/HistorySize", 0).toInt(); if (historySize > 0) { JoyButton::setMouseHistorySize(historySize, GlobalVariables::JoyButton::MAXIMUMMOUSEHISTORYSIZE, GlobalVariables::JoyButton::mouseHistorySize, &GlobalVariables::JoyButton::mouseHistoryX, &GlobalVariables::JoyButton::mouseHistoryY); } double weightModifier = settings->value("Mouse/WeightModifier", 0.0).toDouble(); if (weightModifier > 0.0) { JoyButton::setWeightModifier(weightModifier, GlobalVariables::JoyButton::MAXIMUMWEIGHTMODIFIER, GlobalVariables::JoyButton::weightModifier); } } } void AppLaunchHelper::changeMouseRefreshRate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int refreshRate = settings->value("Mouse/RefreshRate", 0).toInt(); if (refreshRate > 0) { JoyButton::setMouseRefreshRate(refreshRate, GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE, JoyButton::getMouseHelper(), &GlobalVariables::JoyButton::mouseHistoryX, &GlobalVariables::JoyButton::mouseHistoryY, JoyButton::getTestOldMouseTime(), JoyButton::getStaticMouseEventTimer()); } } void AppLaunchHelper::changeGamepadPollRate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int pollRate = settings->value("GamepadPollRate", GlobalVariables::AntimicroSettings::defaultSDLGamepadPollRate).toInt(); if (pollRate > 0) { JoyButton::setGamepadRefreshRate(pollRate, GlobalVariables::JoyButton::gamepadRefreshRate, JoyButton::getMouseHelper()); } } void AppLaunchHelper::printControllerList(QMap *joysticks) { qInstallMessageHandler(MessageHandler::myMessageOutput); QTextStream outstream(stdout); outstream << QObject::tr("# of joysticks found: %1").arg(joysticks->size()) << endl; outstream << endl; outstream << QObject::tr("List Joysticks:") << endl; outstream << QObject::tr("---------------") << endl; QMapIterator iter(*joysticks); int indexNumber = 1; while (iter.hasNext()) { InputDevice *tempdevice = iter.next().value(); outstream << QObject::tr("Joystick %1:").arg(indexNumber) << endl; outstream << " " << QObject::tr("Index: %1").arg(tempdevice->getRealJoyNumber()) << endl; // outstream << " " << QObject::tr("GUID: %1").arg(tempdevice->getGUIDString()) << endl; outstream << " " << QObject::tr("UniqueID: %1").arg(tempdevice->getUniqueIDString()) << endl; outstream << " " << QObject::tr("GUID: %1").arg(tempdevice->getGUIDString()) << endl; outstream << " " << QObject::tr("VendorID: %1").arg(tempdevice->getVendorString()) << endl; outstream << " " << QObject::tr("ProductID: %1").arg(tempdevice->getProductIDString()) << endl; outstream << " " << QObject::tr("Product Version: %1").arg(tempdevice->getProductVersion()) << endl; outstream << " " << QObject::tr("Name: %1").arg(tempdevice->getSDLName()) << endl; QString gameControllerStatus = tempdevice->isGameController() ? QObject::tr("Yes") : QObject::tr("No"); outstream << " " << QObject::tr("Game Controller: %1").arg(gameControllerStatus) << endl; outstream << " " << QObject::tr("# of Axes: %1").arg(tempdevice->getNumberRawAxes()) << endl; outstream << " " << QObject::tr("# of Buttons: %1").arg(tempdevice->getNumberRawButtons()) << endl; outstream << " " << QObject::tr("# of Hats: %1").arg(tempdevice->getNumberHats()) << endl; if (iter.hasNext()) { outstream << endl; indexNumber++; } } } void AppLaunchHelper::changeSpringModeScreen() { qInstallMessageHandler(MessageHandler::myMessageOutput); QDesktopWidget deskWid; int springScreen = settings->value("Mouse/SpringScreen", GlobalVariables::AntimicroSettings::defaultSpringScreen).toInt(); if (springScreen >= deskWid.screenCount()) { springScreen = -1; settings->setValue("Mouse/SpringScreen", GlobalVariables::AntimicroSettings::defaultSpringScreen); settings->sync(); } JoyButton::setSpringModeScreen(springScreen, GlobalVariables::JoyButton::springModeScreen); } void AppLaunchHelper::revertMouseThread() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::indirectStaticMouseThread(QThread::currentThread(), JoyButton::getStaticMouseEventTimer(), JoyButton::getMouseHelper()); } void AppLaunchHelper::changeMouseThread(QThread *thread) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::setStaticMouseThread(thread, JoyButton::getStaticMouseEventTimer(), JoyButton::getTestOldMouseTime(), GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE, JoyButton::getMouseHelper()); } void AppLaunchHelper::establishMouseTimerConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::establishMouseTimerConnections(); } AntiMicroSettings *AppLaunchHelper::getSettings() const { return settings; } AntiMicroX-antimicrox-2888bf6/src/applaunchhelper.h000066400000000000000000000032401377703515000223750ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef APPLAUNCHHELPER_H #define APPLAUNCHHELPER_H #include #include class AntiMicroSettings; class InputDevice; class QThread; class AppLaunchHelper : public QObject { Q_OBJECT public: explicit AppLaunchHelper(AntiMicroSettings *settings, bool graphical = false, QObject *parent = 0); void printControllerList(QMap *joysticks); AntiMicroSettings *getSettings() const; protected: void enablePossibleMouseSmoothing(); void establishMouseTimerConnections(); void changeMouseRefreshRate(); void changeSpringModeScreen(); void changeGamepadPollRate(); public slots: void initRunMethods(); void revertMouseThread(); void changeMouseThread(QThread *thread); private: AntiMicroSettings *settings; bool graphical; }; #endif // APPLAUNCHHELPER_H AntiMicroX-antimicrox-2888bf6/src/autoprofileinfo.cpp000066400000000000000000000117361377703515000227730ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "autoprofileinfo.h" #include "messagehandler.h" #include #include AutoProfileInfo::AutoProfileInfo(QString uniqueID, QString profileLocation, QString exe, bool active, bool partialTitle, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); setUniqueID(uniqueID); setProfileLocation(profileLocation); setExe(exe); setActive(active); setDefaultState(false); setPartialState(partialTitle); } AutoProfileInfo::AutoProfileInfo(QString uniqueID, QString profileLocation, bool active, bool partialTitle, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); setUniqueID(uniqueID); setProfileLocation(profileLocation); setActive(active); setDefaultState(false); setPartialState(partialTitle); } AutoProfileInfo::AutoProfileInfo(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); setActive(true); setDefaultState(false); setPartialState(false); } AutoProfileInfo::~AutoProfileInfo() { qInstallMessageHandler(MessageHandler::myMessageOutput); } void AutoProfileInfo::setUniqueID(QString uniqueID) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->uniqueID = uniqueID; } QString AutoProfileInfo::getUniqueID() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return uniqueID; } void AutoProfileInfo::setProfileLocation(QString profileLocation) { qInstallMessageHandler(MessageHandler::myMessageOutput); QFileInfo info(profileLocation); if ((profileLocation != this->profileLocation) && info.exists() && info.isReadable()) { this->profileLocation = profileLocation; } else if (profileLocation.isEmpty()) { this->profileLocation = ""; } } QString AutoProfileInfo::getProfileLocation() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return profileLocation; } void AutoProfileInfo::setExe(QString exe) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!exe.isEmpty()) { QFileInfo info(exe); if ((exe != this->exe) && info.exists() && info.isExecutable()) { this->exe = exe; } } else { this->exe = exe; } } QString AutoProfileInfo::getExe() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return exe; } void AutoProfileInfo::setWindowClass(QString windowClass) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->windowClass = windowClass; } QString AutoProfileInfo::getWindowClass() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return windowClass; } void AutoProfileInfo::setWindowName(QString winName) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->windowName = winName; } QString AutoProfileInfo::getWindowName() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return windowName; } void AutoProfileInfo::setActive(bool active) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->active = active; } bool AutoProfileInfo::isActive() { qInstallMessageHandler(MessageHandler::myMessageOutput); return active; } void AutoProfileInfo::setDefaultState(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->defaultState = value; } bool AutoProfileInfo::isCurrentDefault() { qInstallMessageHandler(MessageHandler::myMessageOutput); return defaultState; } void AutoProfileInfo::setDeviceName(QString name) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->deviceName = name; } QString AutoProfileInfo::getDeviceName() const { qInstallMessageHandler(MessageHandler::myMessageOutput); if (deviceName.isNull()) return ""; else return deviceName; } void AutoProfileInfo::setPartialState(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->partialState = value; } bool AutoProfileInfo::isPartialState() { qInstallMessageHandler(MessageHandler::myMessageOutput); return partialState; } AntiMicroX-antimicrox-2888bf6/src/autoprofileinfo.h000066400000000000000000000045251377703515000224360ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef AUTOPROFILEINFO_H #define AUTOPROFILEINFO_H #include class AutoProfileInfo : public QObject { Q_OBJECT public: explicit AutoProfileInfo(QString uniqueID, QString profileLocation, bool active, bool partialTitle, QObject *parent = nullptr); explicit AutoProfileInfo(QString uniqueID, QString profileLocation, QString exe, bool active, bool partialTitle, QObject *parent = nullptr); explicit AutoProfileInfo(QObject *parent = 0); ~AutoProfileInfo(); // void setGUID(QString guid); // QString getGUID() const; void setUniqueID(QString guid); QString getUniqueID() const; void setProfileLocation(QString profileLocation); QString getProfileLocation() const; void setExe(QString exe); QString getExe() const; void setWindowClass(QString windowClass); QString getWindowClass() const; void setWindowName(QString winName); QString getWindowName() const; void setActive(bool active); bool isActive(); void setDeviceName(QString name); QString getDeviceName() const; void setDefaultState(bool value); bool isCurrentDefault(); void setPartialState(bool value); bool isPartialState(); private: QString guid; QString uniqueID; QString profileLocation; QString exe; QString deviceName; QString windowClass; QString windowName; bool active; bool defaultState; bool partialState; }; Q_DECLARE_METATYPE(AutoProfileInfo *) #endif // AUTOPROFILEINFO_H AntiMicroX-antimicrox-2888bf6/src/autoprofilewatcher.cpp000066400000000000000000000542311377703515000234720ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "autoprofilewatcher.h" #include "antimicrosettings.h" #include "autoprofileinfo.h" #include "messagehandler.h" #include #include #include #include #include #include #include #include #if defined(WITH_X11) #include "x11extras.h" #endif AutoProfileWatcher *AutoProfileWatcher::_instance = nullptr; QTimer AutoProfileWatcher::checkWindowTimer; AutoProfileWatcher::AutoProfileWatcher(AntiMicroSettings *settings, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->settings = settings; allDefaultInfo = nullptr; currentApplication = ""; _instance = this; syncProfileAssignment(); connect(&(checkWindowTimer), &QTimer::timeout, _instance, &AutoProfileWatcher::runAppCheck); } AutoProfileWatcher::~AutoProfileWatcher() { if (checkWindowTimer.isActive()) { checkWindowTimer.stop(); disconnect(&(checkWindowTimer), &QTimer::timeout, _instance, nullptr); } _instance = nullptr; } AutoProfileWatcher *AutoProfileWatcher::getAutoProfileWatcherInstance() { return _instance; } void AutoProfileWatcher::disconnectWindowTimer() { checkWindowTimer.stop(); disconnect(&(checkWindowTimer), &QTimer::timeout, _instance, nullptr); } void AutoProfileWatcher::startTimer() { qInstallMessageHandler(MessageHandler::myMessageOutput); checkWindowTimer.start(CHECKTIME); } void AutoProfileWatcher::stopTimer() { qInstallMessageHandler(MessageHandler::myMessageOutput); checkWindowTimer.stop(); } void AutoProfileWatcher::runAppCheck() { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << qApp->applicationFilePath(); QString appLocation = QString(); QString baseAppFileName = QString(); getUniqeIDSetLocal().clear(); // Check whether program path needs to be parsed. Removes processing time // and need to run Linux specific code searching /proc. if (!getAppProfileAssignments().isEmpty()) { appLocation = findAppLocation(); qDebug() << "appLocation is " << appLocation << endl; } // More portable check for whether antimicrox is the current application // with focus. QWidget *focusedWidget = qApp->activeWindow(); if (focusedWidget != nullptr) qDebug() << "get active window of app" << endl; QString nowWindow = QString(); QString nowWindowClass = QString(); QString nowWindowName = QString(); long currentWindow = X11Extras::getInstance()->getWindowInFocus(); qDebug() << "getWindowInFocus: " << currentWindow << endl; if (currentWindow > 0) { long tempWindow = X11Extras::getInstance()->findParentClient(currentWindow); qDebug() << "findParentClient: " << tempWindow << endl; if (tempWindow > 0) currentWindow = tempWindow; nowWindow = QString::number(currentWindow); qDebug() << "number of window now: " << nowWindow << endl; nowWindowClass = X11Extras::getInstance()->getWindowClass(static_cast(currentWindow)); qDebug() << "class of window now: " << nowWindowClass << endl; nowWindowName = X11Extras::getInstance()->getWindowTitle(static_cast(currentWindow)); qDebug() << "title of window now: " << nowWindowName << endl; } qDebug() << "WINDOW CLASS: " << nowWindowClass; qDebug() << "WINDOW NAME: " << nowWindowName; qDebug() << "WINDOW IN FOCUS: " << nowWindow; bool checkForTitleChange = getWindowNameProfileAssignments().size() > 0; qDebug() << "window profile assignments size: " << getWindowNameProfileAssignments().size() << endl; qDebug() << "checkForTitleChange: " << checkForTitleChange; if (!focusedWidget && ((!nowWindow.isEmpty() && (nowWindow != currentApplication)) || (checkForTitleChange && (nowWindowName != currentAppWindowTitle)))) { currentApplication = nowWindow; currentAppWindowTitle = nowWindowName; Logger::LogDebug(QObject::tr("Active window changed to: Title = \"%1\", " "Class = \"%2\", Program = \"%3\" or \"%4\".") .arg(nowWindowName, nowWindowClass, appLocation, baseAppFileName)); QSet fullSet; if (!appLocation.isEmpty() && getAppProfileAssignments().contains(appLocation)) { QSet tempSet; tempSet = getAppProfileAssignments().value(appLocation).toSet(); fullSet.unite(tempSet); } else if (!baseAppFileName.isEmpty() && getAppProfileAssignments().contains(baseAppFileName)) { QSet tempSet; tempSet = getAppProfileAssignments().value(baseAppFileName).toSet(); fullSet.unite(tempSet); } if (!nowWindowClass.isEmpty() && getWindowClassProfileAssignments().contains(nowWindowClass)) { QSet tempSet; tempSet = getWindowClassProfileAssignments().value(nowWindowClass).toSet(); fullSet.unite(tempSet); } // part window title if (!nowWindowName.isEmpty()) { QHashIterator> iter(getWindowNameProfileAssignments()); while (iter.hasNext()) { iter.next(); bool hasOnePartName = false; QListIterator iterList(iter.value()); while (iterList.hasNext()) { AutoProfileInfo *autoInfo = iterList.next(); if (autoInfo->isPartialState()) { hasOnePartName = true; break; } } if (hasOnePartName) { qDebug() << "IT HAS A PARTIAL TITLE NAME"; if (nowWindowName.contains(iter.key())) { qDebug() << "WINDOW: \"" << nowWindowName << "\" includes \"" << iter.key() << "\""; QSet tempSet; QList list = iter.value(); tempSet = list.toSet(); fullSet = fullSet.unite(tempSet); } else { qDebug() << "WINDOW: \"" << nowWindowName << "\" doesn't include \"" << iter.key() << "\""; } } else { qDebug() << "IT HAS A FULL TITLE NAME"; if (iter.key() == nowWindowName) { qDebug() << "WINDOW: \"" << nowWindowName << "\" is equal to hash key: \"" << iter.key() << "\""; QSet tempSet; tempSet = getWindowNameProfileAssignments().value(nowWindowName).toSet(); fullSet = fullSet.unite(tempSet); } else { qDebug() << "WINDOW: \"" << nowWindowName << "\" is not equal to hash key: \"" << iter.key() << "\""; } } } } QHash highestMatchCount; QHash highestMatches; QSetIterator fullSetIter(fullSet); while (fullSetIter.hasNext()) { AutoProfileInfo *info = fullSetIter.next(); if (info->isActive()) { int numProps = 0; numProps += !info->getExe().isEmpty() ? 1 : 0; numProps += !info->getWindowClass().isEmpty() ? 1 : 0; numProps += !info->getWindowName().isEmpty() ? 1 : 0; int numMatched = 0; numMatched += (!info->getExe().isEmpty() && (info->getExe() == appLocation || info->getExe() == baseAppFileName)) ? 1 : 0; numMatched += (!info->getWindowClass().isEmpty() && info->getWindowClass() == nowWindowClass) ? 1 : 0; if (info->isPartialState()) { numMatched += (!info->getWindowName().isEmpty() && nowWindowName.contains(info->getWindowName())) ? 1 : 0; } else { numMatched += (!info->getWindowName().isEmpty() && info->getWindowName() == nowWindowName) ? 1 : 0; } if (numProps == numMatched && highestMatchCount.contains(info->getUniqueID())) { int currentHigh = highestMatchCount.value(info->getUniqueID()); if (numMatched > currentHigh) { highestMatchCount.insert(info->getUniqueID(), numMatched); highestMatches.insert(info->getUniqueID(), info); } } else if (numProps == numMatched && !highestMatchCount.contains(info->getUniqueID())) { highestMatchCount.insert(info->getUniqueID(), numMatched); highestMatches.insert(info->getUniqueID(), info); } } } QHashIterator highIter(highestMatches); while (highIter.hasNext()) { AutoProfileInfo *info = highIter.next().value(); getUniqeIDSetLocal().insert(info->getUniqueID()); emit foundApplicableProfile(info); } if ((!getDefaultProfileAssignments().isEmpty() || allDefaultInfo) && !focusedWidget) { if (allDefaultInfo != nullptr && allDefaultInfo->isActive() && !getUniqeIDSetLocal().contains("all")) { emit foundApplicableProfile(allDefaultInfo); } QHashIterator iter(getDefaultProfileAssignments()); while (iter.hasNext()) { iter.next(); AutoProfileInfo *info = iter.value(); if (info->isActive() && !getUniqeIDSetLocal().contains(info->getUniqueID())) { emit foundApplicableProfile(info); } } } } } void AutoProfileWatcher::syncProfileAssignment() { qInstallMessageHandler(MessageHandler::myMessageOutput); clearProfileAssignments(); currentApplication = ""; settings->getLock()->lock(); settings->beginGroup("DefaultAutoProfiles"); QString exe = QString(); QString uniqueID = QString(); QString profile = QString(); QString active = QString(); QString windowClass = QString(); QString windowName = QString(); QStringList registeredUniques = settings->value("Uniques", QStringList()).toStringList(); settings->endGroup(); QString allProfile = settings->value(QString("DefaultAutoProfileAll/Profile"), "all").toString(); QString allActive = settings->value(QString("DefaultAutoProfileAll/Active"), "0").toString(); // Handle overall Default profile assignment bool defaultActive = allActive == "1" ? true : false; if (defaultActive) { allDefaultInfo = new AutoProfileInfo("all", allProfile, defaultActive, 0, this); allDefaultInfo->setDefaultState(true); } // Handle device specific Default profile assignments QStringListIterator iter(registeredUniques); while (iter.hasNext()) { QString tempkey = iter.next(); QString uniqueID = QString(tempkey).replace("UniqueID", ""); QString profile = settings->value(QString("DefaultAutoProfile-%1/Profile").arg(uniqueID), "").toString(); QString active = settings->value(QString("DefaultAutoProfile-%1/Active").arg(uniqueID), "").toString(); QString exe = settings->value(QString("DefaultAutoProfile-%1/Exe").arg(uniqueID), "").toString(); QString partialTitle = settings->value(QString("DefaultAutoProfile-%1/PartialTitle").arg(uniqueID), "").toString(); QString windowClass = settings->value(QString("DefaultAutoProfile-%1/WindowClass").arg(uniqueID), "").toString(); QString windowName = settings->value(QString("DefaultAutoProfile-%1/WindowName").arg(uniqueID), "").toString(); // need to change when it's needed to add windowClass, title and partial name if (!uniqueID.isEmpty() && !profile.isEmpty()) { bool profileActive = active == "1" ? true : false; if (profileActive && uniqueID != "all") { AutoProfileInfo *info = new AutoProfileInfo(uniqueID, profile, profileActive, 0, this); info->setExe(exe); info->setWindowName(windowName); info->setWindowClass(windowClass); info->setPartialState(partialTitle == "1" ? true : false); info->setDefaultState(true); defaultProfileAssignments.insert(uniqueID, info); } } } settings->beginGroup("AutoProfiles"); bool quitSearch = false; for (int i = 1; !quitSearch; i++) { exe = settings->value(QString("AutoProfile%1Exe").arg(i), "").toString(); exe = QDir::toNativeSeparators(exe); convToUniqueIDAutoProfGroupSett(settings, QString("AutoProfile%1GUID").arg(i), QString("AutoProfile%1UniqueID").arg(i)); uniqueID = settings->value(QString("AutoProfile%1UniqueID").arg(i), "").toString(); profile = settings->value(QString("AutoProfile%1Profile").arg(i), "").toString(); active = settings->value(QString("AutoProfile%1Active").arg(i), 0).toString(); windowName = settings->value(QString("AutoProfile%1WindowName").arg(i), "").toString(); QString partialTitle = settings->value(QString("AutoProfile%1PartialTitle").arg(i), 0).toString(); bool partialTitleBool = partialTitle == "1" ? true : false; #ifdef Q_OS_UNIX windowClass = settings->value(QString("AutoProfile%1WindowClass").arg(i), "").toString(); #else windowClass.clear(); #endif // Check if all required elements exist. If not, assume that the end of the // list has been reached. if ((!exe.isEmpty() || !windowClass.isEmpty() || !windowName.isEmpty()) && !uniqueID.isEmpty()) { bool profileActive = active == "1" ? true : false; if (profileActive) { AutoProfileInfo *info = new AutoProfileInfo(uniqueID, profile, profileActive, partialTitleBool, this); if (!windowClass.isEmpty()) { info->setWindowClass(windowClass); QList templist; if (getWindowClassProfileAssignments().contains(windowClass)) templist = getWindowClassProfileAssignments().value(windowClass); templist.append(info); windowClassProfileAssignments.insert(windowClass, templist); } // partly watching is needed for window title if (!windowName.isEmpty()) { info->setWindowName(windowName); qDebug() << "WINDOW NAME IN AUTOPROFILEWATCHER: " << windowName; QList templist; QHashIterator> windows(getWindowNameProfileAssignments()); qDebug() << "getWindowNameProfileAssignments contains such elements like: "; while (windows.hasNext()) { windows.next(); qDebug() << windows.key(); } if (getWindowNameProfileAssignments().contains(windowName)) { qDebug() << "getWindowNameProfileAssignments contains " << windowName; templist = getWindowNameProfileAssignments().value(windowName); } else { qDebug() << "getWindowNameProfileAssignments doesn't contain " << windowName; } templist.append(info); windowNameProfileAssignments.insert(windowName, templist); } if (!exe.isEmpty()) { info->setExe(exe); QList templist; if (getAppProfileAssignments().contains(exe)) templist = getAppProfileAssignments().value(exe); templist.append(info); appProfileAssignments.insert(exe, templist); QString baseExe = QFileInfo(exe).fileName(); if (!baseExe.isEmpty() && baseExe != exe) { QList templist; if (getAppProfileAssignments().contains(baseExe)) templist = getAppProfileAssignments().value(baseExe); templist.append(info); appProfileAssignments.insert(baseExe, templist); } } } } else { quitSearch = true; } } settings->endGroup(); settings->getLock()->unlock(); } void AutoProfileWatcher::clearProfileAssignments() { qInstallMessageHandler(MessageHandler::myMessageOutput); QSet terminateProfiles; QListIterator> iterDelete(getAppProfileAssignments().values()); while (iterDelete.hasNext()) { QList templist = iterDelete.next(); terminateProfiles.unite(templist.toSet()); } appProfileAssignments.clear(); QListIterator> iterClassDelete(getWindowClassProfileAssignments().values()); while (iterClassDelete.hasNext()) { QList templist = iterClassDelete.next(); terminateProfiles.unite(templist.toSet()); } windowClassProfileAssignments.clear(); QListIterator> iterNameDelete(getWindowNameProfileAssignments().values()); while (iterNameDelete.hasNext()) { QList templist = iterNameDelete.next(); terminateProfiles.unite(templist.toSet()); } windowNameProfileAssignments.clear(); QSetIterator iterTerminate(terminateProfiles); while (iterTerminate.hasNext()) { AutoProfileInfo *info = iterTerminate.next(); if (info != nullptr) { delete info; info = nullptr; } } QListIterator iterDefaultsDelete(getDefaultProfileAssignments().values()); while (iterDefaultsDelete.hasNext()) { AutoProfileInfo *info = iterDefaultsDelete.next(); if (info != nullptr) { delete info; info = nullptr; } } defaultProfileAssignments.clear(); allDefaultInfo = nullptr; getUniqeIDSetLocal().clear(); } QString AutoProfileWatcher::findAppLocation() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString exepath = QString(); #ifdef WITH_X11 Window currentWindow = 0; int pid = 0; currentWindow = X11Extras::getInstance()->getWindowInFocus(); if (currentWindow) pid = X11Extras::getInstance()->getApplicationPid(currentWindow); if (pid > 0) exepath = X11Extras::getInstance()->getApplicationLocation(pid); #endif return exepath; } QList *AutoProfileWatcher::getCustomDefaults() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList *temp = new QList(); QHashIterator iter(getDefaultProfileAssignments()); while (iter.hasNext()) { iter.next(); temp->append(iter.value()); } return temp; } AutoProfileInfo *AutoProfileWatcher::getDefaultAllProfile() { qInstallMessageHandler(MessageHandler::myMessageOutput); return allDefaultInfo; } bool AutoProfileWatcher::isUniqueIDLocked(QString uniqueID) { qInstallMessageHandler(MessageHandler::myMessageOutput); return getUniqeIDSetLocal().contains(uniqueID); } QHash> const &AutoProfileWatcher::getAppProfileAssignments() { return appProfileAssignments; } QHash> const &AutoProfileWatcher::getWindowClassProfileAssignments() { return windowClassProfileAssignments; } QHash> const &AutoProfileWatcher::getWindowNameProfileAssignments() { return windowNameProfileAssignments; } QHash const &AutoProfileWatcher::getDefaultProfileAssignments() { return defaultProfileAssignments; } QSet &AutoProfileWatcher::getUniqeIDSetLocal() { return uniqueIDSet; } void AutoProfileWatcher::convToUniqueIDAutoProfGroupSett(QSettings *sett, QString guidAutoProfSett, QString uniqueAutoProfSett) { if (sett->contains(guidAutoProfSett)) { sett->setValue(uniqueAutoProfSett, sett->value(guidAutoProfSett)); sett->remove(guidAutoProfSett); } } AntiMicroX-antimicrox-2888bf6/src/autoprofilewatcher.h000066400000000000000000000055771377703515000231500ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef AUTOPROFILEWATCHER_H #define AUTOPROFILEWATCHER_H #include #include #include class AntiMicroSettings; class AutoProfileInfo; class QSettings; class AutoProfileWatcher : public QObject { Q_OBJECT public: explicit AutoProfileWatcher(AntiMicroSettings *settings, QObject *parent = nullptr); ~AutoProfileWatcher(); void startTimer(); void stopTimer(); static void disconnectWindowTimer(); static AutoProfileWatcher *getAutoProfileWatcherInstance(); QList *getCustomDefaults(); AutoProfileInfo *getDefaultAllProfile(); // bool isGUIDLocked(QString guid); bool isUniqueIDLocked(QString uniqueID); QHash> const &getAppProfileAssignments(); QHash> const &getWindowClassProfileAssignments(); QHash> const &getWindowNameProfileAssignments(); QHash const &getDefaultProfileAssignments(); static const int CHECKTIME = 500; // time in ms protected: QString findAppLocation(); void clearProfileAssignments(); void convToUniqueIDAutoProfGroupSett(QSettings *sett, QString guidAutoProfSett, QString uniqueAutoProfSett); signals: void foundApplicableProfile(AutoProfileInfo *info); public slots: void syncProfileAssignment(); private slots: void runAppCheck(); private: // QSet& getGuidSetLocal(); QSet &getUniqeIDSetLocal(); static AutoProfileWatcher *_instance; static QTimer checkWindowTimer; AntiMicroSettings *settings; QHash> appProfileAssignments; QHash> windowClassProfileAssignments; QHash> windowNameProfileAssignments; QHash defaultProfileAssignments; AutoProfileInfo *allDefaultInfo; QString currentApplication; QString currentAppWindowTitle; // QSet guidSet; QSet uniqueIDSet; }; #endif // AUTOPROFILEWATCHER_H AntiMicroX-antimicrox-2888bf6/src/axiseditdialog.cpp000066400000000000000000000664141377703515000225630ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "axiseditdialog.h" #include "ui_axiseditdialog.h" #include "antkeymapper.h" #include "axisvaluebox.h" #include "buttoneditdialog.h" #include "common.h" #include "event.h" #include "inputdevice.h" #include "joyaxis.h" #include "joycontrolstick.h" #include "messagehandler.h" #include "mousedialog/mouseaxissettingsdialog.h" #include "setaxisthrottledialog.h" #include "setjoystick.h" #include #include AxisEditDialog::AxisEditDialog(JoyAxis *axis, bool keypadUnlocked, QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::AxisEditDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); setAxisThrottleConfirm = new SetAxisThrottleDialog(axis, this); m_axis = axis; this->keypadUnlocked = keypadUnlocked; updateWindowTitleAxisName(); initialThrottleState = axis->getThrottle(); bool actAsTrigger = false; if ((initialThrottleState == static_cast(JoyAxis::PositiveThrottle)) || (initialThrottleState == static_cast(JoyAxis::PositiveHalfThrottle))) { actAsTrigger = true; } if (actAsTrigger) buildTriggerPresetsMenu(); ui->horizontalSlider->setValue(axis->getDeadZone()); ui->lineEdit->setText(QString::number(axis->getDeadZone())); ui->horizontalSlider_2->setValue(axis->getMaxZoneValue()); ui->lineEdit_2->setText(QString::number(axis->getMaxZoneValue())); JoyAxisButton *nButton = axis->getNAxisButton(); if (!nButton->getActionName().isEmpty()) { ui->nPushButton->setText(nButton->getActionName()); } else { ui->nPushButton->setText(nButton->getSlotsSummary()); } JoyAxisButton *pButton = axis->getPAxisButton(); if (!pButton->getActionName().isEmpty()) { ui->pPushButton->setText(pButton->getActionName()); } else { ui->pPushButton->setText(pButton->getSlotsSummary()); } int currentThrottle = axis->getThrottle(); if ((currentThrottle == static_cast(JoyAxis::NegativeThrottle)) || (currentThrottle == static_cast(JoyAxis::NegativeHalfThrottle))) { int tempindex = (currentThrottle == static_cast(JoyAxis::NegativeHalfThrottle)) ? 0 : 1; ui->comboBox_2->setCurrentIndex(tempindex); ui->nPushButton->setEnabled(true); ui->pPushButton->setEnabled(false); } else if ((currentThrottle == static_cast(JoyAxis::PositiveThrottle)) || (currentThrottle == static_cast(JoyAxis::PositiveHalfThrottle))) { int tempindex = (currentThrottle == static_cast(JoyAxis::PositiveThrottle)) ? 3 : 4; ui->comboBox_2->setCurrentIndex(tempindex); ui->pPushButton->setEnabled(true); ui->nPushButton->setEnabled(false); } ui->axisstatusBox->setDeadZone(axis->getDeadZone()); ui->axisstatusBox->setMaxZone(axis->getMaxZoneValue()); ui->axisstatusBox->setThrottle(axis->getThrottle()); ui->joyValueLabel->setText(QString::number(axis->getCurrentRawValue())); ui->axisstatusBox->setValue(axis->getCurrentRawValue()); if (!actAsTrigger) selectAxisCurrentPreset(); else selectTriggerPreset(); ui->axisNameLineEdit->setText(axis->getAxisName()); connect(ui->presetsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AxisEditDialog::implementPresets); connect(ui->horizontalSlider, &QSlider::valueChanged, this, &AxisEditDialog::updateDeadZoneBox); connect(ui->horizontalSlider, &QSlider::valueChanged, this, [this, axis](int deadzone) { ui->axisstatusBox->setDeadZone(axis, deadzone); }); connect(ui->horizontalSlider, &QSlider::valueChanged, axis, &JoyAxis::setDeadZone); connect(ui->horizontalSlider_2, &QSlider::valueChanged, this, &AxisEditDialog::updateMaxZoneBox); connect(ui->horizontalSlider_2, &QSlider::valueChanged, this, [this, axis](int deadzone) { ui->axisstatusBox->setMaxZone(axis, deadzone); }); connect(ui->horizontalSlider_2, &QSlider::valueChanged, axis, &JoyAxis::setMaxZoneValue); connect(ui->comboBox_2, static_cast(&QComboBox::currentIndexChanged), this, &AxisEditDialog::updateThrottleUi); connect(ui->comboBox_2, static_cast(&QComboBox::currentIndexChanged), this, &AxisEditDialog::presetForThrottleChange); connect(axis, &JoyAxis::moved, this, [this, axis](int value) { ui->axisstatusBox->setValue(axis, value); }); connect(axis, &JoyAxis::moved, this, &AxisEditDialog::updateJoyValue); connect(ui->lineEdit, &QLineEdit::textEdited, this, &AxisEditDialog::updateDeadZoneSlider); connect(ui->lineEdit_2, &QLineEdit::textEdited, this, &AxisEditDialog::updateMaxZoneSlider); connect(ui->nPushButton, &QPushButton::clicked, this, &AxisEditDialog::openAdvancedNDialog); connect(ui->pPushButton, &QPushButton::clicked, this, &AxisEditDialog::openAdvancedPDialog); connect(ui->mouseSettingsPushButton, &QPushButton::clicked, this, &AxisEditDialog::openMouseSettingsDialog); connect(ui->axisNameLineEdit, &QLineEdit::textEdited, axis, &JoyAxis::setAxisName); connect(axis, &JoyAxis::axisNameChanged, this, &AxisEditDialog::updateWindowTitleAxisName); connect(this, &AxisEditDialog::finished, this, &AxisEditDialog::checkFinalSettings); } // for tests AxisEditDialog::AxisEditDialog(QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::AxisEditDialog) { } AxisEditDialog::~AxisEditDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void AxisEditDialog::implementPresets(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool actAsTrigger = false; int currentThrottle = m_axis->getThrottle(); if ((currentThrottle == static_cast(JoyAxis::PositiveThrottle)) || (currentThrottle == static_cast(JoyAxis::PositiveHalfThrottle))) { actAsTrigger = true; } if (actAsTrigger) implementTriggerPresets(index); else implementAxisPresets(index); } void AxisEditDialog::implementAxisPresets(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *nbuttonslot = nullptr; JoyButtonSlot *pbuttonslot = nullptr; PadderCommon::lockInputDevices(); InputDevice *tempDevice = m_axis->getParentSet()->getInputDevice(); QMetaObject::invokeMethod(tempDevice, "haltServices", Qt::BlockingQueuedConnection); switch (index) { case 1: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); break; case 2: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); break; case 3: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); break; case 4: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); break; case 5: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up), Qt::Key_Up, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down), Qt::Key_Down, JoyButtonSlot::JoyKeyboard, this); break; case 6: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left), Qt::Key_Left, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right), Qt::Key_Right, JoyButtonSlot::JoyKeyboard, this); break; case 7: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W), Qt::Key_W, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S), Qt::Key_S, JoyButtonSlot::JoyKeyboard, this); break; case 8: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A), Qt::Key_A, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D), Qt::Key_D, JoyButtonSlot::JoyKeyboard, this); break; case 9: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); break; case 10: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); break; case 0: case 11: JoyAxisButton *nbutton = m_axis->getNAxisButton(); JoyAxisButton *pbutton = m_axis->getPAxisButton(); QMetaObject::invokeMethod(nbutton, "clearSlotsEventReset"); QMetaObject::invokeMethod(pbutton, "clearSlotsEventReset", Qt::BlockingQueuedConnection); refreshNButtonLabel(); refreshPButtonLabel(); nbutton->buildActiveZoneSummaryString(); pbutton->buildActiveZoneSummaryString(); break; } if (nbuttonslot != nullptr) { JoyAxisButton *button = m_axis->getNAxisButton(); QMetaObject::invokeMethod(button, "clearSlotsEventReset", Q_ARG(bool, false)); QMetaObject::invokeMethod(button, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, nbuttonslot->getSlotCode()), Q_ARG(int, nbuttonslot->getSlotCodeAlias()), Q_ARG(JoyButtonSlot::JoySlotInputAction, nbuttonslot->getSlotMode())); refreshNButtonLabel(); nbuttonslot->deleteLater(); } if (pbuttonslot != nullptr) { JoyAxisButton *button = m_axis->getPAxisButton(); QMetaObject::invokeMethod(button, "clearSlotsEventReset", Q_ARG(bool, false)); QMetaObject::invokeMethod(button, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, pbuttonslot->getSlotCode()), Q_ARG(int, pbuttonslot->getSlotCodeAlias()), Q_ARG(JoyButtonSlot::JoySlotInputAction, pbuttonslot->getSlotMode())); refreshPButtonLabel(); pbuttonslot->deleteLater(); } PadderCommon::unlockInputDevices(); } void AxisEditDialog::updateDeadZoneBox(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->lineEdit->setText(QString::number(value)); } void AxisEditDialog::updateMaxZoneBox(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->lineEdit_2->setText(QString::number(value)); } void AxisEditDialog::updateThrottleUi(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempthrottle = 0; if ((index == 0) || (index == 1)) { ui->nPushButton->setEnabled(true); ui->pPushButton->setEnabled(false); tempthrottle = (index == 0) ? static_cast(JoyAxis::NegativeHalfThrottle) : static_cast(JoyAxis::NegativeThrottle); } else if (index == 2) { ui->nPushButton->setEnabled(true); ui->pPushButton->setEnabled(true); tempthrottle = static_cast(JoyAxis::NormalThrottle); } else if ((index == 3) || (index == 4)) { ui->pPushButton->setEnabled(true); ui->nPushButton->setEnabled(false); tempthrottle = (index == 3) ? static_cast(JoyAxis::PositiveThrottle) : static_cast(JoyAxis::PositiveHalfThrottle); } m_axis->setThrottle(tempthrottle); ui->axisstatusBox->setThrottle(tempthrottle); } void AxisEditDialog::updateJoyValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->joyValueLabel->setText(QString::number(value)); } void AxisEditDialog::updateDeadZoneSlider(QString value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int temp = value.toInt(); if ((temp >= m_axis->getAxisMinCal()) && (temp <= m_axis->getAxisMaxCal())) { ui->horizontalSlider->setValue(temp); } } void AxisEditDialog::updateMaxZoneSlider(QString value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int temp = value.toInt(); if ((temp >= m_axis->getAxisMinCal()) && (temp <= m_axis->getAxisMaxCal())) { ui->horizontalSlider_2->setValue(temp); } } void AxisEditDialog::openAdvancedPDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ButtonEditDialog *dialog = new ButtonEditDialog( m_axis->getPAxisButton(), m_axis->getPAxisButton()->getParentSet()->getInputDevice(), keypadUnlocked, this); dialog->show(); connect(dialog, &ButtonEditDialog::finished, this, &AxisEditDialog::refreshPButtonLabel); connect(dialog, &ButtonEditDialog::finished, this, &AxisEditDialog::refreshPreset); } void AxisEditDialog::openAdvancedNDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ButtonEditDialog *dialog = new ButtonEditDialog( m_axis->getNAxisButton(), m_axis->getNAxisButton()->getParentSet()->getInputDevice(), keypadUnlocked, this); dialog->show(); connect(dialog, &ButtonEditDialog::finished, this, &AxisEditDialog::refreshNButtonLabel); connect(dialog, &ButtonEditDialog::finished, this, &AxisEditDialog::refreshPreset); } void AxisEditDialog::refreshNButtonLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->nPushButton->setText(m_axis->getNAxisButton()->getSlotsSummary()); } void AxisEditDialog::refreshPButtonLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->pPushButton->setText(m_axis->getPAxisButton()->getSlotsSummary()); } void AxisEditDialog::checkFinalSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_axis->getThrottle() != initialThrottleState) setAxisThrottleConfirm->exec(); } void AxisEditDialog::selectAxisCurrentPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *naxisbutton = m_axis->getNAxisButton(); QList *naxisslots = naxisbutton->getAssignedSlots(); JoyAxisButton *paxisbutton = m_axis->getPAxisButton(); QList *paxisslots = paxisbutton->getAssignedSlots(); if ((naxisslots->length() == 1) && (paxisslots->length() == 1)) { JoyButtonSlot *nslot = naxisslots->at(0); JoyButtonSlot *pslot = paxisslots->at(0); if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseRight)) { ui->presetsComboBox->setCurrentIndex(1); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseRight) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { ui->presetsComboBox->setCurrentIndex(2); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseUp) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseDown)) { ui->presetsComboBox->setCurrentIndex(3); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseDown) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseUp)) { ui->presetsComboBox->setCurrentIndex(4); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down))) { ui->presetsComboBox->setCurrentIndex(5); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right))) { ui->presetsComboBox->setCurrentIndex(6); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S))) { ui->presetsComboBox->setCurrentIndex(7); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D))) { ui->presetsComboBox->setCurrentIndex(8); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2))) { ui->presetsComboBox->setCurrentIndex(9); } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6))) { ui->presetsComboBox->setCurrentIndex(10); } else { ui->presetsComboBox->setCurrentIndex(0); } } else if ((naxisslots->length() == 0) && (paxisslots->length() == 0)) { ui->presetsComboBox->setCurrentIndex(11); } else { ui->presetsComboBox->setCurrentIndex(0); } } void AxisEditDialog::selectTriggerPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *paxisbutton = m_axis->getPAxisButton(); QList *paxisslots = paxisbutton->getAssignedSlots(); if (paxisslots->length() == 1) { JoyButtonSlot *pslot = paxisslots->at(0); if ((pslot->getSlotMode() == JoyButtonSlot::JoyMouseButton) && (pslot->getSlotCode() == JoyButtonSlot::MouseLB)) { ui->presetsComboBox->setCurrentIndex(1); } else if ((pslot->getSlotMode() == JoyButtonSlot::JoyMouseButton) && (pslot->getSlotCode() == JoyButtonSlot::MouseRB)) { ui->presetsComboBox->setCurrentIndex(2); } else { ui->presetsComboBox->setCurrentIndex(0); } } else if (paxisslots->length() == 0) { ui->presetsComboBox->setCurrentIndex(3); } else { ui->presetsComboBox->setCurrentIndex(0); } } void AxisEditDialog::implementTriggerPresets(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *pbuttonslot = nullptr; if (index == 1) { pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseLB, JoyButtonSlot::JoyMouseButton, this); } else if (index == 2) { pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseRB, JoyButtonSlot::JoyMouseButton, this); } else if (index == 3) { JoyAxisButton *nbutton = m_axis->getNAxisButton(); JoyAxisButton *pbutton = m_axis->getPAxisButton(); QMetaObject::invokeMethod(nbutton, "clearSlotsEventReset"); QMetaObject::invokeMethod(pbutton, "clearSlotsEventReset", Qt::BlockingQueuedConnection); refreshNButtonLabel(); refreshPButtonLabel(); } if (pbuttonslot != nullptr) { JoyAxisButton *nbutton = m_axis->getNAxisButton(); JoyAxisButton *pbutton = m_axis->getPAxisButton(); if (nbutton->getAssignedSlots()->length() > 0) { QMetaObject::invokeMethod(nbutton, "clearSlotsEventReset", Qt::BlockingQueuedConnection, Q_ARG(bool, false)); refreshNButtonLabel(); } QMetaObject::invokeMethod(pbutton, "clearSlotsEventReset", Q_ARG(bool, false)); QMetaObject::invokeMethod(pbutton, "setAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, pbuttonslot->getSlotCode()), Q_ARG(int, pbuttonslot->getSlotCodeAlias()), Q_ARG(JoyButtonSlot::JoySlotInputAction, pbuttonslot->getSlotMode())); refreshPButtonLabel(); pbuttonslot->deleteLater(); } } void AxisEditDialog::refreshPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); // Disconnect event associated with presetsComboBox so a change in the index does not // alter the axis buttons disconnect(ui->presetsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AxisEditDialog::implementPresets); selectAxisCurrentPreset(); // Reconnect the event connect(ui->presetsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AxisEditDialog::implementPresets); } void AxisEditDialog::openMouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->mouseSettingsPushButton->setEnabled(false); MouseAxisSettingsDialog *dialog = new MouseAxisSettingsDialog(m_axis, this); dialog->show(); connect(this, &AxisEditDialog::finished, dialog, &MouseAxisSettingsDialog::close); connect(dialog, &MouseAxisSettingsDialog::finished, this, &AxisEditDialog::enableMouseSettingButton); } void AxisEditDialog::enableMouseSettingButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->mouseSettingsPushButton->setEnabled(true); } void AxisEditDialog::updateWindowTitleAxisName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(tr("Set")).append(" "); if (!m_axis->getAxisName().isEmpty()) { temp.append(m_axis->getPartialName(false, true)); } else { temp.append(m_axis->getPartialName()); } if (m_axis->getParentSet()->getIndex() != 0) { int setIndex = m_axis->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = m_axis->getParentSet()->getName(); if (!setName.isEmpty()) temp.append(": ").append(setName); temp.append("]"); } setWindowTitle(temp); } void AxisEditDialog::buildAxisPresetsMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->presetsComboBox->clear(); ui->presetsComboBox->addItem(tr("")); ui->presetsComboBox->addItem(tr("Mouse (Horizontal)")); ui->presetsComboBox->addItem(tr("Mouse (Inverted Horizontal)")); ui->presetsComboBox->addItem(tr("Mouse (Vertical)")); ui->presetsComboBox->addItem(tr("Mouse (Inverted Vertical)")); ui->presetsComboBox->addItem(tr("Arrows: Up | Down")); ui->presetsComboBox->addItem(tr("Arrows: Left | Right")); ui->presetsComboBox->addItem(tr("Keys: W | S")); ui->presetsComboBox->addItem(tr("Keys: A | D")); ui->presetsComboBox->addItem(tr("NumPad: KP_8 | KP_2")); ui->presetsComboBox->addItem(tr("NumPad: KP_4 | KP_6")); ui->presetsComboBox->addItem(tr("None")); } void AxisEditDialog::buildTriggerPresetsMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->presetsComboBox->clear(); ui->presetsComboBox->addItem(tr("")); ui->presetsComboBox->addItem(tr("Left Mouse Button")); ui->presetsComboBox->addItem(tr("Right Mouse Button")); ui->presetsComboBox->addItem(tr("None")); } void AxisEditDialog::presetForThrottleChange(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(index); bool actAsTrigger = false; int currentThrottle = m_axis->getThrottle(); if ((currentThrottle == static_cast(JoyAxis::PositiveThrottle)) || (currentThrottle == static_cast(JoyAxis::PositiveHalfThrottle))) { actAsTrigger = true; } disconnect(ui->presetsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AxisEditDialog::implementPresets); if (actAsTrigger) { buildTriggerPresetsMenu(); selectTriggerPreset(); } else { buildAxisPresetsMenu(); selectAxisCurrentPreset(); } connect(ui->presetsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &AxisEditDialog::implementPresets); } AntiMicroX-antimicrox-2888bf6/src/axiseditdialog.h000066400000000000000000000043551377703515000222240ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef AXISEDITDIALOG_H #define AXISEDITDIALOG_H #include class JoyAxis; class SetAxisThrottleDialog; class QWidget; namespace Ui { class AxisEditDialog; } class AxisEditDialog : public QDialog { Q_OBJECT public: explicit AxisEditDialog(JoyAxis *axis, bool keypadUnlocked, QWidget *parent = 0); AxisEditDialog(QWidget *parent = 0); ~AxisEditDialog(); protected: void selectAxisCurrentPreset(); void selectTriggerPreset(); void buildTriggerPresetsMenu(); void buildAxisPresetsMenu(); private: Ui::AxisEditDialog *ui; JoyAxis *m_axis; bool keypadUnlocked; SetAxisThrottleDialog *setAxisThrottleConfirm; int initialThrottleState; private slots: void implementAxisPresets(int index); void implementTriggerPresets(int index); void implementPresets(int index); void presetForThrottleChange(int index); void updateDeadZoneBox(int value); void updateMaxZoneBox(int value); void updateThrottleUi(int index); void updateJoyValue(int value); void updateDeadZoneSlider(QString value); void updateMaxZoneSlider(QString value); void openAdvancedPDialog(); void openAdvancedNDialog(); void refreshPButtonLabel(); void refreshNButtonLabel(); void refreshPreset(); void checkFinalSettings(); void openMouseSettingsDialog(); void enableMouseSettingButton(); void updateWindowTitleAxisName(); }; #endif // AXISEDITDIALOG_H AntiMicroX-antimicrox-2888bf6/src/axiseditdialog.ui000066400000000000000000000347721377703515000224200ustar00rootroot00000000000000 AxisEditDialog 0 0 511 369 0 0 0 0 16777215 16777215 Axis false true 10 1 Presets: false false 12 12 Mouse (Horizontal) Mouse (Inverted Horizontal) Mouse (Vertical) Mouse (Inverted Vertical) Arrows: Up | Down Arrows: Left | Right Keys: W | S Keys: A | D NumPad: KP_8 | KP_2 NumPad: KP_4 | KP_6 None Qt::Vertical QSizePolicy::Fixed 20 20 10 10 10 0 0 100 16777215 false false Set the value to use as the limit for an axis. Useful for a worn out analog stick. 5 false Dead Zone: Set the value of the dead zone for an axis. 0 32737 100 1000 5000 5000 true Qt::Horizontal false false QSlider::NoTicks 1000 true 0 0 100 16777215 false false Set the value of the dead zone for an axis. 5 true false Set the value to use as the limit for an axis. Useful for a worn out analog stick. 0 32737 100 1000 32000 Qt::Horizontal QSlider::NoTicks 1000 Max Zone: [NO KEY] Throttle setting that determines the behavior of how to interpret an axis hold or release. 2 5 5 Negative Half Throttle Negative Throttle Normal Positive Throttle Positive Half Throttle [NO KEY] 0 0 0 25 16777215 25 10 0 0 Current Value: 0 4 0 0 Qt::Vertical QSizePolicy::Fixed 20 20 Name: axisNameLineEdit Specify the name of an axis. Mouse Settings Qt::Horizontal Qt::Horizontal QDialogButtonBox::Close false AxisValueBox QWidget
axisvaluebox.h
1
buttonBox accepted() AxisEditDialog accept() 248 254 157 274 buttonBox rejected() AxisEditDialog reject() 316 260 286 274
AntiMicroX-antimicrox-2888bf6/src/axisvaluebox.cpp000066400000000000000000000224271377703515000222770ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "axisvaluebox.h" #include "globalvariables.h" #include "joyaxis.h" #include "messagehandler.h" #include #include #include #include #include AxisValueBox::AxisValueBox(QWidget *parent) : QWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_axis = nullptr; m_deadZone = 0; m_maxZone = 0; joyValue = 0; m_throttle = 0; lboxstart = 0; lboxend = 0; rboxstart = 0; rboxend = 0; boxwidth = 0; boxheight = 0; singlewidth = 0; singleend = 0; } void AxisValueBox::setThrottle(int throttle) { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "throttle value at start of function setThrottle: " << throttle; if ((throttle <= static_cast(JoyAxis::PositiveHalfThrottle)) && (throttle >= static_cast(JoyAxis::NegativeHalfThrottle))) { qDebug() << "throttle variable has been set in setThrottle with: " << throttle; m_throttle = throttle; setValue(joyValue); } update(); } void AxisValueBox::setValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "Value for axis from value box at start is: " << value; qDebug() << "throttle variable has value: " << m_throttle; if ((value >= GlobalVariables::JoyAxis::AXISMIN) && (value <= GlobalVariables::JoyAxis::AXISMAX)) { qDebug() << "Value for axis from value box is between : " << GlobalVariables::JoyAxis::AXISMIN << " and " << GlobalVariables::JoyAxis::AXISMAX; switch (m_throttle) { case -2: this->joyValue = (value <= 0) ? value : (-value); break; case -1: this->joyValue = ((value + GlobalVariables::JoyAxis::AXISMIN) / 2); break; case 0: this->joyValue = value; break; case 1: this->joyValue = (value + GlobalVariables::JoyAxis::AXISMAX) / 2; break; case 2: this->joyValue = (value >= 0) ? value : (-value); break; } } update(); } void AxisValueBox::setValue(JoyAxis *axis, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_axis = axis; qDebug() << "Value for axis from value box at start is: " << value; qDebug() << "throttle variable has value: " << m_throttle; if ((value >= axis->getAxisMinCal()) && (value <= axis->getAxisMaxCal())) { qDebug() << "Value for axis from value box is between : " << axis->getAxisMinCal() << " and " << axis->getAxisMaxCal(); switch (m_throttle) { case -2: this->joyValue = (value <= 0) ? value : (-value); break; case -1: this->joyValue = ((value + axis->getAxisMinCal()) / 2); break; case 0: this->joyValue = value; break; case 1: this->joyValue = (value + axis->getAxisMaxCal()) / 2; break; case 2: this->joyValue = (value >= 0) ? value : (-value); break; } } update(); } void AxisValueBox::setDeadZone(int deadZone) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((deadZone >= GlobalVariables::JoyAxis::AXISMIN) && (deadZone <= GlobalVariables::JoyAxis::AXISMAX)) { m_deadZone = deadZone; } update(); } void AxisValueBox::setDeadZone(JoyAxis *axis, int deadZone) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_axis = axis; if ((deadZone >= axis->getAxisMinCal()) && (deadZone <= axis->getAxisMaxCal())) { m_deadZone = deadZone; } update(); } int AxisValueBox::getDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_deadZone; } void AxisValueBox::setMaxZone(int maxZone) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((maxZone >= GlobalVariables::JoyAxis::AXISMIN) && (maxZone <= GlobalVariables::JoyAxis::AXISMAX)) { m_maxZone = maxZone; } update(); } void AxisValueBox::setMaxZone(JoyAxis *axis, int maxZone) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_axis = axis; if ((maxZone >= axis->getAxisMinCal()) && (maxZone <= axis->getAxisMaxCal())) { m_maxZone = maxZone; } update(); } int AxisValueBox::getMaxZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_maxZone; } int AxisValueBox::getJoyValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return joyValue; } int AxisValueBox::getThrottle() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_throttle; } void AxisValueBox::resizeEvent(QResizeEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(event); boxwidth = (this->width() / 2) - 5; boxheight = this->height() - 4; lboxstart = 0; lboxend = lboxstart + boxwidth; rboxstart = lboxend + 10; rboxend = rboxstart + boxwidth; singlewidth = this->width(); singleend = lboxstart + singlewidth; } void AxisValueBox::paintEvent(QPaintEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(event); QPainter paint(this); paint.setPen(palette().base().color()); paint.setBrush(palette().base().color()); QBrush brush(palette().light().color()); if (m_throttle == 0) { qDrawShadeRect(&paint, lboxstart, 0, lboxend, height(), palette(), true, 2, 0, &brush); qDrawShadeRect(&paint, rboxstart, 0, rboxend, height(), palette(), true, 2, 0, &brush); } else { qDrawShadeRect(&paint, lboxstart, 0, singlewidth, height(), palette(), true, 2, 0, &brush); } QColor innerColor; if (abs(joyValue) <= m_deadZone) { innerColor = Qt::gray; } else if (abs(joyValue) >= m_maxZone) { innerColor = Qt::red; } else { innerColor = Qt::blue; } paint.setPen(innerColor); paint.setBrush(innerColor); int barwidth = (m_throttle == 0) ? boxwidth : singlewidth; int barlength = abs((barwidth - 2) * joyValue) / getMaxAxValue(); if (joyValue > 0) { paint.drawRect(((m_throttle == 0) ? rboxstart : lboxstart) + 2, 2, barlength, boxheight); } else if (joyValue < 0) { paint.drawRect(lboxstart + barwidth - 2 - barlength, 2, barlength, boxheight); } // Draw marker for deadZone int deadLine = abs((barwidth - 2) * m_deadZone) / getMaxAxValue(); int maxLine = abs((barwidth - 2) * m_maxZone) / getMaxAxValue(); paint.setPen(Qt::blue); brush.setColor(Qt::blue); QBrush maxBrush(Qt::red); if (m_throttle == static_cast(JoyAxis::NormalThrottle)) { qDrawPlainRect(&paint, rboxstart + 2 + deadLine, 2, 4, boxheight + 2, Qt::black, 1, &brush); qDrawPlainRect(&paint, lboxend - deadLine - 2, 2, 4, boxheight + 2, Qt::black, 1, &brush); paint.setPen(Qt::red); qDrawPlainRect(&paint, rboxstart + 2 + maxLine, 2, 4, boxheight + 2, Qt::black, 1, &maxBrush); qDrawPlainRect(&paint, lboxend - maxLine - 2, 2, 4, boxheight + 2, Qt::black, 1, &maxBrush); } else if ((m_throttle == static_cast(JoyAxis::PositiveThrottle)) || (m_throttle == static_cast(JoyAxis::PositiveHalfThrottle))) { qDrawPlainRect(&paint, lboxstart + deadLine - 2, 2, 4, boxheight + 2, Qt::black, 1, &brush); paint.setPen(Qt::red); qDrawPlainRect(&paint, lboxstart + maxLine, 2, 4, boxheight + 2, Qt::black, 1, &maxBrush); } else if ((m_throttle == static_cast(JoyAxis::NegativeThrottle)) || (m_throttle == static_cast(JoyAxis::NegativeHalfThrottle))) { qDrawPlainRect(&paint, singleend - deadLine - 2, 2, 4, boxheight + 2, Qt::black, 1, &brush); paint.setPen(Qt::red); qDrawPlainRect(&paint, singleend - maxLine, 2, 4, boxheight + 2, Qt::black, 1, &maxBrush); } } int AxisValueBox::getMaxAxValue() { bool axisDefined = false; if (m_axis != nullptr) axisDefined = true; return (axisDefined && (m_axis->getAxisMaxCal() != -1)) ? m_axis->getAxisMaxCal() : GlobalVariables::JoyAxis::AXISMAX; } int AxisValueBox::getMinAxValue() { bool axisDefined = false; if (m_axis != nullptr) axisDefined = true; return (axisDefined && (m_axis->getAxisMinCal() != -1)) ? m_axis->getAxisMinCal() : GlobalVariables::JoyAxis::AXISMIN; } AntiMicroX-antimicrox-2888bf6/src/axisvaluebox.h000066400000000000000000000035541377703515000217440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef AXISVALUEBOX_H #define AXISVALUEBOX_H #include class QResizeEvent; class QPaintEvent; class JoyAxis; class AxisValueBox : public QWidget { Q_OBJECT public: explicit AxisValueBox(QWidget *parent = nullptr); int getDeadZone(); int getMaxZone(); int getJoyValue(); int getThrottle(); int getMinAxValue(); int getMaxAxValue(); protected: virtual void resizeEvent(QResizeEvent *event); virtual void paintEvent(QPaintEvent *event); public slots: void setThrottle(int throttle); void setValue(int value); void setValue(JoyAxis *axis, int value); void setDeadZone(int deadZone); void setDeadZone(JoyAxis *axis, int deadZone); void setMaxZone(int maxZone); void setMaxZone(JoyAxis *axis, int deadZone); private: JoyAxis *m_axis; int m_deadZone; int m_maxZone; int joyValue; int m_throttle; int boxwidth; int boxheight; int lboxstart; int lboxend; int rboxstart; int rboxend; int singlewidth; int singleend; }; #endif // AXISVALUEBOX_H AntiMicroX-antimicrox-2888bf6/src/buttoneditdialog.cpp000066400000000000000000000577251377703515000231370ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "buttoneditdialog.h" #include "ui_buttoneditdialog.h" #include "advancebuttondialog.h" #include "inputdevice.h" #include "joybutton.h" #include "keyboard/virtualkeyboardmousewidget.h" #include "messagehandler.h" #include "quicksetdialog.h" #include "antkeymapper.h" #include "common.h" #include "event.h" #include "eventhandlerfactory.h" #include "inputdevice.h" #include "setjoystick.h" #include #include #include #include #include #include #include ButtonEditDialog *ButtonEditDialog::instance = nullptr; ButtonEditDialog::ButtonEditDialog(InputDevice *joystick, bool isNumKeypad, QWidget *parent) : QDialog(parent, Qt::Window) , helper() , ui(new Ui::ButtonEditDialog) { ui->setupUi(this); withoutQuickSetDialog = false; m_isNumKeypad = isNumKeypad; if (m_isNumKeypad) { setMinimumSize(844, 480); } setAttribute(Qt::WA_DeleteOnClose); setWindowTitle(tr("Choose your keyboard key")); update(); instance = this; qInstallMessageHandler(MessageHandler::myMessageOutput); this->joystick = joystick; lastJoyButton = nullptr; currentQuickDialog = nullptr; SetJoystick *currentset = joystick->getActiveSetJoystick(); currentset->release(); joystick->resetButtonDownCount(); setMinimumHeight(460); setAttribute(Qt::WA_DeleteOnClose); setWindowModality(Qt::WindowModal); ignoreRelease = false; qDebug() << "Thread in ButtonEditDialog"; PadderCommon::inputDaemonMutex.lock(); ui->virtualKeyMouseTabWidget->hide(); ui->virtualKeyMouseTabWidget->deleteLater(); ui->virtualKeyMouseTabWidget = new VirtualKeyboardMouseWidget(joystick, &helper, m_isNumKeypad, currentQuickDialog, nullptr, this); ui->verticalLayout->insertWidget(1, ui->virtualKeyMouseTabWidget); PadderCommon::inputDaemonMutex.unlock(); connect(qApp, &QApplication::focusChanged, this, &ButtonEditDialog::checkForKeyboardWidgetFocus); connect(ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::selectionCleared, this, &ButtonEditDialog::refreshSlotSummaryLabel); connect(this, &ButtonEditDialog::keyGrabbed, this, &ButtonEditDialog::processSlotAssignment); connect(this, &ButtonEditDialog::selectionCleared, this, &ButtonEditDialog::clearButtonSlots); connect(ui->toggleCheckBox, &QCheckBox::clicked, this, &ButtonEditDialog::changeToggleSetting); connect(ui->turboCheckBox, &QCheckBox::clicked, this, &ButtonEditDialog::changeTurboSetting); connect(ui->advancedPushButton, &QPushButton::clicked, this, &ButtonEditDialog::openAdvancedDialog); connect(this, &ButtonEditDialog::advancedDialogOpened, ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::establishVirtualKeyboardAdvancedSignalConnections); connect(this, &ButtonEditDialog::advancedDialogOpened, ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::establishVirtualMouseAdvancedSignalConnections); refreshForLastBtn(); } ButtonEditDialog::ButtonEditDialog(JoyButton *button, InputDevice *joystick, bool isNumKeypad, QWidget *parent) : QDialog(parent, Qt::Window) , helper() , ui(new Ui::ButtonEditDialog) { ui->setupUi(this); withoutQuickSetDialog = true; m_isNumKeypad = isNumKeypad; if (m_isNumKeypad) { setMinimumSize(844, 480); } setAttribute(Qt::WA_DeleteOnClose); setWindowTitle(tr("Choose your keyboard key")); update(); instance = this; qInstallMessageHandler(MessageHandler::myMessageOutput); lastJoyButton = button; this->joystick = joystick; currentQuickDialog = nullptr; SetJoystick *currentset = joystick->getActiveSetJoystick(); currentset->release(); joystick->resetButtonDownCount(); setMinimumHeight(460); setAttribute(Qt::WA_DeleteOnClose); setWindowModality(Qt::WindowModal); ignoreRelease = false; PadderCommon::inputDaemonMutex.lock(); ui->virtualKeyMouseTabWidget->hide(); ui->virtualKeyMouseTabWidget->deleteLater(); ui->virtualKeyMouseTabWidget = new VirtualKeyboardMouseWidget(joystick, &helper, m_isNumKeypad, currentQuickDialog, button, this); ui->verticalLayout->insertWidget(1, ui->virtualKeyMouseTabWidget); PadderCommon::inputDaemonMutex.unlock(); connect(qApp, &QApplication::focusChanged, this, &ButtonEditDialog::checkForKeyboardWidgetFocus); connect(ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::selectionCleared, this, &ButtonEditDialog::refreshSlotSummaryLabel); connect(this, &ButtonEditDialog::keyGrabbed, this, &ButtonEditDialog::processSlotAssignment); connect(this, &ButtonEditDialog::selectionCleared, this, &ButtonEditDialog::clearButtonSlots); // used to clear button sets connect(ui->toggleCheckBox, &QCheckBox::clicked, this, &ButtonEditDialog::changeToggleSetting); connect(ui->turboCheckBox, &QCheckBox::clicked, this, &ButtonEditDialog::changeTurboSetting); connect(ui->advancedPushButton, &QPushButton::clicked, this, &ButtonEditDialog::openAdvancedDialog); connect(this, &ButtonEditDialog::advancedDialogOpened, ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::establishVirtualKeyboardAdvancedSignalConnections); connect(this, &ButtonEditDialog::advancedDialogOpened, ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::establishVirtualMouseAdvancedSignalConnections); refreshForLastBtn(); } // for tests ButtonEditDialog::ButtonEditDialog(QWidget *parent) : QDialog(parent, Qt::Window) , helper() , ui(new Ui::ButtonEditDialog) { } ButtonEditDialog *ButtonEditDialog::getInstance() { return instance; } void ButtonEditDialog::checkForKeyboardWidgetFocus(QWidget *old, QWidget *now) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(old); Q_UNUSED(now); if (ui->virtualKeyMouseTabWidget->hasFocus() && ui->virtualKeyMouseTabWidget->isKeyboardTabVisible()) { grabKeyboard(); } else { releaseKeyboard(); } } ButtonEditDialog::~ButtonEditDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); instance = nullptr; delete ui; } void ButtonEditDialog::keyPressEvent(QKeyEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool ignore = false; // Ignore the following keys that might // trigger an event in QDialog::keyPressEvent switch (event->key()) { case Qt::Key_Escape: case Qt::Key_Right: case Qt::Key_Down: case Qt::Key_Up: case Qt::Key_Left: case Qt::Key_Enter: case Qt::Key_Return: { ignore = true; break; } default: break; } if (!ignore) QDialog::keyPressEvent(event); } void ButtonEditDialog::keyReleaseEvent(QKeyEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "It's keyrelease event"; if (ui->actionNameLineEdit->hasFocus() || ui->buttonNameLineEdit->hasFocus()) { QDialog::keyReleaseEvent(event); } else if (ui->virtualKeyMouseTabWidget->isKeyboardTabVisible()) { int controlcode = event->nativeScanCode(); int virtualactual = event->nativeVirtualKey(); BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); #if defined(WITH_X11) int finalvirtual = 0; int checkalias = 0; if (QApplication::platformName() == QStringLiteral("xcb")) { // Obtain group 1 X11 keysym. Removes effects from modifiers. finalvirtual = X11KeyCodeToX11KeySym(controlcode); #ifdef WITH_UINPUT if (handler->getIdentifier() == "uinput") { // Find Qt Key corresponding to X11 KeySym. Q_ASSERT(AntKeyMapper::getInstance()->hasNativeKeyMapper()); QtKeyMapperBase *x11KeyMapper = AntKeyMapper::getInstance()->getNativeKeyMapper(); Q_ASSERT(x11KeyMapper != nullptr); checkalias = x11KeyMapper->returnQtKey(finalvirtual); finalvirtual = AntKeyMapper::getInstance()->returnVirtualKey( checkalias); // Find corresponding Linux input key for the Qt key. } #endif #ifdef WITH_XTEST BACKEND_ELSE_IF(handler->getIdentifier() == "xtest") { // Check for alias against group 1 keysym. checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); } #endif } else { // Not running on xcb platform. finalvirtual = controlcode; checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); } #else int finalvirtual = 0; int checkalias = 0; if (QApplication::platformName() == QStringLiteral("xcb")) { finalvirtual = AntKeyMapper::getInstance()->returnVirtualKey(event->key()); checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); } else { // Not running on xcb platform. finalvirtual = controlcode; checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); } #endif if (!ignoreRelease && (event->modifiers() & Qt::ControlModifier) && (event->key() == Qt::Key_X)) { controlcode = 0; ignoreRelease = true; emit selectionCleared(); } else if (!ignoreRelease && (controlcode <= 0)) { controlcode = 0; } else if (ignoreRelease) { controlcode = 0; ignoreRelease = false; } if (controlcode > 0 && (checkalias > 0) && (finalvirtual > 0)) { JoyButtonSlot *tempslot = new JoyButtonSlot(finalvirtual, checkalias, JoyButtonSlot::JoyKeyboard, this); emit keyGrabbed(tempslot); } else if ((controlcode > 0) && (virtualactual > 0)) { JoyButtonSlot *tempslot = new JoyButtonSlot(virtualactual, JoyButtonSlot::JoyKeyboard, this); emit keyGrabbed(tempslot); } else { QDialog::keyReleaseEvent(event); } } else { QDialog::keyReleaseEvent(event); } } void ButtonEditDialog::refreshSlotSummaryLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastJoyButton != nullptr) ui->slotSummaryLabel->setText(lastJoyButton->getSlotsString().replace("&", "&&")); else ui->slotSummaryLabel->setText(tr("No button")); } void ButtonEditDialog::changeToggleSetting() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastJoyButton != nullptr) lastJoyButton->setToggle(ui->toggleCheckBox->isChecked()); else QMessageBox::information( this, tr("Last button"), tr("To change settings for last button, it must be at least one assignment from keyboard to gamepad")); } void ButtonEditDialog::changeTurboSetting() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastJoyButton != nullptr) lastJoyButton->setUseTurbo(ui->turboCheckBox->isChecked()); else QMessageBox::information( this, tr("Last button"), tr("To change settings of turbo for last button, it must be at least one assignment from keyboard to gamepad")); } void ButtonEditDialog::openAdvancedDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastJoyButton != nullptr) { if (lastJoyButton->getAssignedSlots()->count() > 0) { AdvanceButtonDialog *dialog = new AdvanceButtonDialog(lastJoyButton, this); dialog->show(); // Disconnect event to allow for placing slot to AdvanceButtonDialog disconnect(this, &ButtonEditDialog::keyGrabbed, nullptr, nullptr); disconnect(this, &ButtonEditDialog::selectionCleared, nullptr, nullptr); disconnect(this, &ButtonEditDialog::selectionFinished, nullptr, nullptr); connect(dialog, &AdvanceButtonDialog::finished, ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::establishVirtualKeyboardSingleSignalConnections); connect(dialog, &AdvanceButtonDialog::finished, ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::establishVirtualMouseSignalConnections); connect(dialog, &AdvanceButtonDialog::finished, this, &ButtonEditDialog::closedAdvancedDialog); connect(dialog, &AdvanceButtonDialog::turboButtonEnabledChange, this, &ButtonEditDialog::setTurboButtonEnabled); connect(this, &ButtonEditDialog::sendTempSlotToAdvanced, dialog, &AdvanceButtonDialog::placeNewSlot); connect(this, &ButtonEditDialog::keyGrabbed, dialog, &AdvanceButtonDialog::placeNewSlot); connect(this, &ButtonEditDialog::selectionCleared, dialog, &AdvanceButtonDialog::clearAllSlots); connect(ui->virtualKeyMouseTabWidget, static_cast( &VirtualKeyboardMouseWidget::selectionMade), dialog, &AdvanceButtonDialog::placeNewSlot); connect(ui->virtualKeyMouseTabWidget, static_cast(&VirtualKeyboardMouseWidget::selectionMade), this, &ButtonEditDialog::createTempSlot); connect(ui->virtualKeyMouseTabWidget, &VirtualKeyboardMouseWidget::selectionCleared, dialog, &AdvanceButtonDialog::clearAllSlots); connect(this, &ButtonEditDialog::finished, dialog, &AdvanceButtonDialog::close); emit advancedDialogOpened(); } else { QMessageBox::information(this, tr("No choice"), tr("Before you open window with advanced settins, you have to choice a key")); } } else { QMessageBox::information( this, tr("Last button"), tr("To open advanced dialog, it's needed to map at least one button from keyboard to gamepad")); } } void ButtonEditDialog::createTempSlot(int keycode, int alias) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *slot = new JoyButtonSlot(keycode, alias, JoyButtonSlot::JoyKeyboard, this); emit sendTempSlotToAdvanced(slot); } void ButtonEditDialog::checkTurboSetting(bool state) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastJoyButton != nullptr) { if (lastJoyButton->containsSequence()) { ui->turboCheckBox->setChecked(false); ui->turboCheckBox->setEnabled(false); } else { ui->turboCheckBox->setChecked(state); ui->turboCheckBox->setEnabled(true); } } } void ButtonEditDialog::setTurboButtonEnabled(bool state) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->turboCheckBox->setEnabled(state); } void ButtonEditDialog::closedAdvancedDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); refreshForLastBtn(); disconnect(ui->virtualKeyMouseTabWidget, static_cast(&VirtualKeyboardMouseWidget::selectionMade), this, nullptr); // Re-connect previously disconnected event connect(this, &ButtonEditDialog::keyGrabbed, this, &ButtonEditDialog::processSlotAssignment); connect(this, &ButtonEditDialog::selectionCleared, this, &ButtonEditDialog::clearButtonSlots); connect(this, &ButtonEditDialog::selectionCleared, this, &ButtonEditDialog::sendSelectionFinished); } void ButtonEditDialog::processSlotAssignment(JoyButtonSlot *tempslot) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (withoutQuickSetDialog) { invokeMethodLastBtn(lastJoyButton, &helper, "setAssignedSlot", tempslot->getSlotCode(), tempslot->getSlotCodeAlias(), -1, tempslot->getSlotMode(), false, false, Qt::QueuedConnection, Qt::QueuedConnection, Qt::QueuedConnection); } else { if ((currentQuickDialog == nullptr) && (!buttonEventInterval.isValid() || (buttonEventInterval.elapsed() > 1000))) { // for better security, force pausing for 1 sec between key presses, // because mapped joystick buttons and axes become keys too // it's good for oversensitive buttons and axes, which can // create QuickSetDialog windows many times for one key if (!buttonEventInterval.isValid()) buttonEventInterval.start(); else buttonEventInterval.restart(); currentQuickDialog = new QuickSetDialog(joystick, &helper, "setAssignedSlot", tempslot->getSlotCode(), tempslot->getSlotCodeAlias(), -1, tempslot->getSlotMode(), false, false, this); currentQuickDialog->show(); connect(currentQuickDialog, &QuickSetDialog::finished, this, &ButtonEditDialog::nullifyDialogPointer); } } tempslot->deleteLater(); } void ButtonEditDialog::clearButtonSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastJoyButton != nullptr) QMetaObject::invokeMethod(lastJoyButton, "clearSlotsEventReset", Q_ARG(bool, false)); else QMessageBox::information(this, tr("Last button"), tr("Slots for button couldn't be cleared, because there was not any set button from " "keyboard for gamepad. Map at least one button from keyboard to gamepad")); } void ButtonEditDialog::sendSelectionFinished() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit selectionFinished(); } void ButtonEditDialog::updateWindowTitleButtonName() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastJoyButton != nullptr) { QString temp = QString(tr("As last gamepad button has been set")) .append(" \"") .append(lastJoyButton->getPartialName(false, true)) .append("\" "); if (lastJoyButton->getParentSet()->getIndex() != 0) { int setIndex = lastJoyButton->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Index %1").arg(setIndex)); QString setName = lastJoyButton->getParentSet()->getName(); if (!setName.isEmpty()) temp.append(": ").append(setName); temp.append("]"); } setWindowTitle(temp); } else { setWindowTitle(tr("Choose your keyboard key")); } } void ButtonEditDialog::nullifyDialogPointer() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (currentQuickDialog != nullptr) { lastJoyButton = currentQuickDialog->getLastPressedButton(); currentQuickDialog = nullptr; emit buttonDialogClosed(); } refreshForLastBtn(); } void ButtonEditDialog::refreshForLastBtn() { if (lastJoyButton != nullptr) { ui->slotSummaryLabel->setText(lastJoyButton->getSlotsString()); updateWindowTitleButtonName(); ui->toggleCheckBox->setChecked(lastJoyButton->getToggleState()); ui->turboCheckBox->setChecked(lastJoyButton->isUsingTurbo()); if (!lastJoyButton->getActionName().isEmpty()) ui->actionNameLineEdit->setText(lastJoyButton->getActionName()); if (!lastJoyButton->getButtonName().isEmpty()) ui->buttonNameLineEdit->setText(lastJoyButton->getButtonName()); if (lastJoyButton != nullptr) { QListIterator iter(*(lastJoyButton->getAssignedSlots())); ui->virtualKeyMouseTabWidget->disableMouseSettingButton(); while (iter.hasNext()) { JoyButtonSlot *buttonslot = iter.next(); switch (buttonslot->getSlotMode()) { case JoyButtonSlot::JoyMouseMovement: case JoyButtonSlot::JoyMouseButton: ui->virtualKeyMouseTabWidget->enableMouseSettingButton(); break; default: break; } } } connect(ui->actionNameLineEdit, &QLineEdit::textEdited, lastJoyButton, &JoyButton::setActionName); connect(ui->buttonNameLineEdit, &QLineEdit::textEdited, lastJoyButton, &JoyButton::setButtonName); connect(lastJoyButton, &JoyButton::toggleChanged, ui->toggleCheckBox, &QCheckBox::setChecked); connect(lastJoyButton, &JoyButton::turboChanged, this, &ButtonEditDialog::checkTurboSetting); connect(lastJoyButton, &JoyButton::slotsChanged, this, &ButtonEditDialog::refreshSlotSummaryLabel); connect(lastJoyButton, &JoyButton::buttonNameChanged, this, &ButtonEditDialog::updateWindowTitleButtonName); } update(); } void ButtonEditDialog::invokeMethodLastBtn(JoyButton *lastJoyBtn, ButtonEditDialogHelper *helper, const char *invokeString, int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode, bool withClear, bool withTrue, Qt::ConnectionType connTypeForAlias, Qt::ConnectionType connTypeForNothing, Qt::ConnectionType connTypeForAll) { QPointer lastBtn = lastJoyBtn; if (helper != nullptr) helper = new ButtonEditDialogHelper(); QPointer btnEditDHelper = helper; if (lastJoyBtn != nullptr) { helper->setThisButton(lastJoyBtn); helper->moveToThread(lastJoyBtn->thread()); qDebug() << "Thread in QuickSetDialog"; if (withClear) QMetaObject::invokeMethod(lastJoyBtn, "clearSlotsEventReset", Q_ARG(bool, withTrue)); // when alias exists but not index if ((alias != -1) && (index == -1)) { QMetaObject::invokeMethod(helper, invokeString, connTypeForAlias, Q_ARG(int, code), Q_ARG(int, alias), Q_ARG(JoyButtonSlot::JoySlotInputAction, mode)); // when alias doesn't exists and index too } else if ((alias == -1) && (index == -1)) { QMetaObject::invokeMethod(helper, invokeString, connTypeForNothing, Q_ARG(int, code), Q_ARG(JoyButtonSlot::JoySlotInputAction, mode)); // when all exist (code, alias, index) } else { if (lastJoyBtn->isPartVDPad()) connTypeForAll = Qt::BlockingQueuedConnection; QMetaObject::invokeMethod(helper, invokeString, connTypeForAll, Q_ARG(int, code), Q_ARG(int, alias), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, mode)); } } if (lastBtn.isNull()) lastBtn.clear(); if (btnEditDHelper.isNull()) btnEditDHelper.clear(); } JoyButton *ButtonEditDialog::getLastJoyButton() { return lastJoyButton; } void ButtonEditDialog::setUpLastJoyButton(JoyButton *newButton) { lastJoyButton = newButton; } ButtonEditDialogHelper &ButtonEditDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/buttoneditdialog.h000066400000000000000000000066511377703515000225740ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BUTTONEDITDIALOGTWO_H #define BUTTONEDITDIALOGTWO_H #include #include "uihelpers/buttoneditdialoghelper.h" class JoyButton; class JoyButtonSlot; class QWidget; class QKeyEvent; class InputDevice; class QuickSetDialog; namespace Ui { class ButtonEditDialog; } class ButtonEditDialog : public QDialog { Q_OBJECT public: explicit ButtonEditDialog(JoyButton *button, InputDevice *joystick, bool isNumKeypad, QWidget *parent = nullptr); // called for chosen button explicit ButtonEditDialog(InputDevice *joystick, bool isNumKeypad, QWidget *parent = nullptr); // Accessed by pressing the "Quick Set" button ButtonEditDialog(QWidget *parent = 0); ~ButtonEditDialog(); static ButtonEditDialog *getInstance(); JoyButton *getLastJoyButton(); void setUpLastJoyButton(JoyButton *); void refreshForLastBtn(); void invokeMethodLastBtn(JoyButton *lastJoyBtn, ButtonEditDialogHelper *helper, const char *invokeString, int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode, bool withClear, bool withTrue, Qt::ConnectionType connTypeForAlias, Qt::ConnectionType connTypeForNothing, Qt::ConnectionType connTypeForAll); protected: virtual void keyReleaseEvent(QKeyEvent *event); virtual void keyPressEvent(QKeyEvent *event); private: ButtonEditDialogHelper helper; Ui::ButtonEditDialog *ui; ButtonEditDialogHelper &getHelperLocal(); QElapsedTimer buttonEventInterval; InputDevice *joystick; QuickSetDialog *currentQuickDialog; bool ignoreRelease; bool withoutQuickSetDialog; bool m_isNumKeypad; JoyButton *lastJoyButton; static ButtonEditDialog *instance; signals: void advancedDialogOpened(); void sendTempSlotToAdvanced(JoyButtonSlot *tempslot); void keyGrabbed(JoyButtonSlot *tempslot); void selectionCleared(); void selectionFinished(); void buttonDialogClosed(); private slots: void nullifyDialogPointer(); void refreshSlotSummaryLabel(); void changeToggleSetting(); void changeTurboSetting(); void openAdvancedDialog(); void closedAdvancedDialog(); void createTempSlot(int keycode, int alias); void checkTurboSetting(bool state); void setTurboButtonEnabled(bool state); void processSlotAssignment(JoyButtonSlot *tempslot); void clearButtonSlots(); void sendSelectionFinished(); void updateWindowTitleButtonName(); void checkForKeyboardWidgetFocus(QWidget *old, QWidget *now); }; #endif // BUTTONEDITDIALOGTWO_H AntiMicroX-antimicrox-2888bf6/src/buttoneditdialog.ui000066400000000000000000000210401377703515000227470ustar00rootroot00000000000000 ButtonEditDialog Qt::WindowModal 0 0 800 430 800 430 Dialog false false 0 0 1 To make a new assignment, press any keyboard key or click a button in the Keyboard or Mouse tab false Qt::AlignCenter true QTabWidget::South 0 false Placeholder Qt::Vertical QSizePolicy::Fixed 20 4 Enables a key press or release to only occur when a controller button is pressed. Toggle Qt::Horizontal QSizePolicy::Fixed 20 20 Enables rapid key presses and releases. Turbo controller. Turbo Qt::Horizontal QSizePolicy::Expanding 20 20 75 true Last keyboard/mouse button: Slots false 30 6 6 4 Na&me: buttonNameLineEdit Specify the name of a button. 20 4 Action: actionNameLineEdit Specify the action that will be performed in game while this button is being used. 50 Qt::Horizontal 4 Advanced .. Qt::Horizontal QDialogButtonBox::Close VirtualKeyboardMouseWidget QTabWidget
keyboard/virtualkeyboardmousewidget.h
1
buttonBox accepted() ButtonEditDialog accept() 366 422 157 274 buttonBox rejected() ButtonEditDialog reject() 434 422 286 274
AntiMicroX-antimicrox-2888bf6/src/calibration.cpp000066400000000000000000000622031377703515000220500ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "calibration.h" #include "ui_calibration.h" #include "globalvariables.h" #include "inputdevice.h" #include "joybuttontypes/joycontrolstickmodifierbutton.h" #include "joycontrolstick.h" #include "joytabwidget.h" #include "messagehandler.h" #include #include #include #include #include #include #include #include #include Calibration::Calibration(InputDevice *joystick, QWidget *parent) : QWidget(parent) , ui(new Ui::Calibration) , currentJoystick(joystick) , helper(currentJoystick->getActiveSetJoystick()->getJoyStick(0)) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose, true); setWindowTitle(tr("Calibration")); sumX = 0; sumY = 0; center_calibrated_x = 0; center_calibrated_y = 0; deadzone_calibrated_x = 0; deadzone_calibrated_y = 0; max_axis_val_x = 0; min_axis_val_x = 0; max_axis_val_y = 0; min_axis_val_y = 0; calibrated = false; QPointer controlstick = currentJoystick->getActiveSetJoystick()->getJoyStick(0); this->stick = controlstick.data(); calibrated = this->stick->wasCalibrated(); ui->Informations->setText(stick->getCalibrationSummary()); ui->resetBtn->setEnabled(calibrated); ui->saveBtn->setEnabled(false); controlstick.data()->getModifierButton()->establishPropertyUpdatedConnections(); helper.moveToThread(controlstick.data()->thread()); setProgressBars(0, 0); ui->stickStatusBoxWidget->setFocus(); ui->stickStatusBoxWidget->setStick(controlstick.data()); ui->stickStatusBoxWidget->update(); if (controlstick.isNull()) controlstick.clear(); QList sticksList = currentJoystick->getActiveSetJoystick()->getSticks().values(); QListIterator currStick(sticksList); while (currStick.hasNext()) { ui->axesBox->addItem(currStick.next()->getPartialName()); } connect(currentJoystick, &InputDevice::destroyed, this, &Calibration::close); connect(ui->saveBtn, &QPushButton::clicked, this, &Calibration::saveSettings); connect(ui->cancelBtn, &QPushButton::clicked, this, &Calibration::close); connect(ui->axesBox, static_cast(&QComboBox::currentIndexChanged), this, &Calibration::createAxesConnection); connect(ui->startButton, &QPushButton::clicked, this, &Calibration::startCalibration); connect(ui->resetBtn, &QPushButton::clicked, [this](bool clicked) { resetSettings(false, clicked); }); update(); } Calibration::~Calibration() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } /** * @brief Resets memory of all variables to default, updates window and shows message * @return Nothing */ void Calibration::resetSettings(bool silentReset, bool) { if (!silentReset) { QMessageBox msgBox; msgBox.setText(tr("Do you really want to reset settings of current axis?")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); switch (msgBox.exec()) { case QMessageBox::Yes: restoreCalValues(); ui->steps->clear(); break; case QMessageBox::No: break; default: break; } } else { restoreCalValues(); ui->steps->clear(); } } void Calibration::restoreCalValues() { sumX = 0; sumY = 0; center_calibrated_x = 0; center_calibrated_y = 0; deadzone_calibrated_x = 0; deadzone_calibrated_y = 0; max_axis_val_x = 0; min_axis_val_x = 0; max_axis_val_y = 0; min_axis_val_y = 0; x_es_val.clear(); y_es_val.clear(); joyAxisX->setAxisCenterCal(center_calibrated_x); joyAxisY->setAxisCenterCal(center_calibrated_y); joyAxisX->setAxisMinCal(GlobalVariables::JoyAxis::AXISMIN); joyAxisY->setAxisMinCal(GlobalVariables::JoyAxis::AXISMIN); joyAxisX->setAxisMaxCal(GlobalVariables::JoyAxis::AXISMAX); joyAxisY->setAxisMaxCal(GlobalVariables::JoyAxis::AXISMAX); joyAxisX->setDeadZone(GlobalVariables::JoyAxis::AXISDEADZONE); joyAxisY->setDeadZone(GlobalVariables::JoyAxis::AXISDEADZONE); joyAxisX->setMaxZoneValue(GlobalVariables::JoyAxis::AXISMAXZONE); joyAxisY->setMaxZoneValue(GlobalVariables::JoyAxis::AXISMAXZONE); stick->setDeadZone(GlobalVariables::JoyAxis::AXISDEADZONE); stick->setMaxZone(GlobalVariables::JoyAxis::AXISMAXZONE); stick->setCalibrationFlag(false); stick->setCalibrationSummary(QString()); ui->Informations->clear(); calibrated = false; ui->saveBtn->setEnabled(false); ui->resetBtn->setEnabled(false); ui->stickStatusBoxWidget->update(); update(); } /** * @brief Creates quadratic field in a case, when max value is not equal to negative min value. It always chooses less value * @param max value for X - positive value * @param min value for X - negative value * @param max value for Y - positive value * @param min value for Y - negative value * @return Nothing */ void Calibration::setQuadraticZoneCalibrated(int &max_axis_val_x, int &min_axis_val_x, int &max_axis_val_y, int &min_axis_val_y) { if (max_axis_val_x > abs(min_axis_val_x)) max_axis_val_x = abs(min_axis_val_x); else min_axis_val_x = -(max_axis_val_x); if (max_axis_val_y > abs(min_axis_val_y)) max_axis_val_y = abs(min_axis_val_y); else min_axis_val_y = -(max_axis_val_y); } /** * @brief Moves deadzone position after changing center position of axes * @return Moved deadzone position */ int Calibration::calibratedDeadZone(int center, int deadzone) { return (center + deadzone); } int Calibration::fakeMapFunc(const int &x) { return x; } void Calibration::summarizeValues(int &numbFromList, const int &mappednumb) { numbFromList += mappednumb; } void Calibration::getMinVal(int &numbFromList, const int &mappednumb) { if (numbFromList > mappednumb) numbFromList = mappednumb; } void Calibration::getMaxVal(int &numbFromList, const int &mappednumb) { if (numbFromList < mappednumb) numbFromList = mappednumb; } /** * @brief Prepares first step of calibration - finding center * @return nothing */ void Calibration::startCalibration() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool confirmed = true; if (stick->wasCalibrated()) { QMessageBox msgBox; msgBox.setText(tr("Calibration was saved for the preset. Do you really want to reset settings?")); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); switch (msgBox.exec()) { case QMessageBox::Ok: confirmed = true; ui->resetBtn->setEnabled(false); break; case QMessageBox::Cancel: confirmed = false; break; default: confirmed = true; break; } } else { center_calibrated_x = 0; center_calibrated_y = 0; deadzone_calibrated_x = 0; deadzone_calibrated_y = 0; min_axis_val_x = 0; min_axis_val_y = 0; max_axis_val_x = 0; max_axis_val_y = 0; x_es_val.clear(); y_es_val.clear(); } if ((joyAxisX != nullptr) && (joyAxisY != nullptr) && confirmed) { center_calibrated_x = 0; center_calibrated_y = 0; deadzone_calibrated_x = 0; deadzone_calibrated_y = 0; min_axis_val_x = 0; min_axis_val_y = 0; max_axis_val_x = 0; max_axis_val_y = 0; x_es_val.clear(); y_es_val.clear(); stick->setCalibrationFlag(false); calibrated = false; ui->steps->setText(tr("Place the joystick in the center position.\n\nIt's the part, where often you don't have to " "move. Just skip it in such situation.")); this->setWindowTitle(tr("Calibrating center")); ui->startButton->setText(tr("Start second step")); update(); QList xValues = x_es_val.values(); QFuture resX = QtConcurrent::mappedReduced(xValues, &Calibration::fakeMapFunc, &Calibration::summarizeValues); sumX = resX.result(); QList yValues = x_es_val.values(); QFuture resY = QtConcurrent::mappedReduced(yValues, &Calibration::fakeMapFunc, &Calibration::summarizeValues); sumY = resY.result(); if ((sumX != 0) && (sumY != 0)) { center_calibrated_x = sumX / x_es_val.count(); center_calibrated_y = sumY / y_es_val.count(); } else { center_calibrated_x = 0; center_calibrated_y = 0; } QString text = QString(); text.append(tr("\n\nCenter X: %1").arg(center_calibrated_x)); text.append(tr("\nCenter Y: %1").arg(center_calibrated_y)); ui->Informations->setText(text); this->text = text; x_es_val.clear(); y_es_val.clear(); sumX = 0; sumY = 0; update(); disconnect(ui->startButton, &QPushButton::clicked, this, nullptr); connect(ui->startButton, &QPushButton::clicked, this, &Calibration::startSecondStep); } } /** * @brief Prepares second step of calibration - moving into top-left corner - negative values * @return nothing */ void Calibration::startSecondStep() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((joyAxisX != nullptr) && (joyAxisY != nullptr)) { ui->steps->setText(tr("\nPlace the joystick in the top-left corner many times")); this->setWindowTitle(tr("Calibrating position")); update(); qDebug() << "X_ES_VAL: " << x_es_val.count(QString("-")); qDebug() << "Y_ES_VAL: " << y_es_val.count(QString("-")); if (enoughProb(x_es_val.count(QString("-")), y_es_val.count(QString("-")), QString("-"))) { int min_x = 0; int min_y = 0; QList xValues = x_es_val.values(QString("-")); QFuture resX = QtConcurrent::mappedReduced(xValues, &Calibration::fakeMapFunc, &Calibration::getMinVal); min_x = resX.result(); QList yValues = y_es_val.values(QString("-")); QFuture resY = QtConcurrent::mappedReduced(yValues, &Calibration::fakeMapFunc, &Calibration::getMinVal); min_y = resY.result(); min_axis_val_x = min_x; min_axis_val_y = min_y; QString text = ui->Informations->text(); text.append(tr("\n\nX: %1").arg(min_axis_val_x)); text.append(tr("\nY: %1").arg(min_axis_val_y)); ui->Informations->setText(text); this->text = text; x_es_val.clear(); y_es_val.clear(); sumX = 0; sumY = 0; update(); disconnect(ui->startButton, &QPushButton::clicked, this, nullptr); connect(ui->startButton, &QPushButton::clicked, this, &Calibration::startLastStep); } } } /** * @brief Prepares third step of calibration - moving into bottom-right corner - postive values * @return nothing */ void Calibration::startLastStep() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((joyAxisX != nullptr) && (joyAxisY != nullptr)) { ui->steps->setText(tr("\nPlace the joystick in the bottom-right corner")); this->setWindowTitle(tr("Calibrating position")); ui->startButton->setText(tr("Start final step")); update(); if (enoughProb(x_es_val.count(QString("+")), y_es_val.count(QString("+")), QString("+"))) { int max_x = 0; int max_y = 0; QList xValues = x_es_val.values(QString("+")); QFuture resX = QtConcurrent::mappedReduced(xValues, &Calibration::fakeMapFunc, &Calibration::getMaxVal); max_x = resX.result(); QList yValues = y_es_val.values(QString("+")); QFuture resY = QtConcurrent::mappedReduced(yValues, &Calibration::fakeMapFunc, &Calibration::getMaxVal); max_y = resY.result(); max_axis_val_x = max_x; max_axis_val_y = max_y; QString text2 = ui->Informations->text(); text2.append(tr("\n\nX: %1").arg(max_axis_val_x)); text2.append(tr("\nY: %1").arg(max_axis_val_y)); ui->Informations->setText(text2); this->text = text2; update(); setQuadraticZoneCalibrated(max_axis_val_x, min_axis_val_x, max_axis_val_y, min_axis_val_y); deadzone_calibrated_x = (max_axis_val_y + max_axis_val_x) / 4; deadzone_calibrated_y = (max_axis_val_y + max_axis_val_x) / 4; QString text3 = ui->Informations->text(); text3.append(tr("\n\nrange X: %1 - %2").arg(min_axis_val_x).arg(max_axis_val_x)); text3.append(tr("\nrange Y: %1 - %2").arg(min_axis_val_y).arg(max_axis_val_y)); text3.append(tr("\n\ndeadzone X: %1").arg(deadzone_calibrated_x)); text3.append(tr("\ndeadzone Y: %1").arg(deadzone_calibrated_y)); ui->Informations->setText(text3); this->text = text3; if (stick != nullptr) { ui->saveBtn->setEnabled(true); } ui->steps->setText(tr("\n---Calibration done!---\n")); ui->startButton->setText(tr("Start calibration")); this->setWindowTitle(tr("Calibration")); update(); x_es_val.clear(); y_es_val.clear(); sumX = 0; sumY = 0; disconnect(ui->startButton, &QPushButton::clicked, this, nullptr); connect(ui->startButton, &QPushButton::clicked, this, &Calibration::startCalibration); } } } /** * @brief Updates variables contents and shows message * @return nothing */ void Calibration::saveSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((joyAxisX != nullptr) && (joyAxisY != nullptr)) { joyAxisX->setAxisCenterCal(center_calibrated_x); joyAxisY->setAxisCenterCal(center_calibrated_y); joyAxisX->setDeadZone(deadzone_calibrated_x); joyAxisY->setDeadZone(deadzone_calibrated_y); stick->setDeadZone(deadzone_calibrated_x); joyAxisX->setAxisMinCal(min_axis_val_x); joyAxisY->setAxisMinCal(min_axis_val_y); joyAxisX->setAxisMaxCal(max_axis_val_x); joyAxisY->setAxisMaxCal(max_axis_val_y); joyAxisX->setMaxZoneValue(max_axis_val_x); joyAxisY->setMaxZoneValue(max_axis_val_y); stick->setMaxZone(max_axis_val_x); calibrated = true; stick->setCalibrationFlag(true); stick->setCalibrationSummary(this->text); ui->resetBtn->setEnabled(true); ui->saveBtn->setEnabled(false); ui->stickStatusBoxWidget->update(); update(); QMessageBox::information(this, tr("Save"), tr("Calibration values have been saved")); } } /** * @brief checks whether axes were moved at least 5 times in both ways. If not, it shows a message * @param counts of ax X moving values * @param counts of ax Y moving values * @return if counts of values for X and Y axes were greater than 4 */ bool Calibration::enoughProb(int x_count, int y_count, QString character) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool enough = true; if ((x_count < 5) || (y_count < 5)) { if (character == QString("-")) { enough = false; QMessageBox::information(this, tr("Dead zone calibration"), tr("You have to move axes to the top-left corner at least five times.")); } else if (character == QString("+")) { enough = false; QMessageBox::information(this, tr("Dead zone calibration"), tr("You have to move axes to the bottom-right corner at least five times.")); } } return enough; } /** * @brief it's a slot of moving ax Y. Counts positive and negative values for later comparisions * @param place for sign "+" or "-". Depends on we want to find max value or min value for ax * @param list of moving ax values in positive and negative ways * @return min value if sign was "-" or max value if sign was "+" */ int Calibration::chooseMinMax(QString min_max_sign, QList ax_values) { qInstallMessageHandler(MessageHandler::myMessageOutput); int min_max = 0; foreach (int val, ax_values) { if (min_max_sign == QString("+")) { if (min_max < val) min_max = val; } else { if (min_max > val) min_max = val; } } return min_max; } /** * @brief it's a slot of moving ax X. Counts positive and negative values for later comparisions * @param value of moving ax * @return nothing */ void Calibration::checkX(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value > 0) { if (x_es_val.count(QString("+")) <= 100) x_es_val.insert(QString("+"), value); } else if (value < 0) { if (x_es_val.count(QString("-")) <= 100) x_es_val.insert(QString("-"), value); } axisBarX->setValue(value); update(); } /** * @brief it's a slot of moving ax Y. Counts positive and negative values for later comparisions * @param value of moving ax * @return nothing */ void Calibration::checkY(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value > 0) { if (y_es_val.count(QString("+")) <= 100) y_es_val.insert(QString("+"), value); } else if (value < 0) { if (y_es_val.count(QString("-")) <= 100) y_es_val.insert(QString("-"), value); } axisBarY->setValue(value); update(); } /** * @brief Refreshes list of sticks, which is below input devices list * @return nothing */ void Calibration::updateAxesBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->axesBox->clear(); QList sticksList = currentJoystick->getActiveSetJoystick()->getSticks().values(); QListIterator currStick(sticksList); while (currStick.hasNext()) { ui->axesBox->addItem(currStick.next()->getPartialName()); } update(); } /** * @brief Initializes widget for moving axes (animations) and changes storing data for variables * @return nothing */ void Calibration::createAxesConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ui->saveBtn->isEnabled()) { QMessageBox msgBox; msgBox.setText(tr("Do you want to save calibration of current axis?")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); switch (msgBox.exec()) { case QMessageBox::Yes: saveSettings(); break; case QMessageBox::No: break; default: break; } } while (!ui->progressBarsLayout->isEmpty()) { QLayout *hb = ui->progressBarsLayout->takeAt(0)->layout(); while (!hb->isEmpty()) { QWidget *w = hb->takeAt(0)->widget(); delete w; } delete hb; } update(); QPointer controlstick = currentJoystick->getActiveSetJoystick()->getJoyStick(ui->axesBox->currentIndex()); this->stick = controlstick.data(); center_calibrated_x = controlstick->getAxisX()->getAxisCenterCal(); center_calibrated_y = controlstick->getAxisY()->getAxisCenterCal(); deadzone_calibrated_x = controlstick->getAxisX()->getDeadZone(); deadzone_calibrated_y = controlstick->getAxisY()->getDeadZone(); min_axis_val_x = controlstick->getAxisX()->getAxisMinCal(); min_axis_val_y = controlstick->getAxisY()->getAxisMinCal(); max_axis_val_x = controlstick->getAxisX()->getAxisMaxCal(); max_axis_val_y = controlstick->getAxisY()->getAxisMaxCal(); calibrated = controlstick->wasCalibrated(); text = controlstick->getCalibrationSummary(); if (calibrated) ui->resetBtn->setEnabled(true); else ui->resetBtn->setEnabled(false); controlstick.data()->getModifierButton()->establishPropertyUpdatedConnections(); helper.moveToThread(controlstick.data()->thread()); ui->stickStatusBoxWidget->setStick(controlstick.data()); ui->stickStatusBoxWidget->update(); setProgressBars(controlstick.data()); update(); if (controlstick.isNull()) controlstick.clear(); } /** * @brief Creates progress bars for axes and creates connections * @param pointer to stick * @return nothing */ void Calibration::setProgressBars(JoyControlStick *controlstick) { qInstallMessageHandler(MessageHandler::myMessageOutput); joyAxisX = controlstick->getAxisX(); joyAxisY = controlstick->getAxisY(); calibrated = controlstick->wasCalibrated(); ui->Informations->setText(controlstick->getCalibrationSummary()); if ((joyAxisX != nullptr) && (joyAxisY != nullptr)) { QHBoxLayout *hbox = new QHBoxLayout(); QHBoxLayout *hbox2 = new QHBoxLayout(); QLabel *axisLabel = new QLabel(); QLabel *axisLabel2 = new QLabel(); axisLabel->setText(tr("Axis %1").arg(joyAxisX->getRealJoyIndex())); axisLabel2->setText(tr("Axis %1").arg(joyAxisY->getRealJoyIndex())); axisBarX = new QProgressBar(); axisBarY = new QProgressBar(); axisBarX->setMinimum(GlobalVariables::JoyAxis::AXISMIN); axisBarX->setMaximum(GlobalVariables::JoyAxis::AXISMAX); axisBarX->setFormat("%v"); axisBarX->setValue(joyAxisX->getCurrentRawValue()); axisBarY->setMinimum(GlobalVariables::JoyAxis::AXISMIN); axisBarY->setMaximum(GlobalVariables::JoyAxis::AXISMAX); axisBarY->setFormat("%v"); axisBarY->setValue(joyAxisY->getCurrentRawValue()); hbox->addWidget(axisLabel); hbox->addWidget(axisBarX); hbox->addSpacing(10); hbox2->addWidget(axisLabel2); hbox2->addWidget(axisBarY); hbox2->addSpacing(10); ui->progressBarsLayout->addLayout(hbox); ui->progressBarsLayout->addLayout(hbox2); connect(joyAxisX, &JoyAxis::moved, this, &Calibration::checkX); connect(joyAxisY, &JoyAxis::moved, this, &Calibration::checkY); } update(); } /** * @brief Creates progress bars for axes and creates connections * @param device number * @param joystick number * @param stick number * @return nothing */ void Calibration::setProgressBars(int setJoyNr, int stickNr) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStick *controlstick = currentJoystick->getActiveSetJoystick()->getJoyStick(stickNr); // helper.moveToThread(controlstick->thread()); joyAxisX = controlstick->getAxisX(); joyAxisY = controlstick->getAxisY(); calibrated = controlstick->wasCalibrated(); ui->Informations->setText(controlstick->getCalibrationSummary()); if ((joyAxisX != nullptr) && (joyAxisY != nullptr)) { QHBoxLayout *hbox = new QHBoxLayout(); QHBoxLayout *hbox2 = new QHBoxLayout(); QLabel *axisLabel = new QLabel(); QLabel *axisLabel2 = new QLabel(); axisLabel->setText(tr("Axis %1").arg(joyAxisX->getRealJoyIndex())); axisLabel2->setText(tr("Axis %1").arg(joyAxisY->getRealJoyIndex())); axisBarX = new QProgressBar(); axisBarY = new QProgressBar(); axisBarX->setMinimum(GlobalVariables::JoyAxis::AXISMIN); axisBarX->setMaximum(GlobalVariables::JoyAxis::AXISMAX); axisBarX->setFormat("%v"); axisBarX->setValue(joyAxisX->getCurrentRawValue()); axisBarY->setMinimum(GlobalVariables::JoyAxis::AXISMIN); axisBarY->setMaximum(GlobalVariables::JoyAxis::AXISMAX); axisBarY->setFormat("%v"); axisBarY->setValue(joyAxisY->getCurrentRawValue()); hbox->addWidget(axisLabel); hbox->addWidget(axisBarX); hbox->addSpacing(10); hbox2->addWidget(axisLabel2); hbox2->addWidget(axisBarY); hbox2->addSpacing(10); ui->progressBarsLayout->addLayout(hbox); ui->progressBarsLayout->addLayout(hbox2); connect(joyAxisX, &JoyAxis::moved, this, &Calibration::checkX); connect(joyAxisY, &JoyAxis::moved, this, &Calibration::checkY); } update(); } AntiMicroX-antimicrox-2888bf6/src/calibration.h000066400000000000000000000055011377703515000215130ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CALIBRATION_H #define CALIBRATION_H #include "joycontrolstickeditdialog.h" #include #include class JoyControlStick; class InputDevice; namespace Ui { class Calibration; } class Calibration : public QWidget { Q_OBJECT public: explicit Calibration(InputDevice *joystick, QWidget *parent = 0); ~Calibration(); int chooseMinMax(QString min_max_sign, QList ax_values); void setQuadraticZoneCalibrated(int &max_axis_val_x, int &min_axis_val_x, int &max_axis_val_y, int &min_axis_val_y); protected: void setProgressBars(int setJoyNr, int stickNr); void setProgressBars(JoyControlStick *controlstick); void updateAxesBox(); void restoreCalValues(); bool enoughProb(int x_count, int y_count, QString character); int calibratedDeadZone(int center, int deadzone); private: static int fakeMapFunc(const int &x); static void summarizeValues(int &numbFromList, const int &mappednumb); static void getMinVal(int &numbFromList, const int &mappednumb); static void getMaxVal(int &numbFromList, const int &mappednumb); Ui::Calibration *ui; JoyControlStick *stick; InputDevice *currentJoystick; JoyControlStickEditDialogHelper helper; JoyAxis *joyAxisX; JoyAxis *joyAxisY; QProgressBar *axisBarX; QProgressBar *axisBarY; QMultiHash x_es_val; QMultiHash y_es_val; int center_calibrated_x; int center_calibrated_y; int max_axis_val_x; int min_axis_val_x; int max_axis_val_y; int min_axis_val_y; int deadzone_calibrated_x; int deadzone_calibrated_y; int sumX; int sumY; bool calibrated; QString text; public slots: void saveSettings(); void checkX(int value); void checkY(int value); void createAxesConnection(); void startCalibration(); void startSecondStep(); void startLastStep(); protected slots: void resetSettings(bool silentReset, bool clicked = false); signals: void deadZoneChanged(int value); void propertyUpdated(); }; #endif // CALIBRATION_H AntiMicroX-antimicrox-2888bf6/src/calibration.ui000066400000000000000000000142671377703515000217120ustar00rootroot00000000000000 Calibration 0 0 700 800 700 600 Form 0 0 300 300 16777215 16777215 0 0 200 200 Start calibration 100 100 Qt::Vertical 20 40 Qt::Vertical QSizePolicy::Fixed 20 20 Sticks: Qt::Vertical 20 40 Reset settings Qt::Horizontal 40 20 Cancel Save JoyControlStickStatusBox QWidget
joycontrolstickstatusbox.h
1
AntiMicroX-antimicrox-2888bf6/src/capturedwindowinfodialog.cpp000066400000000000000000000113331377703515000246520ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "capturedwindowinfodialog.h" #include "ui_capturedwindowinfodialog.h" #include "messagehandler.h" #include #include #include #include "x11extras.h" CapturedWindowInfoDialog::CapturedWindowInfoDialog(long window, QWidget *parent) : QDialog(parent) , ui(new Ui::CapturedWindowInfoDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); selectedMatch = WindowNone; X11Extras *info = X11Extras::getInstance(); ui->winPathChoiceComboBox->setVisible(false); bool setRadioDefault = false; fullWinPath = false; winClass = info->getWindowClass(static_cast(window)); ui->winClassLabel->setText(winClass); if (winClass.isEmpty()) { ui->winClassCheckBox->setEnabled(false); ui->winClassCheckBox->setChecked(false); } else { ui->winClassCheckBox->setChecked(true); setRadioDefault = true; } ui->winPathChoiceComboBox->setVisible(false); winName = info->getWindowTitle(static_cast(window)); ui->winTitleLabel->setText(winName); if (winName.isEmpty()) { ui->winTitleCheckBox->setEnabled(false); ui->winTitleCheckBox->setChecked(false); } else if (!setRadioDefault) { ui->winTitleCheckBox->setChecked(true); setRadioDefault = true; } ui->winPathLabel->clear(); int pid = info->getApplicationPid(static_cast(window)); if (pid > 0) { QString exepath = X11Extras::getInstance()->getApplicationLocation(pid); if (!exepath.isEmpty()) { ui->winPathLabel->setText(exepath); winPath = exepath; if (!setRadioDefault) ui->winTitleCheckBox->setChecked(true); } else { ui->winPathCheckBox->setEnabled(false); ui->winPathCheckBox->setChecked(false); } } else { ui->winPathCheckBox->setEnabled(false); ui->winPathCheckBox->setChecked(false); } if (winClass.isEmpty() && winName.isEmpty() && winPath.isEmpty()) { QPushButton *button = ui->buttonBox->button(QDialogButtonBox::Ok); button->setEnabled(false); } connect(this, &CapturedWindowInfoDialog::accepted, this, &CapturedWindowInfoDialog::populateOption); } CapturedWindowInfoDialog::~CapturedWindowInfoDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void CapturedWindowInfoDialog::populateOption() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ui->winClassCheckBox->isChecked()) selectedMatch = selectedMatch | WindowClass; if (ui->winTitleCheckBox->isChecked()) selectedMatch = selectedMatch | WindowName; if (ui->winPathCheckBox->isChecked()) { selectedMatch = selectedMatch | WindowPath; if (ui->winPathChoiceComboBox->currentIndex() == 0) fullWinPath = true; else fullWinPath = false; } } CapturedWindowInfoDialog::CapturedWindowOption CapturedWindowInfoDialog::getSelectedOptions() { qInstallMessageHandler(MessageHandler::myMessageOutput); return selectedMatch; } QString CapturedWindowInfoDialog::getWindowClass() { qInstallMessageHandler(MessageHandler::myMessageOutput); return winClass; } QString CapturedWindowInfoDialog::getWindowName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return winName; } QString CapturedWindowInfoDialog::getWindowPath() { qInstallMessageHandler(MessageHandler::myMessageOutput); return winPath; } bool CapturedWindowInfoDialog::useFullWindowPath() { qInstallMessageHandler(MessageHandler::myMessageOutput); return fullWinPath; } AntiMicroX-antimicrox-2888bf6/src/capturedwindowinfodialog.h000066400000000000000000000034431377703515000243220ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UNIXWINDOWINFODIALOG_H #define UNIXWINDOWINFODIALOG_H #include class QWidget; namespace Ui { class CapturedWindowInfoDialog; } class CapturedWindowInfoDialog : public QDialog { Q_OBJECT public: explicit CapturedWindowInfoDialog(long window, QWidget *parent = nullptr); ~CapturedWindowInfoDialog(); enum { WindowNone = 0, WindowClass = (1 << 0), WindowName = (1 << 1), WindowPath = (1 << 2), }; typedef int CapturedWindowOption; QString getWindowClass(); QString getWindowName(); QString getWindowPath(); bool useFullWindowPath(); CapturedWindowOption getSelectedOptions(); private: Ui::CapturedWindowInfoDialog *ui; CapturedWindowOption selectedMatch; QString winClass; QString winName; QString winPath; bool fullWinPath; private slots: void populateOption(); }; #endif // UNIXWINDOWINFODIALOG_H AntiMicroX-antimicrox-2888bf6/src/capturedwindowinfodialog.ui000066400000000000000000000137721377703515000245160ustar00rootroot00000000000000 CapturedWindowInfoDialog 0 0 533 363 Captured Window Properties 20 50 false Information About Window true 20 Class: true TextLabel Title: true TextLabel Path: true TextLabel Match By Properties true false false Class Title Path true Full Path File Name Qt::Vertical 20 40 Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() CapturedWindowInfoDialog accept() 248 254 157 274 buttonBox rejected() CapturedWindowInfoDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/commandlineutility.cpp000066400000000000000000000357261377703515000235050ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "commandlineutility.h" #include "common.h" #include "eventhandlerfactory.h" #include "messagehandler.h" #include #include #include #include QStringList CommandLineUtility::eventGeneratorsList = EventHandlerFactory::buildEventGeneratorList(); CommandLineUtility::CommandLineUtility(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); launchInTray = false; hideTrayIcon = false; profileLocation = ""; controllerNumber = 0; encounteredError = false; hiddenRequest = false; unloadProfile = false; startSetNumber = 0; daemonMode = false; displayString = ""; listControllers = false; mappingController = false; currentLogLevel = Logger::LOG_NONE; currentListsIndex = 0; ControllerOptionsInfo tempInfo; controllerOptionsList.append(tempInfo); eventGenerator = EventHandlerFactory::fallBackIdentifier(); } void CommandLineUtility::parseArguments(QCommandLineParser *parser) { qInstallMessageHandler(MessageHandler::myMessageOutput); int i = 0; while ((i < parser->optionNames().count()) && !encounteredError) { if (parser->isSet("tray")) { qDebug() << "tray is set"; launchInTray = true; hideTrayIcon = false; } else if (parser->isSet("no-tray")) { qDebug() << "no-tray is set"; hideTrayIcon = true; launchInTray = false; } if (parser->isSet("profile")) { parseArgsProfile(parser); } if (parser->isSet("profile-controller")) { parseArgsPrControle(parser); } if (parser->isSet("hidden")) { hiddenRequest = true; } if (parser->isSet("unload")) { parseArgsUnload(parser); } if (parser->isSet("startSet")) { parseArgsStartSet(parser); } if (parser->isSet("next")) { currentListsIndex++; ControllerOptionsInfo tempInfo; controllerOptionsList.append(tempInfo); } if (parser->isSet("list")) { listControllers = true; } if (parser->isSet("map")) { parseArgsMap(parser); } if (parser->isSet("daemon")) { daemonMode = true; } #ifdef WITH_X11 if (parser->isSet("display")) { if (!parser->value("display").isEmpty()) { displayString = parser->value("display"); } else { setErrorMessage(QObject::tr("No display string was specified.")); } } #endif #if (defined(WITH_UINPUT) && defined(WITH_XTEST)) if (parser->isSet("eventgen")) { QString eventGenText = parser->value("eventgen"); if (!eventGenText.isEmpty() && !eventGeneratorsList.contains(eventGenText)) { eventGenerator = ""; setErrorMessage(QObject::tr("An invalid event generator was specified.")); } else if (!eventGenText.isEmpty() && eventGeneratorsList.contains(eventGenText)) { eventGenerator = eventGenText; } else { setErrorMessage(QObject::tr("No event generator string was specified.")); } } #endif if (parser->isSet("log-level")) { QString logLevelText = parser->value("log-level"); if (logLevelText == "debug") currentLogLevel = Logger::LOG_DEBUG; else if (logLevelText == "info") currentLogLevel = Logger::LOG_INFO; else if (logLevelText == "warn") currentLogLevel = Logger::LOG_WARNING; else if (logLevelText == "error") currentLogLevel = Logger::LOG_ERROR; } if (parser->isSet("log-file")) { if (!parser->value("log-file").isEmpty()) { currentLogFile = parser->value("log-file"); } else { setErrorMessage(QObject::tr("No log file specified.")); } } i++; } } void CommandLineUtility::parseArgsProfile(QCommandLineParser *parser) { QFileInfo profileFileInfo(parser->value("profile")); if (profileFileInfo.exists() && (profileFileInfo.suffix() != "amgp") && (profileFileInfo.suffix() != "xml")) { setErrorMessage(QObject::tr("Profile location %1 is not an XML file.").arg(parser->value("profile"))); } else if (profileFileInfo.exists() && ((profileFileInfo.suffix() == "amgp") || (profileFileInfo.suffix() == "xml"))) { QString tempProfileLocation = profileFileInfo.absoluteFilePath(); ControllerOptionsInfo tempInfo = getControllerOptionsList().at(currentListsIndex); tempInfo.setProfileLocation(tempProfileLocation); controllerOptionsList.replace(currentListsIndex, tempInfo); } else { setErrorMessage(QObject::tr("Profile location %1 does not exist.").arg(parser->value("profile"))); } } void CommandLineUtility::parseArgsPrControle(QCommandLineParser *parser) { bool validNumber = false; int tempNumber = parser->value("profile-controller").toInt(&validNumber); if (validNumber) { if (controllerNumber == 0) controllerNumber = tempNumber; ControllerOptionsInfo tempInfo = getControllerOptionsList().at(currentListsIndex); tempInfo.setControllerNumber(tempNumber); controllerOptionsList.replace(currentListsIndex, tempInfo); } else if (!parser->value("profile-controller").isEmpty()) { if (controllerIDString.isEmpty()) controllerIDString = parser->value("profile-controller"); ControllerOptionsInfo tempInfo = getControllerOptionsList().at(currentListsIndex); tempInfo.setControllerID(parser->value("profile-controller")); controllerOptionsList.replace(currentListsIndex, tempInfo); } else { setErrorMessage(QObject::tr("Controller identifier is not a valid value.")); } } void CommandLineUtility::parseArgsUnload(QCommandLineParser *parser) { ControllerOptionsInfo gameControllerOptionInfo = getControllerOptionsList().at(currentListsIndex); gameControllerOptionInfo.setProfileLocation(""); gameControllerOptionInfo.setUnloadRequest(true); controllerOptionsList.replace(currentListsIndex, gameControllerOptionInfo); QStringList parserVals = QStringList() << parser->values("unload"); QListIterator profileForUnload(parserVals); QString unloadedProfText = QString(); if (profileForUnload.hasNext()) { unloadedProfText = profileForUnload.next(); // A value has been passed. Attempt // to validate the value. bool validNumber = false; int tempNumber = unloadedProfText.toInt(&validNumber); if (validNumber) { controllerNumber = tempNumber; gameControllerOptionInfo = getControllerOptionsList().at(currentListsIndex); gameControllerOptionInfo.setControllerNumber(controllerNumber); controllerOptionsList.replace(currentListsIndex, gameControllerOptionInfo); } else if (!unloadedProfText.isEmpty()) { controllerIDString = unloadedProfText; gameControllerOptionInfo = getControllerOptionsList().at(currentListsIndex); gameControllerOptionInfo.setControllerID(controllerIDString); controllerOptionsList.replace(currentListsIndex, gameControllerOptionInfo); } else { setErrorMessage(QObject::tr("Controller identifier is not a valid value.")); } } else { unloadProfile = true; profileLocation = ""; } } void CommandLineUtility::parseArgsStartSet(QCommandLineParser *parser) { QStringList parserValues = QStringList() << parser->values("startSet"); QListIterator profileForStartset(parserValues); QString startSetText = QString(); if (profileForStartset.hasNext()) { startSetText = profileForStartset.next(); bool validNumber = false; int tempNumber = startSetText.toInt(&validNumber); if (validNumber && (tempNumber >= 1) && (tempNumber <= 8)) { startSetNumber = tempNumber; ControllerOptionsInfo tempInfo = getControllerOptionsList().at(currentListsIndex); tempInfo.setStartSetNumber(startSetNumber); controllerOptionsList.replace(currentListsIndex, tempInfo); } else if (validNumber) { setErrorMessage(QObject::tr("An invalid set number '%1' was specified.").arg(tempNumber)); } if (profileForStartset.hasNext()) { startSetText = profileForStartset.next(); if (validNumber) { controllerNumber = tempNumber; ControllerOptionsInfo tempInfo = getControllerOptionsList().at(currentListsIndex); tempInfo.setControllerNumber(controllerNumber); controllerOptionsList.replace(currentListsIndex, tempInfo); } else if (!startSetText.isEmpty()) { controllerIDString = startSetText; ControllerOptionsInfo tempInfo = getControllerOptionsList().at(currentListsIndex); tempInfo.setControllerID(controllerIDString); controllerOptionsList.replace(currentListsIndex, tempInfo); } else { setErrorMessage(QObject::tr("Controller identifier '%s'' is not a valid value.").arg(startSetText)); } } } else { setErrorMessage(QObject::tr("No set number was specified.")); } } void CommandLineUtility::parseArgsMap(QCommandLineParser *parser) { QString mapOptionText = parser->value("map"); if (!mapOptionText.isEmpty()) { bool validNumber = false; int tempNumber = mapOptionText.toInt(&validNumber); if (validNumber) { controllerNumber = tempNumber; mappingController = true; } else if (!mapOptionText.isEmpty()) { controllerIDString = mapOptionText; mappingController = true; } else { setErrorMessage(QObject::tr("Controller identifier is not a valid value.")); } } else { setErrorMessage(QObject::tr("No controller was specified.")); } } bool CommandLineUtility::isLaunchInTrayEnabled() { qInstallMessageHandler(MessageHandler::myMessageOutput); return launchInTray; } bool CommandLineUtility::isTrayHidden() { qInstallMessageHandler(MessageHandler::myMessageOutput); return hideTrayIcon; } bool CommandLineUtility::hasProfile() { qInstallMessageHandler(MessageHandler::myMessageOutput); return !profileLocation.isEmpty(); } bool CommandLineUtility::hasControllerNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return (controllerNumber > 0); } QString CommandLineUtility::getProfileLocation() { qInstallMessageHandler(MessageHandler::myMessageOutput); return profileLocation; } int CommandLineUtility::getControllerNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return controllerNumber; } bool CommandLineUtility::hasError() { qInstallMessageHandler(MessageHandler::myMessageOutput); return encounteredError; } bool CommandLineUtility::isHiddenRequested() { qInstallMessageHandler(MessageHandler::myMessageOutput); return hiddenRequest; } bool CommandLineUtility::hasControllerID() { qInstallMessageHandler(MessageHandler::myMessageOutput); return !controllerIDString.isEmpty(); } QString CommandLineUtility::getControllerID() { qInstallMessageHandler(MessageHandler::myMessageOutput); return controllerIDString; } bool CommandLineUtility::isUnloadRequested() { qInstallMessageHandler(MessageHandler::myMessageOutput); return unloadProfile; } int CommandLineUtility::getStartSetNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return startSetNumber; } int CommandLineUtility::getJoyStartSetNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return startSetNumber - 1; } bool CommandLineUtility::shouldListControllers() { qInstallMessageHandler(MessageHandler::myMessageOutput); return listControllers; } bool CommandLineUtility::shouldMapController() { qInstallMessageHandler(MessageHandler::myMessageOutput); return mappingController; } QString CommandLineUtility::getEventGenerator() { qInstallMessageHandler(MessageHandler::myMessageOutput); return eventGenerator; } bool CommandLineUtility::launchAsDaemon() { qInstallMessageHandler(MessageHandler::myMessageOutput); return daemonMode; } QString CommandLineUtility::getDisplayString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return displayString; } Logger::LogLevel CommandLineUtility::getCurrentLogLevel() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentLogLevel; } QString CommandLineUtility::getCurrentLogFile() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentLogFile; } QString CommandLineUtility::getErrorText() { qInstallMessageHandler(MessageHandler::myMessageOutput); return errorText; } void CommandLineUtility::setErrorMessage(QString temp) { qInstallMessageHandler(MessageHandler::myMessageOutput); errorText = temp; encounteredError = true; } QList const &CommandLineUtility::getControllerOptionsList() { qInstallMessageHandler(MessageHandler::myMessageOutput); return controllerOptionsList; } bool CommandLineUtility::hasProfileInOptions() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QListIterator iter(getControllerOptionsList()); while (iter.hasNext()) { ControllerOptionsInfo temp = iter.next(); if (temp.hasProfile()) { result = true; iter.toBack(); } } return result; } AntiMicroX-antimicrox-2888bf6/src/commandlineutility.h000066400000000000000000000101101377703515000231260ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COMMANDLINEPARSER_H #define COMMANDLINEPARSER_H class QCommandLineParser; #include "logger.h" class ControllerOptionsInfo { public: ControllerOptionsInfo() { controllerNumber = 0; startSetNumber = 0; unloadProfile = false; } bool hasProfile() { return !profileLocation.isEmpty(); } QString getProfileLocation() { return profileLocation; } void setProfileLocation(QString location) { profileLocation = location; } bool hasControllerNumber() { return (controllerNumber > 0); } int getControllerNumber() { return controllerNumber; } void setControllerNumber(int temp) { controllerNumber = temp; } bool hasControllerID() { return !controllerIDString.isEmpty(); } QString getControllerID() { return controllerIDString; } void setControllerID(QString temp) { controllerIDString = temp; } bool isUnloadRequested() { return unloadProfile; } void setUnloadRequest(bool status) { unloadProfile = status; } int getStartSetNumber() { return startSetNumber; } int getJoyStartSetNumber() { return startSetNumber - 1; } void setStartSetNumber(int temp) { if ((temp >= 1) && (temp <= 8)) { startSetNumber = temp; } } private: QString profileLocation; int controllerNumber; QString controllerIDString; int startSetNumber; bool unloadProfile; }; class CommandLineUtility : public QObject { Q_OBJECT public: explicit CommandLineUtility(QObject *parent = nullptr); void parseArguments(QCommandLineParser *parser); bool isLaunchInTrayEnabled(); bool isTrayHidden(); bool hasProfile(); bool hasControllerNumber(); bool hasControllerID(); bool isHiddenRequested(); bool isUnloadRequested(); bool shouldListControllers(); bool shouldMapController(); bool hasProfileInOptions(); bool hasError(); int getControllerNumber(); int getStartSetNumber(); int getJoyStartSetNumber(); QString getControllerID(); QString getProfileLocation(); QString getEventGenerator(); QString getCurrentLogFile(); QString getErrorText(); QList *getJoyStartSetNumberList(); QList const &getControllerOptionsList(); bool launchAsDaemon(); QString getDisplayString(); Logger::LogLevel getCurrentLogLevel(); protected: void setErrorMessage(QString temp); private: bool launchInTray; bool hideTrayIcon; bool encounteredError; bool hiddenRequest; bool unloadProfile; bool daemonMode; bool listControllers; bool mappingController; int startSetNumber; int controllerNumber; int currentListsIndex; QString profileLocation; QString controllerIDString; QString displayString; QString eventGenerator; QString errorText; QString currentLogFile; Logger::LogLevel currentLogLevel; QList controllerOptionsList; static QStringList eventGeneratorsList; void parseArgsProfile(QCommandLineParser *parser); void parseArgsPrControle(QCommandLineParser *parser); void parseArgsUnload(QCommandLineParser *parser); void parseArgsStartSet(QCommandLineParser *parser); void parseArgsMap(QCommandLineParser *parser); }; #endif // COMMANDLINEPARSER_H AntiMicroX-antimicrox-2888bf6/src/common.cpp000066400000000000000000000111661377703515000210530ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "common.h" #include "messagehandler.h" #include #include #include #include namespace PadderCommon { QString preferredProfileDir(AntiMicroSettings *settings) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString lastProfileDir = settings->value("LastProfileDir", "").toString(); QString defaultProfileDir = settings->value("DefaultProfileDir", "").toString(); QString lookupDir = QString(); if (!defaultProfileDir.isEmpty()) { QFileInfo dirinfo(defaultProfileDir); if (dirinfo.isDir() && dirinfo.isReadable()) lookupDir = defaultProfileDir; } if (lookupDir.isEmpty() && !lastProfileDir.isEmpty()) { QFileInfo dirinfo(lastProfileDir); if (dirinfo.isDir() && dirinfo.isReadable()) lookupDir = lastProfileDir; } if (lookupDir.isEmpty()) { lookupDir = QDir::homePath(); } return lookupDir; } QStringList arguments(const int &argc, char **argv) { qInstallMessageHandler(MessageHandler::myMessageOutput); QStringList list = QStringList(); for (int a = 0; a < argc; ++a) list << QString::fromLocal8Bit(argv[a]); return list; } QStringList parseArgumentsString(QString tempString) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool inside = (!tempString.isEmpty() && tempString.at(0) == QChar('"')); QStringList tempList = tempString.split(QRegExp("\""), QString::SkipEmptyParts); QStringList finalList = QStringList(); QStringListIterator iter(tempList); while (iter.hasNext()) { QString temp = iter.next(); if (inside) finalList.append(temp); else finalList.append(temp.split(QRegExp("\\s+"), QString::SkipEmptyParts)); inside = !inside; } return finalList; } /** * @brief Reload main application and base Qt translation files. * @param Based Qt translator * @param Application translator * @param Language code */ void reloadTranslations(QTranslator *translator, QTranslator *appTranslator, QString language) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Remove application specific translation strings qApp->removeTranslator(translator); // Remove old Qt translation strings qApp->removeTranslator(appTranslator); // Load new Qt translation strings translator->load(QString("qt_").append(language), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); qApp->installTranslator(appTranslator); // Load application specific translation strings translator->load("antimicrox_" + language, QApplication::applicationDirPath().append("/../share/antimicrox/translations")); qApp->installTranslator(translator); } void lockInputDevices() { qInstallMessageHandler(MessageHandler::myMessageOutput); sdlWaitMutex.lock(); } void unlockInputDevices() { qInstallMessageHandler(MessageHandler::myMessageOutput); sdlWaitMutex.unlock(); } /** * @brief Universal method for loading icons * * @param name - name of used icon * @param fallback_location - location of icon loaded when icon described by name not found * @return QIcon */ QIcon loadIcon(const QString &name, const QString &fallback_location) { qDebug() << " Application theme has icon named: " << name << " " << QIcon::hasThemeIcon(name); QFileInfo f(fallback_location); if (!f.exists()) { qWarning() << "file " << fallback_location << " does not exist!"; } return QIcon::fromTheme(name, QIcon(fallback_location)); } QWaitCondition waitThisOut; QMutex sdlWaitMutex; QMutex inputDaemonMutex; QReadWriteLock editingLock; bool editingBindings = false; MouseHelper mouseHelperObj; } // namespace PadderCommon AntiMicroX-antimicrox-2888bf6/src/common.h000066400000000000000000000102411377703515000205110ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COMMON_H #define COMMON_H #include "antimicrosettings.h" #include "config.h" #include "mousehelper.h" #include #include #include #include #include namespace PadderCommon { inline QString configPath() { return (!qgetenv("XDG_CONFIG_HOME").isEmpty()) ? QString::fromUtf8(qgetenv("XDG_CONFIG_HOME")) + "/antimicrox" : QDir::homePath() + "/.config/antimicrox"; } const QString configFileName = "antimicrox_settings.ini"; inline QString configFilePath() { return QString(configPath()).append("/").append(configFileName); } inline QString configLegacyFilePath() { QString configPath = (!qgetenv("XDG_CONFIG_HOME").isEmpty()) ? QString::fromUtf8(qgetenv("XDG_CONFIG_HOME")) + "/antimicroX" : QDir::homePath() + "/.config/antimicroX"; return QString(configPath).append("/").append("antimicroX_settings.ini"); } inline QString configAntimicroLegacyFilePath() { QString configPath = (!qgetenv("XDG_CONFIG_HOME").isEmpty()) ? QString::fromUtf8(qgetenv("XDG_CONFIG_HOME")) + "/antimicro" : QDir::homePath() + "/.config/antimicro"; return QString(configPath).append("/").append("antimicro_settings.ini"); } const int LATESTCONFIGFILEVERSION = 19; // Specify the last known profile version that requires a migration // to be performed in order to be compatible with the latest version. const int LATESTCONFIGMIGRATIONVERSION = 5; const QString localSocketKey = "antimicroxSignalListener"; const QString githubProjectPage = "https://github.com/AntiMicroX/antimicrox/"; const QString githubIssuesPage = "https://github.com/AntiMicroX/antimicrox/issues"; const QString wikiPage = QString("%1/wiki").arg(githubProjectPage); const QString mouseDeviceName("antimicrox Mouse Emulation"); const QString keyboardDeviceName("antimicrox Keyboard Emulation"); const QString springMouseDeviceName("antimicrox Abs Mouse Emulation"); const int ANTIMICROX_MAJOR_VERSION = PROJECT_MAJOR_VERSION; const int ANTIMICROX_MINOR_VERSION = PROJECT_MINOR_VERSION; const int ANTIMICROX_PATCH_VERSION = PROJECT_PATCH_VERSION; const QString programVersion = (ANTIMICROX_PATCH_VERSION > 0) ? QString("%1.%2.%3").arg(ANTIMICROX_MAJOR_VERSION).arg(ANTIMICROX_MINOR_VERSION).arg(ANTIMICROX_PATCH_VERSION) : QString("%1.%2").arg(ANTIMICROX_MAJOR_VERSION).arg(ANTIMICROX_MINOR_VERSION); extern QWaitCondition waitThisOut; extern QMutex sdlWaitMutex; extern QMutex inputDaemonMutex; extern bool editingBindings; extern QReadWriteLock editingLock; extern MouseHelper mouseHelperObj; QString preferredProfileDir(AntiMicroSettings *settings); QStringList arguments(const int &argc, char **argv); QStringList parseArgumentsString(QString tempString); void reloadTranslations(QTranslator *translator, QTranslator *appTranslator, QString language); void lockInputDevices(); void unlockInputDevices(); QIcon loadIcon(const QString &name, const QString &fallback_location); /*! * \brief Returns the "human-readable" name of the given profile. */ inline QString getProfileName(QFileInfo &profile) { QString retVal = profile.completeBaseName(); return retVal; } } // namespace PadderCommon Q_DECLARE_METATYPE(QThread *) #endif // COMMON_H AntiMicroX-antimicrox-2888bf6/src/config.h.in000066400000000000000000000003431377703515000210750ustar00rootroot00000000000000 #ifndef CONFIG_H #define CONFIG_H #define PROJECT_MAJOR_VERSION @ANTIMICROX_MAJOR_VERSION@ #define PROJECT_MINOR_VERSION @ANTIMICROX_MINOR_VERSION@ #define PROJECT_PATCH_VERSION @ANTIMICROX_PATCH_VERSION@ #endif // CONFIG_H AntiMicroX-antimicrox-2888bf6/src/dpadcontextmenu.cpp000066400000000000000000000527661377703515000230000ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dpadcontextmenu.h" #include "antkeymapper.h" #include "common.h" #include "inputdevice.h" #include "joydpad.h" #include "messagehandler.h" #include "mousedialog/mousedpadsettingsdialog.h" #include #include DPadContextMenu::DPadContextMenu(JoyDPad *dpad, QWidget *parent) : QMenu(parent) , helper(dpad) { this->dpad = dpad; qInstallMessageHandler(MessageHandler::myMessageOutput); getHelper().moveToThread(dpad->thread()); connect(this, &DPadContextMenu::aboutToHide, this, &DPadContextMenu::deleteLater); } /** * @brief Generate the context menu that will be shown to a user when the person * right clicks on the DPad settings button. */ void DPadContextMenu::buildMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); QActionGroup *presetGroup = new QActionGroup(this); QAction *action = nullptr; int presetMode = 0; int currentPreset = getPresetIndex(); generateActionPreset(action, tr("Mouse (Normal)"), currentPreset, presetMode, presetGroup); generateActionPreset(action, tr("Mouse (Inverted Horizontal)"), currentPreset, presetMode, presetGroup); generateActionPreset(action, tr("Mouse (Inverted Vertical)"), currentPreset, presetMode, presetGroup); generateActionPreset(action, tr("Mouse (Inverted Horizontal + Vertical)"), currentPreset, presetMode, presetGroup); generateActionPreset(action, tr("Arrows"), currentPreset, presetMode, presetGroup); generateActionPreset(action, tr("Keys: W | A | S | D"), currentPreset, presetMode, presetGroup); generateActionPreset(action, tr("NumPad"), currentPreset, presetMode, presetGroup); generateActionPreset(action, tr("None"), currentPreset, presetMode, presetGroup); this->addSeparator(); QActionGroup *modesGroup = new QActionGroup(this); generateActionMode(modesGroup, action, tr("Standard"), static_cast(dpad->getJoyMode()), static_cast(JoyDPad::StandardMode)); generateActionMode(modesGroup, action, tr("Eight Way"), static_cast(dpad->getJoyMode()), static_cast(JoyDPad::EightWayMode)); generateActionMode(modesGroup, action, tr("4 Way Cardinal"), static_cast(dpad->getJoyMode()), static_cast(JoyDPad::FourWayCardinal)); generateActionMode(modesGroup, action, tr("4 Way Diagonal"), static_cast(dpad->getJoyMode()), static_cast(JoyDPad::FourWayDiagonal)); this->addSeparator(); action = this->addAction(tr("Mouse Settings")); action->setCheckable(false); connect(action, &QAction::triggered, this, &DPadContextMenu::openMouseSettingsDialog); } void DPadContextMenu::generateActionPreset(QAction *action, QString actionText, int currentPreset, int &presetMode, QActionGroup *presetGroup) { action = this->addAction(actionText); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setDPadPreset(action); }); presetGroup->addAction(action); presetMode++; } void DPadContextMenu::generateActionMode(QActionGroup *modesGroup, QAction *action, QString actionText, int currentPreset, int presetMode) { action = this->addAction(actionText); action->setCheckable(true); action->setChecked(currentPreset == presetMode); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setDPadMode(action); }); modesGroup->addAction(action); } /** * @brief Set the appropriate mode for a DPad based on the item chosen. */ void DPadContextMenu::setDPadMode(QAction *action) { qInstallMessageHandler(MessageHandler::myMessageOutput); int item = action->data().toInt(); dpad->setJoyMode(static_cast(item)); } /** * @brief Assign the appropriate slots to DPad buttons based on the preset item * that was chosen. */ void DPadContextMenu::setDPadPreset(QAction *action) { qInstallMessageHandler(MessageHandler::myMessageOutput); int item = action->data().toInt(); JoyButtonSlot *upButtonSlot = nullptr; JoyButtonSlot *downButtonSlot = nullptr; JoyButtonSlot *leftButtonSlot = nullptr; JoyButtonSlot *rightButtonSlot = nullptr; JoyButtonSlot *upLeftButtonSlot = nullptr; JoyButtonSlot *upRightButtonSlot = nullptr; JoyButtonSlot *downLeftButtonSlot = nullptr; JoyButtonSlot *downRightButtonSlot = nullptr; switch (item) { case 0: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); dpad->setJoyMode(JoyDPad::StandardMode); PadderCommon::inputDaemonMutex.unlock(); break; case 1: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); dpad->setJoyMode(JoyDPad::StandardMode); PadderCommon::inputDaemonMutex.unlock(); break; case 2: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); dpad->setJoyMode(JoyDPad::StandardMode); PadderCommon::inputDaemonMutex.unlock(); break; case 3: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); dpad->setJoyMode(JoyDPad::StandardMode); PadderCommon::inputDaemonMutex.unlock(); break; case 4: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up), Qt::Key_Up, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down), Qt::Key_Down, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left), Qt::Key_Left, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right), Qt::Key_Right, JoyButtonSlot::JoyKeyboard, this); dpad->setJoyMode(JoyDPad::StandardMode); PadderCommon::inputDaemonMutex.unlock(); break; case 5: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W), Qt::Key_W, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S), Qt::Key_S, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A), Qt::Key_A, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D), Qt::Key_D, JoyButtonSlot::JoyKeyboard, this); dpad->setJoyMode(JoyDPad::StandardMode); PadderCommon::inputDaemonMutex.unlock(); break; case 6: PadderCommon::inputDaemonMutex.lock(); if ((dpad->getJoyMode() == JoyDPad::StandardMode) || (dpad->getJoyMode() == JoyDPad::FourWayCardinal)) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); } else if (dpad->getJoyMode() == JoyDPad::EightWayMode) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } else if (dpad->getJoyMode() == JoyDPad::FourWayDiagonal) { upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } PadderCommon::inputDaemonMutex.unlock(); break; case 7: QMetaObject::invokeMethod(&helper, "clearButtonsSlotsEventReset", Qt::BlockingQueuedConnection); break; } QHash tempHash; tempHash.insert(JoyDPadButton::DpadUp, upButtonSlot); tempHash.insert(JoyDPadButton::DpadDown, downButtonSlot); tempHash.insert(JoyDPadButton::DpadLeft, leftButtonSlot); tempHash.insert(JoyDPadButton::DpadRight, rightButtonSlot); tempHash.insert(JoyDPadButton::DpadLeftUp, upLeftButtonSlot); tempHash.insert(JoyDPadButton::DpadRightUp, upRightButtonSlot); tempHash.insert(JoyDPadButton::DpadLeftDown, downLeftButtonSlot); tempHash.insert(JoyDPadButton::DpadRightDown, downRightButtonSlot); getHelper().setPendingSlots(&tempHash); QMetaObject::invokeMethod(&helper, "setFromPendingSlots", Qt::BlockingQueuedConnection); } /** * @brief Find the appropriate menu item index for the currently assigned * slots that are assigned to a DPad. * @return Menu index that corresponds to the currently assigned preset choice. * 0 means that no matching preset was found. */ int DPadContextMenu::getPresetIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = 0; PadderCommon::inputDaemonMutex.lock(); JoyDPadButton *upButton = dpad->getJoyButton(JoyDPadButton::DpadUp); QList *upslots = upButton->getAssignedSlots(); JoyDPadButton *downButton = dpad->getJoyButton(JoyDPadButton::DpadDown); QList *downslots = downButton->getAssignedSlots(); JoyDPadButton *leftButton = dpad->getJoyButton(JoyDPadButton::DpadLeft); QList *leftslots = leftButton->getAssignedSlots(); JoyDPadButton *rightButton = dpad->getJoyButton(JoyDPadButton::DpadRight); QList *rightslots = rightButton->getAssignedSlots(); if ((upslots->length() == 1) && (downslots->length() == 1) && (leftslots->length() == 1) && (rightslots->length() == 1)) { JoyButtonSlot *upslot = upslots->at(0); JoyButtonSlot *downslot = downslots->at(0); JoyButtonSlot *leftslot = leftslots->at(0); JoyButtonSlot *rightslot = rightslots->at(0); if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { result = 1; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { result = 2; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { result = 3; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { result = 4; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right))) { result = 5; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D))) { result = 6; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6))) { result = 7; } } else if ((upslots->length() == 0) && (downslots->length() == 0) && (leftslots->length() == 0) && (rightslots->length() == 0)) { result = 8; } PadderCommon::inputDaemonMutex.unlock(); return result; } /** * @brief Open a mouse settings dialog for changing the mouse speed settings * for all DPad buttons. */ void DPadContextMenu::openMouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); MouseDPadSettingsDialog *dialog = new MouseDPadSettingsDialog(dpad, parentWidget()); dialog->show(); } DPadContextMenuHelper &DPadContextMenu::getHelper() { return helper; } AntiMicroX-antimicrox-2888bf6/src/dpadcontextmenu.h000066400000000000000000000033321377703515000224260ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DPADCONTEXTMENU_H #define DPADCONTEXTMENU_H #include "uihelpers/dpadcontextmenuhelper.h" #include class JoyDPad; class QWidget; class DPadContextMenu : public QMenu { Q_OBJECT public: explicit DPadContextMenu(JoyDPad *dpad, QWidget *parent = nullptr); void buildMenu(); protected: int getPresetIndex(); private slots: void setDPadPreset(QAction *action); void setDPadMode(QAction *action); void openMouseSettingsDialog(); private: DPadContextMenuHelper &getHelper(); JoyDPad *dpad; DPadContextMenuHelper helper; void generateActionPreset(QAction *action, QString actionText, int currentPreset, int &presetMode, QActionGroup *presetGroup); void generateActionMode(QActionGroup *modesGroup, QAction *action, QString actionText, int currentPreset, int presetMode); }; #endif // DPADCONTEXTMENU_H AntiMicroX-antimicrox-2888bf6/src/dpadeditdialog.cpp000066400000000000000000000551541377703515000225260ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dpadeditdialog.h" #include "ui_dpadeditdialog.h" #include "antkeymapper.h" #include "common.h" #include "event.h" #include "inputdevice.h" #include "joydpad.h" #include "messagehandler.h" #include "mousedialog/mousedpadsettingsdialog.h" #include "setjoystick.h" #include #include #include DPadEditDialog::DPadEditDialog(JoyDPad *dpad, QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::DPadEditDialog) , helper(dpad) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->dpad = dpad; getHelperLocal().moveToThread(dpad->thread()); PadderCommon::inputDaemonMutex.lock(); updateWindowTitleDPadName(); switch (dpad->getJoyMode()) { case JoyDPad::StandardMode: ui->joyModeComboBox->setCurrentIndex(0); break; case JoyDPad::EightWayMode: ui->joyModeComboBox->setCurrentIndex(1); break; case JoyDPad::FourWayCardinal: ui->joyModeComboBox->setCurrentIndex(2); break; case JoyDPad::FourWayDiagonal: ui->joyModeComboBox->setCurrentIndex(3); break; } selectCurrentPreset(); ui->dpadNameLineEdit->setText(dpad->getDpadName()); int dpadDelay = dpad->getDPadDelay(); ui->dpadDelaySlider->setValue(dpadDelay * .1); ui->dpadDelayDoubleSpinBox->setValue(dpadDelay * .001); PadderCommon::inputDaemonMutex.unlock(); connect(ui->presetsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &DPadEditDialog::implementPresets); connect(ui->joyModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &DPadEditDialog::implementModes); connect(ui->mouseSettingsPushButton, &QPushButton::clicked, this, &DPadEditDialog::openMouseSettingsDialog); connect(ui->dpadNameLineEdit, &QLineEdit::textEdited, dpad, &JoyDPad::setDPadName); connect(ui->dpadDelaySlider, static_cast(&QSlider::valueChanged), &helper, &DPadEditDialogHelper::updateJoyDPadDelay); connect(dpad, &JoyDPad::dpadDelayChanged, this, &DPadEditDialog::updateDPadDelaySpinBox); connect(ui->dpadDelayDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &DPadEditDialog::updateDPadDelaySlider); connect(dpad, &JoyDPad::dpadNameChanged, this, &DPadEditDialog::updateWindowTitleDPadName); } DPadEditDialog::~DPadEditDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void DPadEditDialog::implementPresets(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *upButtonSlot = nullptr; JoyButtonSlot *downButtonSlot = nullptr; JoyButtonSlot *leftButtonSlot = nullptr; JoyButtonSlot *rightButtonSlot = nullptr; JoyButtonSlot *upLeftButtonSlot = nullptr; JoyButtonSlot *upRightButtonSlot = nullptr; JoyButtonSlot *downLeftButtonSlot = nullptr; JoyButtonSlot *downRightButtonSlot = nullptr; switch (index) { case 1: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); break; case 2: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); break; case 3: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); break; case 4: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); break; case 5: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up), Qt::Key_Up, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down), Qt::Key_Down, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left), Qt::Key_Left, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right), Qt::Key_Right, JoyButtonSlot::JoyKeyboard, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); break; case 6: PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W), Qt::Key_W, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S), Qt::Key_S, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A), Qt::Key_A, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D), Qt::Key_D, JoyButtonSlot::JoyKeyboard, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); break; case 7: PadderCommon::inputDaemonMutex.lock(); if ((ui->joyModeComboBox->currentIndex() == 0) || (ui->joyModeComboBox->currentIndex() == 2)) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); } else if (ui->joyModeComboBox->currentIndex() == 1) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } else if (ui->joyModeComboBox->currentIndex() == 3) { upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } PadderCommon::inputDaemonMutex.unlock(); break; case 0: case 8: QMetaObject::invokeMethod(&helper, "clearButtonsSlotsEventReset", Qt::BlockingQueuedConnection); dpad->getJoyButton(JoyDPadButton::DpadUp)->buildActiveZoneSummaryString(); dpad->getJoyButton(JoyDPadButton::DpadDown)->buildActiveZoneSummaryString(); dpad->getJoyButton(JoyDPadButton::DpadLeft)->buildActiveZoneSummaryString(); dpad->getJoyButton(JoyDPadButton::DpadRight)->buildActiveZoneSummaryString(); break; } QHash tempHash; tempHash.insert(JoyDPadButton::DpadUp, upButtonSlot); tempHash.insert(JoyDPadButton::DpadDown, downButtonSlot); tempHash.insert(JoyDPadButton::DpadLeft, leftButtonSlot); tempHash.insert(JoyDPadButton::DpadRight, rightButtonSlot); tempHash.insert(JoyDPadButton::DpadLeftUp, upLeftButtonSlot); tempHash.insert(JoyDPadButton::DpadRightUp, upRightButtonSlot); tempHash.insert(JoyDPadButton::DpadLeftDown, downLeftButtonSlot); tempHash.insert(JoyDPadButton::DpadRightDown, downRightButtonSlot); getHelperLocal().setPendingSlots(&tempHash); QMetaObject::invokeMethod(&helper, "setFromPendingSlots", Qt::BlockingQueuedConnection); } void DPadEditDialog::implementModes(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); dpad->releaseButtonEvents(); switch (index) { case 0: dpad->setJoyMode(JoyDPad::StandardMode); break; case 1: dpad->setJoyMode(JoyDPad::EightWayMode); break; case 2: dpad->setJoyMode(JoyDPad::FourWayCardinal); break; case 3: dpad->setJoyMode(JoyDPad::FourWayDiagonal); break; } PadderCommon::inputDaemonMutex.unlock(); } void DPadEditDialog::selectCurrentPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *upButton = dpad->getJoyButton(JoyDPadButton::DpadUp); QList *upslots = upButton->getAssignedSlots(); JoyDPadButton *downButton = dpad->getJoyButton(JoyDPadButton::DpadDown); QList *downslots = downButton->getAssignedSlots(); JoyDPadButton *leftButton = dpad->getJoyButton(JoyDPadButton::DpadLeft); QList *leftslots = leftButton->getAssignedSlots(); JoyDPadButton *rightButton = dpad->getJoyButton(JoyDPadButton::DpadRight); QList *rightslots = rightButton->getAssignedSlots(); if ((upslots->length() == 1) && (downslots->length() == 1) && (leftslots->length() == 1) && (rightslots->length() == 1)) { JoyButtonSlot *upslot = upslots->at(0); JoyButtonSlot *downslot = downslots->at(0); JoyButtonSlot *leftslot = leftslots->at(0); JoyButtonSlot *rightslot = rightslots->at(0); if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { ui->presetsComboBox->setCurrentIndex(1); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { ui->presetsComboBox->setCurrentIndex(2); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { ui->presetsComboBox->setCurrentIndex(3); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { ui->presetsComboBox->setCurrentIndex(4); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right))) { ui->presetsComboBox->setCurrentIndex(5); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D))) { ui->presetsComboBox->setCurrentIndex(6); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6))) { ui->presetsComboBox->setCurrentIndex(7); } } else if ((upslots->length() == 0) && (downslots->length() == 0) && (leftslots->length() == 0) && (rightslots->length() == 0)) { ui->presetsComboBox->setCurrentIndex(8); } } void DPadEditDialog::openMouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->mouseSettingsPushButton->setEnabled(false); MouseDPadSettingsDialog *dialog = new MouseDPadSettingsDialog(this->dpad, this); dialog->show(); connect(this, &DPadEditDialog::finished, dialog, &MouseDPadSettingsDialog::close); connect(dialog, &MouseDPadSettingsDialog::finished, this, &DPadEditDialog::enableMouseSettingButton); } void DPadEditDialog::enableMouseSettingButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->mouseSettingsPushButton->setEnabled(true); } /** * @brief Update QDoubleSpinBox value based on updated dpad delay value. * @param Delay value obtained from JoyDPad. */ void DPadEditDialog::updateDPadDelaySpinBox(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); double temp = value * 0.001; ui->dpadDelayDoubleSpinBox->setValue(temp); } /** * @brief Update QSlider value based on value from QDoubleSpinBox. * @param Value from QDoubleSpinBox. */ void DPadEditDialog::updateDPadDelaySlider(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int currentDpadDelay = value * 100; if (ui->dpadDelaySlider->value() != currentDpadDelay) { ui->dpadDelaySlider->setValue(currentDpadDelay); } } void DPadEditDialog::updateWindowTitleDPadName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(tr("Set")).append(" "); if (!dpad->getDpadName().isEmpty()) temp.append(dpad->getName(false, true)); else temp.append(dpad->getName()); if (dpad->getParentSet()->getIndex() != 0) { int setIndex = dpad->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = dpad->getParentSet()->getName(); if (!setName.isEmpty()) { temp.append(": ").append(setName); } temp.append("]"); } setWindowTitle(temp); } JoyDPad *DPadEditDialog::getDPad() const { return dpad; } DPadEditDialogHelper const &DPadEditDialog::getHelper() { return helper; } DPadEditDialogHelper &DPadEditDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/dpadeditdialog.h000066400000000000000000000033241377703515000221630ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DPADEDITDIALOG_H #define DPADEDITDIALOG_H #include "uihelpers/dpadeditdialoghelper.h" #include class JoyDPad; class QWidget; namespace Ui { class DPadEditDialog; } class DPadEditDialog : public QDialog { Q_OBJECT public: explicit DPadEditDialog(JoyDPad *dpad, QWidget *parent = nullptr); ~DPadEditDialog(); JoyDPad *getDPad() const; DPadEditDialogHelper const &getHelper(); protected: void selectCurrentPreset(); private slots: void implementPresets(int index); void implementModes(int index); void openMouseSettingsDialog(); void enableMouseSettingButton(); void updateWindowTitleDPadName(); void updateDPadDelaySpinBox(int value); void updateDPadDelaySlider(double value); private: Ui::DPadEditDialog *ui; DPadEditDialogHelper &getHelperLocal(); JoyDPad *dpad; DPadEditDialogHelper helper; }; #endif // DPADEDITDIALOG_H AntiMicroX-antimicrox-2888bf6/src/dpadeditdialog.ui000066400000000000000000000211351377703515000223510ustar00rootroot00000000000000 DPadEditDialog Qt::WindowModal 0 0 528 334 Dialog Presets: 282 0 Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Dpad Mode: 282 0 Standard: 8 region dpad with two direction buttons active when the dpad is in a diagonal region. Eight Way: 8 region dpad with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region dpad with regions corresponding to the cardinal directions of the dpad. Useful for menus. 4 Way Diagonal: 4 region dpad with each region corresponding to a diagonal zone. Standard Eight Way 4 Way Cardinal 4 Way Diagonal Qt::Vertical QSizePolicy::Fixed 20 20 DPad Delay: Time lapsed before a direction change is taken into effect. 0 100 1 10 0 0 Qt::Horizontal QSlider::TicksBelow 0 Time lapsed before a direction change is taken into effect. false s 2 1.000000000000000 0.010000000000000 Qt::Vertical QSizePolicy::MinimumExpanding 20 36 10 6 &Name: dpadNameLineEdit Specify the name of a dpad. Mouse Settings Qt::Horizontal Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() DPadEditDialog accept() 248 254 157 274 buttonBox rejected() DPadEditDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/dpadpushbutton.cpp000066400000000000000000000057251377703515000226330ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dpadpushbutton.h" #include "dpadcontextmenu.h" #include "joydpad.h" #include "messagehandler.h" #include DPadPushButton::DPadPushButton(JoyDPad *dpad, bool displayNames, QWidget *parent) : FlashButtonWidget(displayNames, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->dpad = dpad; refreshLabel(); enableFlashes(); tryFlash(); this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &DPadPushButton::customContextMenuRequested, this, &DPadPushButton::showContextMenu); connect(dpad, &JoyDPad::dpadNameChanged, this, &DPadPushButton::refreshLabel); } JoyDPad *DPadPushButton::getDPad() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return dpad; } QString DPadPushButton::generateLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (!dpad->getDpadName().isEmpty()) temp.append(dpad->getName(false, ifDisplayNames())); else temp.append(dpad->getName()); qDebug() << "Dpad button name is: " << temp; return temp; } void DPadPushButton::disableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(dpad, &JoyDPad::active, this, &DPadPushButton::flash); disconnect(dpad, &JoyDPad::released, this, &DPadPushButton::unflash); this->unflash(); } void DPadPushButton::enableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(dpad, &JoyDPad::active, this, &DPadPushButton::flash, Qt::QueuedConnection); connect(dpad, &JoyDPad::released, this, &DPadPushButton::unflash, Qt::QueuedConnection); } void DPadPushButton::showContextMenu(const QPoint &point) { qInstallMessageHandler(MessageHandler::myMessageOutput); QPoint globalPos = this->mapToGlobal(point); DPadContextMenu *contextMenu = new DPadContextMenu(dpad, this); contextMenu->buildMenu(); contextMenu->popup(globalPos); } void DPadPushButton::tryFlash() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (dpad->getCurrentDirection() != static_cast(JoyDPadButton::DpadCentered)) { flash(); } } AntiMicroX-antimicrox-2888bf6/src/dpadpushbutton.h000066400000000000000000000026111377703515000222670ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DPADPUSHBUTTON_H #define DPADPUSHBUTTON_H #include "flashbuttonwidget.h" class JoyDPad; class QWidget; class DPadPushButton : public FlashButtonWidget { Q_OBJECT public: explicit DPadPushButton(JoyDPad *dpad, bool displayNames, QWidget *parent = nullptr); JoyDPad *getDPad() const; void tryFlash(); protected: QString generateLabel() override; public slots: void disableFlashes() override; void enableFlashes() override; private slots: void showContextMenu(const QPoint &point); private: JoyDPad *dpad; }; #endif // DPADPUSHBUTTON_H AntiMicroX-antimicrox-2888bf6/src/dpadpushbuttongroup.cpp000066400000000000000000000131341377703515000237010ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dpadpushbuttongroup.h" #include "buttoneditdialog.h" #include "dpadeditdialog.h" #include "dpadpushbutton.h" #include "inputdevice.h" #include "joydpad.h" #include "joydpadbuttonwidget.h" #include "messagehandler.h" #include #include #include DPadPushButtonGroup::DPadPushButtonGroup(JoyDPad *dpad, bool keypadUnlocked, bool displayNames, QWidget *parent) : QGridLayout(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->dpad = dpad; this->displayNames = displayNames; this->keypadUnlocked = keypadUnlocked; generateButtons(); changeButtonLayout(); connect(dpad, &JoyDPad::joyModeChanged, this, &DPadPushButtonGroup::changeButtonLayout); } void DPadPushButtonGroup::generateButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash *buttons = dpad->getJoyButtons(); upLeftButton = generateBtnForGrid(buttons, 9, 0, 0); upButton = generateBtnForGrid(buttons, 1, 0, 1); upRightButton = generateBtnForGrid(buttons, 3, 0, 2); leftButton = generateBtnForGrid(buttons, 8, 1, 0); dpadWidget = new DPadPushButton(dpad, displayNames, parentWidget()); dpadWidget->setIcon( QIcon::fromTheme(QString::fromUtf8("games_config_options"), QIcon(":/icons/actions/games_config_options.png"))); connect(dpadWidget, &DPadPushButton::clicked, this, &DPadPushButtonGroup::showDPadDialog); addWidget(dpadWidget, 1, 1); rightButton = generateBtnForGrid(buttons, 2, 1, 2); downLeftButton = generateBtnForGrid(buttons, 12, 2, 0); downButton = generateBtnForGrid(buttons, 4, 2, 1); downRightButton = generateBtnForGrid(buttons, 6, 2, 2); } JoyDPadButtonWidget *DPadPushButtonGroup::generateBtnForGrid(QHash *buttons, int dpadDirection, int cellRow, int cellCol) { JoyDPadButton *button = buttons->value(static_cast(dpadDirection)); JoyDPadButtonWidget *pushbutton = new JoyDPadButtonWidget(button, displayNames, parentWidget()); connect(pushbutton, &JoyDPadButtonWidget::clicked, this, [this, pushbutton] { openDPadButtonDialog(pushbutton); }); button->establishPropertyUpdatedConnections(); connect(button, &JoyDPadButton::slotsChanged, this, &DPadPushButtonGroup::propogateSlotsChanged); addWidget(pushbutton, cellRow, cellCol); return pushbutton; } void DPadPushButtonGroup::changeButtonLayout() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((dpad->getJoyMode() == JoyDPad::StandardMode) || (dpad->getJoyMode() == JoyDPad::EightWayMode) || (dpad->getJoyMode() == JoyDPad::FourWayCardinal)) { upButton->setVisible(true); downButton->setVisible(true); leftButton->setVisible(true); rightButton->setVisible(true); } else { upButton->setVisible(false); downButton->setVisible(false); leftButton->setVisible(false); rightButton->setVisible(false); } if ((dpad->getJoyMode() == JoyDPad::EightWayMode) || (dpad->getJoyMode() == JoyDPad::FourWayDiagonal)) { upLeftButton->setVisible(true); upRightButton->setVisible(true); downLeftButton->setVisible(true); downRightButton->setVisible(true); } else { upLeftButton->setVisible(false); upRightButton->setVisible(false); downLeftButton->setVisible(false); downRightButton->setVisible(false); } } void DPadPushButtonGroup::propogateSlotsChanged() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit buttonSlotChanged(); } JoyDPad *DPadPushButtonGroup::getDPad() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return dpad; } void DPadPushButtonGroup::openDPadButtonDialog(JoyButtonWidget *buttonWidget) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = buttonWidget->getJoyButton(); ButtonEditDialog *dialog = new ButtonEditDialog(button, dpad->getParentSet()->getInputDevice(), keypadUnlocked, parentWidget()); dialog->show(); } void DPadPushButtonGroup::showDPadDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); DPadEditDialog *dialog = new DPadEditDialog(dpad, parentWidget()); dialog->show(); } void DPadPushButtonGroup::toggleNameDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); displayNames = !displayNames; upButton->toggleNameDisplay(); downButton->toggleNameDisplay(); leftButton->toggleNameDisplay(); rightButton->toggleNameDisplay(); upLeftButton->toggleNameDisplay(); upRightButton->toggleNameDisplay(); downLeftButton->toggleNameDisplay(); downRightButton->toggleNameDisplay(); dpadWidget->toggleNameDisplay(); } AntiMicroX-antimicrox-2888bf6/src/dpadpushbuttongroup.h000066400000000000000000000042201377703515000233420ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DPADPUSHBUTTONGROUP_H #define DPADPUSHBUTTONGROUP_H #include class JoyDPad; class QWidget; class JoyDPadButtonWidget; class DPadPushButton; class JoyButtonWidget; class JoyDPadButton; class DPadPushButtonGroup : public QGridLayout { Q_OBJECT public: explicit DPadPushButtonGroup(JoyDPad *dpad, bool keypadUnlocked, bool displayNames = false, QWidget *parent = nullptr); JoyDPad *getDPad() const; protected: void generateButtons(); signals: void buttonSlotChanged(); public slots: void changeButtonLayout(); void toggleNameDisplay(); private slots: void propogateSlotsChanged(); void openDPadButtonDialog(JoyButtonWidget *buttonWidget); void showDPadDialog(); private: JoyDPad *dpad; bool keypadUnlocked; bool displayNames; JoyDPadButtonWidget *upButton; JoyDPadButtonWidget *downButton; JoyDPadButtonWidget *leftButton; JoyDPadButtonWidget *rightButton; JoyDPadButtonWidget *upLeftButton; JoyDPadButtonWidget *upRightButton; JoyDPadButtonWidget *downLeftButton; JoyDPadButtonWidget *downRightButton; DPadPushButton *dpadWidget; JoyDPadButtonWidget *generateBtnForGrid(QHash *buttons, int dpadDirection, int cellRow, int cellCol); }; #endif // DPADPUSHBUTTONGROUP_H AntiMicroX-antimicrox-2888bf6/src/editalldefaultautoprofiledialog.cpp000066400000000000000000000073571377703515000262070ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "editalldefaultautoprofiledialog.h" #include "ui_editalldefaultautoprofiledialog.h" #include "antimicrosettings.h" #include "autoprofileinfo.h" #include "common.h" #include "messagehandler.h" #include #include #include #include #include EditAllDefaultAutoProfileDialog::EditAllDefaultAutoProfileDialog(AutoProfileInfo *info, AntiMicroSettings *settings, QWidget *parent) : QDialog(parent) , ui(new Ui::EditAllDefaultAutoProfileDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->info = info; this->settings = settings; if (!info->getProfileLocation().isEmpty()) ui->profileLineEdit->setText(info->getProfileLocation()); connect(ui->profileBrowsePushButton, &QPushButton::clicked, this, &EditAllDefaultAutoProfileDialog::openProfileBrowseDialog); connect(this, &EditAllDefaultAutoProfileDialog::accepted, this, &EditAllDefaultAutoProfileDialog::saveAutoProfileInformation); } EditAllDefaultAutoProfileDialog::~EditAllDefaultAutoProfileDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void EditAllDefaultAutoProfileDialog::openProfileBrowseDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString preferredProfileDir = PadderCommon::preferredProfileDir(settings); QString profileFilename = QFileDialog::getOpenFileName(this, tr("Open Config"), preferredProfileDir, QString("Config Files (*.amgp *.xml)")); if (!profileFilename.isNull() && !profileFilename.isEmpty()) ui->profileLineEdit->setText(profileFilename); } void EditAllDefaultAutoProfileDialog::saveAutoProfileInformation() { qInstallMessageHandler(MessageHandler::myMessageOutput); // info->setGUID("all"); info->setUniqueID("all"); info->setProfileLocation(ui->profileLineEdit->text()); info->setActive(true); } AutoProfileInfo *EditAllDefaultAutoProfileDialog::getAutoProfile() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return info; } void EditAllDefaultAutoProfileDialog::accept() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool validForm = true; QString errorString = QString(); if (ui->profileLineEdit->text().length() > 0) { QFileInfo profileInfo(ui->profileLineEdit->text()); if (!profileInfo.exists()) { validForm = false; errorString = tr("Profile file path is invalid."); } } if (validForm) { QDialog::accept(); } else { QMessageBox msgBox; msgBox.setText(errorString); msgBox.setStandardButtons(QMessageBox::Close); msgBox.exec(); } } AntiMicroSettings *EditAllDefaultAutoProfileDialog::getSettings() const { return settings; } AntiMicroX-antimicrox-2888bf6/src/editalldefaultautoprofiledialog.h000066400000000000000000000032221377703515000256370ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef EDITALLDEFAULTAUTOPROFILEDIALOG_H #define EDITALLDEFAULTAUTOPROFILEDIALOG_H #include class AutoProfileInfo; class AntiMicroSettings; class QWidget; namespace Ui { class EditAllDefaultAutoProfileDialog; } class EditAllDefaultAutoProfileDialog : public QDialog { Q_OBJECT public: explicit EditAllDefaultAutoProfileDialog(AutoProfileInfo *info, AntiMicroSettings *settings, QWidget *parent = nullptr); ~EditAllDefaultAutoProfileDialog(); AutoProfileInfo *getAutoProfile() const; AntiMicroSettings *getSettings() const; protected: virtual void accept(); private: Ui::EditAllDefaultAutoProfileDialog *ui; AutoProfileInfo *info; AntiMicroSettings *settings; private slots: void openProfileBrowseDialog(); void saveAutoProfileInformation(); }; #endif // EDITALLDEFAULTAUTOPROFILEDIALOG_H AntiMicroX-antimicrox-2888bf6/src/editalldefaultautoprofiledialog.ui000066400000000000000000000047721377703515000260400ustar00rootroot00000000000000 EditAllDefaultAutoProfileDialog 0 0 384 114 Default Profile true Profile: profileLineEdit Browse Qt::Vertical QSizePolicy::Fixed 20 10 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() EditAllDefaultAutoProfileDialog accept() 248 254 157 274 buttonBox rejected() EditAllDefaultAutoProfileDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/event.cpp000066400000000000000000000604031377703515000207020ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "event.h" #include "eventhandlerfactory.h" #include "globalvariables.h" #include "joybutton.h" #include "messagehandler.h" #if defined(WITH_X11) #include "x11extras.h" #include #include #include #ifdef WITH_XTEST #include #endif #endif #if defined(WITH_UINPUT) #include "uinputhelper.h" #endif // TODO: Implement function for determining final mouse pointer position // based around a fixed bounding box resolution. void fakeAbsMouseCoordinates(double springX, double springY, int width, int height, int &finalx, int &finaly, int screen) { qInstallMessageHandler(MessageHandler::myMessageOutput); int screenWidth = 0; int screenHeight = 0; int screenMidwidth = 0; int screenMidheight = 0; int destSpringWidth = 0; int destSpringHeight = 0; int destMidWidth = 0; int destMidHeight = 0; QRect deskRect = PadderCommon::mouseHelperObj.getDesktopWidget()->screenGeometry(screen); screenWidth = deskRect.width(); screenHeight = deskRect.height(); screenMidwidth = screenWidth / 2; screenMidheight = screenHeight / 2; if ((width >= 2) && (height >= 2)) { destSpringWidth = qMin(width, screenWidth); destSpringHeight = qMin(height, screenHeight); } else { destSpringWidth = screenWidth; destSpringHeight = screenHeight; } destMidWidth = destSpringWidth / 2; destMidHeight = destSpringHeight / 2; finalx = (screenMidwidth + (springX * destMidWidth) + deskRect.x()); finaly = (screenMidheight + (springY * destMidHeight) + deskRect.y()); } // Create the event used by the operating system. void sendevent(JoyButtonSlot *slot, bool pressed) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot::JoySlotInputAction device = slot->getSlotMode(); if (device == JoyButtonSlot::JoyKeyboard) { EventHandlerFactory::getInstance()->handler()->sendKeyboardEvent(slot, pressed); } else if (device == JoyButtonSlot::JoyMouseButton) { EventHandlerFactory::getInstance()->handler()->sendMouseButtonEvent(slot, pressed); } else if ((device == JoyButtonSlot::JoyTextEntry) && pressed && !slot->getTextData().isEmpty()) { EventHandlerFactory::getInstance()->handler()->sendTextEntryEvent(slot->getTextData()); } else if ((device == JoyButtonSlot::JoyExecute) && pressed && !slot->getTextData().isEmpty()) { if (slot->getExtraData().canConvert()) { QString argumentsString = slot->getExtraData().toString(); // QStringList argumentsTempList(PadderCommon::parseArgumentsString(argumentsString)); bool success = QProcess::startDetached(QString("%1 %2 %3") .arg(detectedScriptExt(slot->getTextData())) .arg(slot->getTextData()) .arg(argumentsString)); if (!success) qDebug() << "Script cannot be executed"; } else { bool success = QProcess::startDetached( QString("%1 %2").arg(detectedScriptExt(slot->getTextData())).arg(slot->getTextData())); if (!success) qDebug() << "Script cannot be executed"; } } } QString detectedScriptExt(QString file) { QFileInfo fileinfo(file); QFile inputFile(file); QString firstLine = QString(); if (inputFile.open(QIODevice::ReadOnly)) { QTextStream in(&inputFile); firstLine = in.readLine(); inputFile.close(); } /* * shell scripts work, but I am not sure about other extensions * neither start method form QProcess nor QProcess::startDetached * don't work as expected * need to find another way */ if (fileinfo.completeSuffix() == "sh" || firstLine.contains("bin/bash")) return "/bin/sh"; else if (fileinfo.completeSuffix() == "py" && firstLine.contains("python3")) return "python3"; else if (fileinfo.completeSuffix() == "py" && firstLine.contains("python")) return "python"; else if (fileinfo.completeSuffix() == "pl" || firstLine.contains("usr/bin/perl")) return "perl"; else if (fileinfo.completeSuffix() == "php" || firstLine.contains("/php")) return "php"; else if (fileinfo.completeSuffix() == "rb" || firstLine.contains("ruby")) return "ruby"; // when run "chmod +x file_name" return ""; } // Create the relative mouse event used by the operating system. void sendevent(int code1, int code2) { qInstallMessageHandler(MessageHandler::myMessageOutput); EventHandlerFactory::getInstance()->handler()->sendMouseEvent(code1, code2); } // TODO: Re-implement spring event generation to simplify the process // and reduce overhead. Refactor old function to only be used when an absmouse // position must be faked. void sendSpringEventRefactor(PadderCommon::springModeInfo *fullSpring, PadderCommon::springModeInfo *relativeSpring, int *const mousePosX, int *const mousePosY) { Q_UNUSED(relativeSpring) Q_UNUSED(mousePosX) Q_UNUSED(mousePosY) qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::mouseHelperObj.mouseTimer.stop(); if (fullSpring != nullptr) { int xmovecoor = 0; int ymovecoor = 0; double displacementX = 0.0; double displacementY = 0.0; PadderCommon::mouseHelperObj.mouseTimer.stop(); BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if ((fullSpring->screen >= -1) && (fullSpring->screen >= PadderCommon::mouseHelperObj.getDesktopWidget()->screenCount())) { fullSpring->screen = -1; } int springWidth = fullSpring->width; int springHeight = fullSpring->height; if ((springWidth >= 2) && (springHeight >= 2)) { displacementX = fullSpring->displacementX; displacementY = fullSpring->displacementY; } else { displacementX = fullSpring->displacementX; displacementY = fullSpring->displacementY; } if (relativeSpring && (relativeSpring->width >= 2) && (relativeSpring->height >= 2)) { int pivotX = 0; int pivotY = 0; if (PadderCommon::mouseHelperObj.pivotPoint[0] != -1) pivotX = PadderCommon::mouseHelperObj.pivotPoint[0]; if (PadderCommon::mouseHelperObj.pivotPoint[1] != -1) pivotY = PadderCommon::mouseHelperObj.pivotPoint[1]; if ((pivotX >= 0) && (pivotY >= 0)) { // Find a use for this routine in this context. int destRelativeWidth = relativeSpring->width; int destRelativeHeight = relativeSpring->height; int xRelativeMoovCoor = 0; int yRelativeMoovCoor = 0; if (relativeSpring->displacementX >= -1.0) xRelativeMoovCoor = (relativeSpring->displacementX * destRelativeWidth) / 2; if (relativeSpring->displacementY >= -1.0) yRelativeMoovCoor = (relativeSpring->displacementY * destRelativeHeight) / 2; xmovecoor += xRelativeMoovCoor; ymovecoor += yRelativeMoovCoor; } } if (handler->getIdentifier() == "xtest") { fakeAbsMouseCoordinates(displacementX, displacementY, springWidth, springHeight, xmovecoor, ymovecoor, fullSpring->screen); } else if (handler->getIdentifier() == "uinput") { fakeAbsMouseCoordinates(displacementX, displacementY, springWidth, springHeight, xmovecoor, ymovecoor, fullSpring->screen); } } else { PadderCommon::mouseHelperObj.springMouseMoving = false; PadderCommon::mouseHelperObj.pivotPoint[0] = -1; PadderCommon::mouseHelperObj.pivotPoint[1] = -1; } } // TODO: Change to only use this routine when using a relative mouse // pointer to fake absolute mouse moves. Otherwise, don't worry about // current position of the mouse and just send an absolute mouse pointer // event. void sendSpringEvent(PadderCommon::springModeInfo *fullSpring, PadderCommon::springModeInfo *relativeSpring, int *const mousePosX, int *const mousePosY) { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::mouseHelperObj.mouseTimer.stop(); if (((fullSpring->displacementX >= -2.0) && (fullSpring->displacementX <= 1.0) && (fullSpring->displacementY >= -2.0) && (fullSpring->displacementY <= 1.0)) || (relativeSpring && ((relativeSpring->displacementX >= -2.0) && (relativeSpring->displacementX <= 1.0) && (relativeSpring->displacementY >= -2.0) && (relativeSpring->displacementY <= 1.0)))) { int xmovecoor = 0; int ymovecoor = 0; int width = 0; int height = 0; int midwidth = 0; int midheight = 0; int destSpringWidth = 0; int destSpringHeight = 0; int destMidWidth = 0; int destMidHeight = 0; int currentMouseX = 0; int currentMouseY = 0; if ((fullSpring->screen >= -1) && (fullSpring->screen >= PadderCommon::mouseHelperObj.getDesktopWidget()->screenCount())) { fullSpring->screen = -1; } QRect deskRect = PadderCommon::mouseHelperObj.getDesktopWidget()->screenGeometry(fullSpring->screen); width = deskRect.width(); height = deskRect.height(); #if defined(WITH_X11) QPoint currentPoint; if (QApplication::platformName() == QStringLiteral("xcb")) { currentPoint = X11Extras::getInstance()->getPos(); } else { currentPoint = QCursor::pos(); } #endif currentMouseX = currentPoint.x(); currentMouseY = currentPoint.y(); midwidth = width / 2; midheight = height / 2; int springWidth = fullSpring->width; int springHeight = fullSpring->height; if ((springWidth >= 2) && (springHeight >= 2)) { destSpringWidth = qMin(springWidth, width); destSpringHeight = qMin(springHeight, height); } else { destSpringWidth = width; destSpringHeight = height; } destMidWidth = destSpringWidth / 2; destMidHeight = destSpringHeight / 2; int pivotX = currentMouseX; int pivotY = currentMouseY; if (relativeSpring != nullptr) { if (PadderCommon::mouseHelperObj.pivotPoint[0] != -1) { pivotX = PadderCommon::mouseHelperObj.pivotPoint[0]; } else { pivotX = currentMouseX; } if (PadderCommon::mouseHelperObj.pivotPoint[1] != -1) { pivotY = PadderCommon::mouseHelperObj.pivotPoint[1]; } else { pivotY = currentMouseY; } } xmovecoor = (fullSpring->displacementX >= -1.0) ? (midwidth + (fullSpring->displacementX * destMidWidth) + deskRect.x()) : pivotX; ymovecoor = (fullSpring->displacementY >= -1.0) ? (midheight + (fullSpring->displacementY * destMidHeight) + deskRect.y()) : pivotY; int fullSpringDestX = xmovecoor; int fullSpringDestY = ymovecoor; int destRelativeWidth = 0; int destRelativeHeight = 0; if ((relativeSpring != nullptr) && (relativeSpring->width >= 2) && (relativeSpring->height >= 2)) { destRelativeWidth = relativeSpring->width; destRelativeHeight = relativeSpring->height; int xRelativeMoovCoor = 0; int yRelativeMoovCoor = 0; if (relativeSpring->displacementX >= -1.0) xRelativeMoovCoor = (relativeSpring->displacementX * destRelativeWidth) / 2; if (relativeSpring->displacementY >= -1.0) yRelativeMoovCoor = (relativeSpring->displacementY * destRelativeHeight) / 2; xmovecoor += xRelativeMoovCoor; ymovecoor += yRelativeMoovCoor; } if (mousePosX) *mousePosX = xmovecoor; if (mousePosY) *mousePosY = ymovecoor; if ((xmovecoor != currentMouseX) || (ymovecoor != currentMouseY)) { double diffx = abs(currentMouseX - xmovecoor); double diffy = abs(currentMouseY - ymovecoor); // If either position is set to center, force update. if ((xmovecoor == (deskRect.x() + midwidth)) || (ymovecoor == (deskRect.y() + midheight))) { BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (fullSpring->screen <= -1) { if (handler->getIdentifier() == "xtest") { EventHandlerFactory::getInstance()->handler()->sendMouseAbsEvent(xmovecoor, ymovecoor, -1); } else if (handler->getIdentifier() == "uinput") { EventHandlerFactory::getInstance()->handler()->sendMouseSpringEvent( xmovecoor, ymovecoor, width + deskRect.x(), height + deskRect.y()); } } else { EventHandlerFactory::getInstance()->handler()->sendMouseEvent(xmovecoor - currentMouseX, ymovecoor - currentMouseY); } } else if (!PadderCommon::mouseHelperObj.springMouseMoving && relativeSpring && ((relativeSpring->displacementX >= -1.0) || (relativeSpring->displacementY >= -1.0)) && ((diffx >= (destRelativeWidth * .013)) || (diffy >= (destRelativeHeight * .013)))) { PadderCommon::mouseHelperObj.springMouseMoving = true; BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (fullSpring->screen <= -1) { if (handler->getIdentifier() == "xtest") { EventHandlerFactory::getInstance()->handler()->sendMouseAbsEvent(xmovecoor, ymovecoor, -1); } else if (handler->getIdentifier() == "uinput") { EventHandlerFactory::getInstance()->handler()->sendMouseSpringEvent( xmovecoor, ymovecoor, width + deskRect.x(), height + deskRect.y()); } } else { EventHandlerFactory::getInstance()->handler()->sendMouseEvent(xmovecoor - currentMouseX, ymovecoor - currentMouseY); } PadderCommon::mouseHelperObj.mouseTimer.start( qMax(GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::gamepadRefreshRate) + 1); } else if (!PadderCommon::mouseHelperObj.springMouseMoving && ((diffx >= (destSpringWidth * .013)) || (diffy >= (destSpringHeight * .013)))) { PadderCommon::mouseHelperObj.springMouseMoving = true; BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (fullSpring->screen <= -1) { if (handler->getIdentifier() == "xtest") { EventHandlerFactory::getInstance()->handler()->sendMouseAbsEvent(xmovecoor, ymovecoor, -1); } else if (handler->getIdentifier() == "uinput") { EventHandlerFactory::getInstance()->handler()->sendMouseSpringEvent( xmovecoor, ymovecoor, width + deskRect.x(), height + deskRect.y()); } } else { EventHandlerFactory::getInstance()->handler()->sendMouseEvent(xmovecoor - currentMouseX, ymovecoor - currentMouseY); } PadderCommon::mouseHelperObj.mouseTimer.start( qMax(GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::gamepadRefreshRate) + 1); } else if (PadderCommon::mouseHelperObj.springMouseMoving && ((diffx < 2) && (diffy < 2))) { PadderCommon::mouseHelperObj.springMouseMoving = false; } else if (PadderCommon::mouseHelperObj.springMouseMoving) { BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (fullSpring->screen <= -1) { if (handler->getIdentifier() == "xtest") { EventHandlerFactory::getInstance()->handler()->sendMouseAbsEvent(xmovecoor, ymovecoor, -1); } else if (handler->getIdentifier() == "uinput") { EventHandlerFactory::getInstance()->handler()->sendMouseSpringEvent( xmovecoor, ymovecoor, width + deskRect.x(), height + deskRect.y()); } } else { EventHandlerFactory::getInstance()->handler()->sendMouseEvent(xmovecoor - currentMouseX, ymovecoor - currentMouseY); } PadderCommon::mouseHelperObj.mouseTimer.start( qMax(GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::gamepadRefreshRate) + 1); } PadderCommon::mouseHelperObj.previousCursorLocation[0] = currentMouseX; PadderCommon::mouseHelperObj.previousCursorLocation[1] = currentMouseY; PadderCommon::mouseHelperObj.pivotPoint[0] = fullSpringDestX; PadderCommon::mouseHelperObj.pivotPoint[1] = fullSpringDestY; } else if ((PadderCommon::mouseHelperObj.previousCursorLocation[0] == xmovecoor) && (PadderCommon::mouseHelperObj.previousCursorLocation[1] == ymovecoor)) { PadderCommon::mouseHelperObj.springMouseMoving = false; } else { PadderCommon::mouseHelperObj.previousCursorLocation[0] = currentMouseX; PadderCommon::mouseHelperObj.previousCursorLocation[1] = currentMouseY; PadderCommon::mouseHelperObj.pivotPoint[0] = fullSpringDestX; PadderCommon::mouseHelperObj.pivotPoint[1] = fullSpringDestY; PadderCommon::mouseHelperObj.mouseTimer.start( qMax(GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::gamepadRefreshRate) + 1); } } else { PadderCommon::mouseHelperObj.springMouseMoving = false; PadderCommon::mouseHelperObj.pivotPoint[0] = -1; PadderCommon::mouseHelperObj.pivotPoint[1] = -1; } } int X11KeySymToKeycode(QString key) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempcode = 0; BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (key.length() > 0) { #ifdef WITH_XTEST if (handler->getIdentifier() == "xtest") { Display *display = X11Extras::getInstance()->display(); tempcode = XKeysymToKeycode(display, XStringToKeysym(key.toUtf8().data())); } #endif #ifdef WITH_UINPUT if (handler->getIdentifier() == "uinput") { tempcode = UInputHelper::getInstance()->getVirtualKey(key); } #endif } return tempcode; } QString keycodeToKeyString(int keycode, int alias) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString newkey = QString(); Q_UNUSED(alias) qDebug() << "keycode is: " << keycode; if (keycode <= 0) { newkey = "[NO KEY]"; } else { BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); #ifdef WITH_XTEST if (handler->getIdentifier() == "xtest") { Display *display = X11Extras::getInstance()->display(); newkey = QString("0x%1").arg(keycode, 0, 16); QString tempkey = XKeysymToString(XkbKeycodeToKeysym(display, static_cast(keycode), 0, 0)); QString tempalias = X11Extras::getInstance()->getDisplayString(tempkey); if (!tempalias.isEmpty()) { newkey = tempalias; } else { XKeyPressedEvent tempevent; tempevent.keycode = keycode; tempevent.type = KeyPress; tempevent.display = display; tempevent.state = 0; char tempstring[256]; memset(tempstring, 0, sizeof(tempstring)); int bitestoreturn = sizeof(tempstring) - 1; int numchars = XLookupString(&tempevent, tempstring, bitestoreturn, nullptr, nullptr); if (numchars > 0) { tempstring[numchars] = '\0'; newkey = QString::fromUtf8(tempstring); qDebug() << "NEWKEY:" << newkey << endl; qDebug() << "NEWKEY LEGNTH:" << numchars << endl; } else { newkey = tempkey; } } } #endif #ifdef WITH_UINPUT if (handler->getIdentifier() == "uinput") { QString tempalias = UInputHelper::getInstance()->getDisplayString(keycode); if (!tempalias.isEmpty()) newkey = tempalias; else newkey = QString("0x%1").arg(keycode, 0, 16); } #endif } return newkey; } int X11KeyCodeToX11KeySym(int keycode) { qInstallMessageHandler(MessageHandler::myMessageOutput); #ifdef WITH_X11 Display *display = X11Extras::getInstance()->display(); return XkbKeycodeToKeysym(display, static_cast(keycode), 0, 0); #else Q_UNUSED(keycode) return 0; #endif } QString keysymToKeyString(int keysym, int alias) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString newkey = QString(); #ifdef WITH_X11 Q_UNUSED(alias) BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (handler->getIdentifier() == "xtest") { Display *display = X11Extras::getInstance()->display(); int keycode = 0; if (keysym > 0) keycode = XKeysymToKeycode(display, static_cast(keysym)); newkey = keycodeToKeyString(keycode); } else if (handler->getIdentifier() == "uinput") { newkey = keycodeToKeyString(keysym); } #else newkey = keycodeToKeyString(keysym, alias); #endif return newkey; } void sendKeybEvent(JoyButtonSlot *slot, bool pressed) { EventHandlerFactory::getInstance()->handler()->sendKeyboardEvent(slot, pressed); } AntiMicroX-antimicrox-2888bf6/src/event.h000066400000000000000000000035371377703515000203540ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef EVENT_H #define EVENT_H #include "common.h" #include "joybuttonslot.h" #include "springmousemoveinfo.h" void sendevent(JoyButtonSlot *slot, bool pressed = true); void sendevent(int code1, int code2); void sendKeybEvent(JoyButtonSlot *slot, bool pressed = true); void sendSpringEventRefactor(PadderCommon::springModeInfo *fullSpring, PadderCommon::springModeInfo *relativeSpring = 0, int *const mousePosX = 0, int *const mousePos = 0); void sendSpringEvent(PadderCommon::springModeInfo *fullSpring, PadderCommon::springModeInfo *relativeSpring = 0, int *const mousePosX = 0, int *const mousePos = 0); void fakeAbsMouseCoordinates(double springX, double springY, int width, int height, int &finalx, int &finaly, int screen = -1); QString detectedScriptExt(QString file); int X11KeySymToKeycode(QString key); QString keycodeToKeyString(int keycode, int alias = 0); int X11KeyCodeToX11KeySym(int keycode); QString keysymToKeyString(int keysym, int alias = 0); #endif // EVENT_H AntiMicroX-antimicrox-2888bf6/src/eventhandlerfactory.cpp000066400000000000000000000067711377703515000236400ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "eventhandlerfactory.h" #include "eventhandlers/baseeventhandler.h" #include "messagehandler.h" #include #include static QHash buildDisplayNames() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temp; temp.insert("xtest", "Xtest"); temp.insert("uinput", "uinput"); return temp; } QHash handlerDisplayNames = buildDisplayNames(); EventHandlerFactory *EventHandlerFactory::instance = nullptr; EventHandlerFactory::EventHandlerFactory(QString handler, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); #ifdef WITH_UINPUT if (handler == "uinput") eventHandler = new UInputEventHandler(this); #endif #ifdef WITH_XTEST if (handler == "xtest") eventHandler = new XTestEventHandler(this); #endif } EventHandlerFactory::~EventHandlerFactory() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (eventHandler != nullptr) { delete eventHandler; eventHandler = nullptr; } } EventHandlerFactory *EventHandlerFactory::getInstance(QString handler) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (instance == nullptr) { QStringList temp = buildEventGeneratorList(); if (!handler.isEmpty() && temp.contains(handler)) instance = new EventHandlerFactory(handler); else instance = new EventHandlerFactory(fallBackIdentifier()); } return instance; } void EventHandlerFactory::deleteInstance() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (instance != nullptr) { delete instance; instance = nullptr; } } BaseEventHandler *EventHandlerFactory::handler() { qInstallMessageHandler(MessageHandler::myMessageOutput); return eventHandler; } QString EventHandlerFactory::fallBackIdentifier() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); #if defined(WITH_XTEST) temp = "xtest"; #elif defined(WITH_UINPUT) temp = "uinput"; #else temp = "xtest"; #endif return temp; } QStringList EventHandlerFactory::buildEventGeneratorList() { qInstallMessageHandler(MessageHandler::myMessageOutput); QStringList temp = QStringList(); temp.append("xtest"); temp.append("uinput"); return temp; } QString EventHandlerFactory::handlerDisplayName(QString handler) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString handlerDispName = QString(); if (handlerDisplayNames.contains(handler)) handlerDispName = handlerDisplayNames.value(handler); return handlerDispName; } AntiMicroX-antimicrox-2888bf6/src/eventhandlerfactory.h000066400000000000000000000037111377703515000232740ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef EVENTHANDLERFACTORY_H #define EVENTHANDLERFACTORY_H #include #include #ifdef WITH_UINPUT #include "eventhandlers/uinputeventhandler.h" #endif #ifdef WITH_XTEST #include "eventhandlers/xtesteventhandler.h" #endif #ifdef WITH_XTEST #define ADD_XTEST 1 #else #define ADD_XTEST 0 #endif #ifdef WITH_UINPUT #define ADD_UINPUT 1 #else #define ADD_UINPUT 0 #endif #define NUM_BACKENDS (ADD_XTEST + ADD_UINPUT) #if (NUM_BACKENDS > 1) #define BACKEND_ELSE_IF else if #else #define BACKEND_ELSE_IF if #endif class BaseEventHandler; class EventHandlerFactory : public QObject { Q_OBJECT public: static EventHandlerFactory *getInstance(QString handler = ""); void deleteInstance(); BaseEventHandler *handler(); static QString fallBackIdentifier(); static QStringList buildEventGeneratorList(); static QString handlerDisplayName(QString handler); protected: explicit EventHandlerFactory(QString handler, QObject *parent = nullptr); ~EventHandlerFactory(); BaseEventHandler *eventHandler; static EventHandlerFactory *instance; }; #endif // EVENTHANDLERFACTORY_H AntiMicroX-antimicrox-2888bf6/src/eventhandlers/000077500000000000000000000000001377703515000217145ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/eventhandlers/baseeventhandler.cpp000066400000000000000000000055011377703515000257330ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "baseeventhandler.h" #include "joybuttonslot.h" #include "messagehandler.h" #include BaseEventHandler::BaseEventHandler(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } BaseEventHandler::~BaseEventHandler() { qInstallMessageHandler(MessageHandler::myMessageOutput); } QString BaseEventHandler::getErrorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return lastErrorString; } /** * @brief Do nothing by default. Allow child classes to specify text to output * to a text stream. */ void BaseEventHandler::printPostMessages() { qInstallMessageHandler(MessageHandler::myMessageOutput); } /** * @brief Do nothing by default. Useful for child classes to define behavior. * @param Displacement of X coordinate * @param Displacement of Y coordinate * @param Screen number or -1 to use default */ void BaseEventHandler::sendMouseAbsEvent(int xDis, int yDis, int screen) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(xDis); Q_UNUSED(yDis); Q_UNUSED(screen); } /** * @brief Do nothing by default. Useful for child classes to define behavior. * @param Displacement of X coordinate * @param Displacement of Y coordinate * @param Bounding box width * @param Bounding box height */ void BaseEventHandler::sendMouseSpringEvent(int xDis, int yDis, int width, int height) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(xDis); Q_UNUSED(yDis); Q_UNUSED(width); Q_UNUSED(height); } /** * @brief Do nothing by default. Useful for child classes to define behavior. * @param Displacement of X coordinate * @param Displacement of Y coordinate */ void BaseEventHandler::sendMouseSpringEvent(int xDis, int yDis) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(xDis); Q_UNUSED(yDis); } void BaseEventHandler::sendTextEntryEvent(QString maintext) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(maintext); } AntiMicroX-antimicrox-2888bf6/src/eventhandlers/baseeventhandler.h000066400000000000000000000034521377703515000254030ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BASEEVENTHANDLER_H #define BASEEVENTHANDLER_H #include class JoyButtonSlot; class BaseEventHandler : public QObject { Q_OBJECT public: explicit BaseEventHandler(QObject *parent = nullptr); virtual ~BaseEventHandler(); virtual bool init() = 0; virtual bool cleanup() = 0; virtual void sendKeyboardEvent(JoyButtonSlot *slot, bool pressed) = 0; virtual void sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed) = 0; virtual void sendMouseEvent(int xDis, int yDis) = 0; virtual void sendMouseAbsEvent(int xDis, int yDis, int screen); virtual void sendMouseSpringEvent(int xDis, int yDis, int width, int height); virtual void sendMouseSpringEvent(int xDis, int yDis); virtual void sendTextEntryEvent(QString maintext); virtual QString getName() = 0; virtual QString getIdentifier() = 0; virtual void printPostMessages(); QString getErrorString(); protected: QString lastErrorString; }; #endif // BASEEVENTHANDLER_H AntiMicroX-antimicrox-2888bf6/src/eventhandlers/uinputeventhandler.cpp000066400000000000000000000411671377703515000263550ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const QString mouseDeviceName = PadderCommon::mouseDeviceName; static const QString keyboardDeviceName = PadderCommon::keyboardDeviceName; static const QString springMouseDeviceName = PadderCommon::springMouseDeviceName; #ifdef WITH_X11 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include #endif #include #endif #include "messagehandler.h" #include "uinputeventhandler.h" UInputEventHandler::UInputEventHandler(QObject *parent) : BaseEventHandler(parent) { keyboardFileHandler = 0; mouseFileHandler = 0; springMouseFileHandler = 0; } UInputEventHandler::~UInputEventHandler() { cleanupUinputEvHand(); } /** * @brief Initialize keyboard and mouse virtual devices. Each device will * use its own file handle with various codes set to distinquish the two * devices. * @return */ bool UInputEventHandler::init() { bool result = true; // Open file handle for keyboard emulation. initDevice(keyboardFileHandler, "keyboardFileHandler", result); // two separate statements for "result" are needed anyway because of possible changing its // statement in "initDevice" method if (result) { // Open mouse file handle to use for relative mouse emulation. initDevice(mouseFileHandler, "mouseFileHandler", result); } if (result) { // Open mouse file handle to use for absolute mouse emulation. initDevice(springMouseFileHandler, "springMouseFileHandler", result); } #ifdef WITH_X11 if (result) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) if (QApplication::platformName() == QStringLiteral("xcb")) { #endif // Some time needs to elapse after device creation before changing // pointer settings. Otherwise, settings will not take effect. QTimer::singleShot(2000, this, SLOT(x11ResetMouseAccelerationChange())); #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) } #endif } #endif return result; } void UInputEventHandler::initDevice(int &device, QString name, bool &result) { device = openUInputHandle(); if (device > 0) { if (name == "springMouseFileHandler") { setSpringMouseEvents(device); createUInputSpringMouseDevice(device); } else if (name == "mouseFileHandler") { setRelMouseEvents(device); createUInputMouseDevice(device); } else if (name == "keyboardFileHandler") { setKeyboardEvents(device); populateKeyCodes(device); createUInputKeyboardDevice(device); } } else { result = false; } } #ifdef WITH_X11 void UInputEventHandler::x11ResetMouseAccelerationChange() { if (X11Extras::getInstance()) { X11Extras::getInstance()->x11ResetMouseAccelerationChange(); } } #endif bool UInputEventHandler::cleanup() { return cleanupUinputEvHand(); } bool UInputEventHandler::cleanupUinputEvHand() { if (keyboardFileHandler > 0) { closeUInputDevice(keyboardFileHandler); keyboardFileHandler = 0; } if (mouseFileHandler > 0) { closeUInputDevice(mouseFileHandler); mouseFileHandler = 0; } if (springMouseFileHandler > 0) { closeUInputDevice(springMouseFileHandler); springMouseFileHandler = 0; } return true; } void UInputEventHandler::sendKeyboardEvent(JoyButtonSlot *slot, bool pressed) { JoyButtonSlot::JoySlotInputAction device = slot->getSlotMode(); int code = slot->getSlotCode(); if (device == JoyButtonSlot::JoyKeyboard) { write_uinput_event(keyboardFileHandler, EV_KEY, code, pressed ? 1 : 0); } } void UInputEventHandler::sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed) { JoyButtonSlot::JoySlotInputAction device = slot->getSlotMode(); int code = slot->getSlotCode(); if (device == JoyButtonSlot::JoyMouseButton) { if (code <= 3) { unsigned int tempcode = BTN_LEFT; switch (code) { case 3: { tempcode = BTN_RIGHT; break; } case 2: { tempcode = BTN_MIDDLE; break; } case 1: default: { tempcode = BTN_LEFT; } } write_uinput_event(mouseFileHandler, EV_KEY, tempcode, pressed ? 1 : 0); } else if (code == 4) { if (pressed) { write_uinput_event(mouseFileHandler, EV_REL, REL_WHEEL, 1); } } else if (code == 5) { if (pressed) { write_uinput_event(mouseFileHandler, EV_REL, REL_WHEEL, -1); } } else if (code == 6) { if (pressed) { write_uinput_event(mouseFileHandler, EV_REL, REL_HWHEEL, 1); } } else if (code == 7) { if (pressed) { write_uinput_event(mouseFileHandler, EV_REL, REL_HWHEEL, -1); } } else if (code == 8) { write_uinput_event(mouseFileHandler, EV_KEY, BTN_SIDE, pressed ? 1 : 0); } else if (code == 9) { write_uinput_event(mouseFileHandler, EV_KEY, BTN_EXTRA, pressed ? 1 : 0); } } } void UInputEventHandler::sendMouseEvent(int xDis, int yDis) { write_uinput_event(mouseFileHandler, EV_REL, REL_X, xDis, false); write_uinput_event(mouseFileHandler, EV_REL, REL_Y, yDis); } void UInputEventHandler::sendMouseAbsEvent(int xDis, int yDis, int screen) { Q_UNUSED(screen); write_uinput_event(springMouseFileHandler, EV_ABS, ABS_X, xDis, false); write_uinput_event(springMouseFileHandler, EV_ABS, ABS_Y, yDis); } void UInputEventHandler::sendMouseSpringEvent(int xDis, int yDis, int width, int height) { if ((width > 0) && (height > 0)) { double midwidth = width / 2.0; double midheight = height / 2.0; int fx = ceil(32767 * ((xDis - midwidth) / midwidth)); int fy = ceil(32767 * ((yDis - midheight) / midheight)); sendMouseAbsEvent(fx, fy, -1); } } void UInputEventHandler::sendMouseSpringEvent(int xDis, int yDis) { if ((xDis >= -1.0) && (xDis <= 1.0) && (yDis >= -1.0) && (yDis <= 1.0)) { int fx = ceil(32767 * xDis); int fy = ceil(32767 * yDis); sendMouseAbsEvent(fx, fy, -1); } } int UInputEventHandler::openUInputHandle() { int filehandle = -1; QStringList locations; locations.append("/dev/input/uinput"); locations.append("/dev/uinput"); locations.append("/dev/misc/uinput"); QString possibleLocation; QStringListIterator iter(locations); while (iter.hasNext()) { QString temp = iter.next(); QFileInfo tempFileInfo(temp); if (tempFileInfo.exists()) { possibleLocation = temp; iter.toBack(); } } if (possibleLocation.isEmpty()) { lastErrorString = tr("Could not find a valid uinput device file.\n" "Please check that you have the uinput module loaded.\n" "lsmod | grep uinput"); } else { QByteArray tempArray = possibleLocation.toUtf8(); filehandle = open(tempArray.constData(), O_WRONLY | O_NONBLOCK); if (filehandle < 0) { lastErrorString = tr("Could not open uinput device file\n" "Please check that you have permission to write to the device"); lastErrorString.append("\n").append(possibleLocation); } else { uinputDeviceLocation = possibleLocation; } } return filehandle; } void UInputEventHandler::setKeyboardEvents(int filehandle) { ioctl(filehandle, UI_SET_EVBIT, EV_KEY); ioctl(filehandle, UI_SET_EVBIT, EV_SYN); } void UInputEventHandler::setRelMouseEvents(int filehandle) { ioctl(filehandle, UI_SET_EVBIT, EV_KEY); ioctl(filehandle, UI_SET_EVBIT, EV_SYN); ioctl(filehandle, UI_SET_EVBIT, EV_REL); ioctl(filehandle, UI_SET_RELBIT, REL_X); ioctl(filehandle, UI_SET_RELBIT, REL_Y); ioctl(filehandle, UI_SET_RELBIT, REL_WHEEL); ioctl(filehandle, UI_SET_RELBIT, REL_HWHEEL); ioctl(filehandle, UI_SET_KEYBIT, BTN_LEFT); ioctl(filehandle, UI_SET_KEYBIT, BTN_RIGHT); ioctl(filehandle, UI_SET_KEYBIT, BTN_MIDDLE); ioctl(filehandle, UI_SET_KEYBIT, BTN_SIDE); ioctl(filehandle, UI_SET_KEYBIT, BTN_EXTRA); } void UInputEventHandler::setSpringMouseEvents(int filehandle) { ioctl(filehandle, UI_SET_EVBIT, EV_KEY); ioctl(filehandle, UI_SET_EVBIT, EV_SYN); ioctl(filehandle, UI_SET_KEYBIT, BTN_LEFT); ioctl(filehandle, UI_SET_KEYBIT, BTN_RIGHT); ioctl(filehandle, UI_SET_KEYBIT, BTN_MIDDLE); ioctl(filehandle, UI_SET_KEYBIT, BTN_SIDE); ioctl(filehandle, UI_SET_KEYBIT, BTN_EXTRA); ioctl(filehandle, UI_SET_EVBIT, EV_ABS); ioctl(filehandle, UI_SET_ABSBIT, ABS_X); ioctl(filehandle, UI_SET_ABSBIT, ABS_Y); ioctl(filehandle, UI_SET_KEYBIT, BTN_TOUCH); // BTN_TOOL_PEN is required for the mouse to be seen as an // absolute mouse as opposed to a relative mouse. ioctl(filehandle, UI_SET_KEYBIT, BTN_TOOL_PEN); } void UInputEventHandler::populateKeyCodes(int filehandle) { for (unsigned int i = KEY_ESC; i <= KEY_MICMUTE; i++) { ioctl(filehandle, UI_SET_KEYBIT, i); } } void UInputEventHandler::createUInputKeyboardDevice(int filehandle) { struct uinput_user_dev uidev; memset(&uidev, 0, sizeof(uidev)); QByteArray temp = keyboardDeviceName.toUtf8(); strncpy(uidev.name, temp.constData(), UINPUT_MAX_NAME_SIZE); uidev.id.bustype = BUS_USB; uidev.id.vendor = 0x0; uidev.id.product = 0x0; uidev.id.version = 1; write(filehandle, &uidev, sizeof(uidev)); ioctl(filehandle, UI_DEV_CREATE); } void UInputEventHandler::createUInputMouseDevice(int filehandle) { struct uinput_user_dev uidev; memset(&uidev, 0, sizeof(uidev)); QByteArray temp = mouseDeviceName.toUtf8(); strncpy(uidev.name, temp.constData(), UINPUT_MAX_NAME_SIZE); uidev.id.bustype = BUS_USB; uidev.id.vendor = 0x0; uidev.id.product = 0x0; uidev.id.version = 1; write(filehandle, &uidev, sizeof(uidev)); ioctl(filehandle, UI_DEV_CREATE); } void UInputEventHandler::createUInputSpringMouseDevice(int filehandle) { struct uinput_user_dev uidev; memset(&uidev, 0, sizeof(uidev)); QByteArray temp = springMouseDeviceName.toUtf8(); strncpy(uidev.name, temp.constData(), UINPUT_MAX_NAME_SIZE); uidev.id.bustype = BUS_USB; uidev.id.vendor = 0x0; uidev.id.product = 0x0; uidev.id.version = 1; uidev.absmin[ABS_X] = -32767; uidev.absmax[ABS_X] = 32767; uidev.absflat[ABS_X] = 0; uidev.absmin[ABS_Y] = -32767; uidev.absmax[ABS_Y] = 32767; uidev.absflat[ABS_Y] = 0; write(filehandle, &uidev, sizeof(uidev)); ioctl(filehandle, UI_DEV_CREATE); } void UInputEventHandler::closeUInputDevice(int filehandle) { ioctl(filehandle, UI_DEV_DESTROY); close(filehandle); } void UInputEventHandler::write_uinput_event(int filehandle, int type, int code, int value, bool syn) { struct input_event ev; struct input_event ev2; memset(&ev, 0, sizeof(struct input_event)); gettimeofday(&ev.time, nullptr); ev.type = type; ev.code = code; ev.value = value; write(filehandle, &ev, sizeof(struct input_event)); if (syn) { memset(&ev2, 0, sizeof(struct input_event)); gettimeofday(&ev2.time, nullptr); ev2.type = EV_SYN; ev2.code = SYN_REPORT; ev2.value = 0; write(filehandle, &ev2, sizeof(struct input_event)); } } QString UInputEventHandler::getName() { return QString("uinput"); } QString UInputEventHandler::getIdentifier() { return getName(); } /** * @brief Print extra help messages to stdout. */ void UInputEventHandler::printPostMessages() { if (!lastErrorString.isEmpty()) { Logger::LogInfo(lastErrorString); } if (!uinputDeviceLocation.isEmpty()) { Logger::LogInfo(tr("Using uinput device file %1").arg(uinputDeviceLocation)); } } void UInputEventHandler::sendTextEntryEvent(QString maintext) { AntKeyMapper *mapper = AntKeyMapper::getInstance(); if ((mapper != nullptr) && mapper->getKeyMapper()) { QtUInputKeyMapper *keymapper = qobject_cast(mapper->getKeyMapper()); #ifdef WITH_X11 QtX11KeyMapper *nativeWinKeyMapper = nullptr; if (mapper->getNativeKeyMapper()) { nativeWinKeyMapper = qobject_cast(mapper->getNativeKeyMapper()); } #endif QList tempList; for (int i = 0; i < maintext.size(); i++) { tempList.clear(); QtUInputKeyMapper::charKeyInformation temp; temp.virtualkey = 0; temp.modifiers = Qt::NoModifier; #ifdef WITH_X11 if (nativeWinKeyMapper != nullptr) { QtX11KeyMapper::charKeyInformation tempX11 = nativeWinKeyMapper->getCharKeyInformation(maintext.at(i)); tempX11.virtualkey = X11Extras::getInstance()->getGroup1KeySym(tempX11.virtualkey); unsigned int tempQtKey = nativeWinKeyMapper->returnQtKey(tempX11.virtualkey); if (tempQtKey > 0) { temp.virtualkey = keymapper->returnVirtualKey(tempQtKey); temp.modifiers = tempX11.modifiers; } else { temp = keymapper->getCharKeyInformation(maintext.at(i)); } } else { #endif temp = keymapper->getCharKeyInformation(maintext.at(i)); #ifdef WITH_X11 } #endif if (temp.virtualkey > KEY_RESERVED) { if (temp.modifiers != Qt::NoModifier) { testAndAppend(temp.modifiers.testFlag(Qt::ShiftModifier), tempList, KEY_LEFTSHIFT); testAndAppend(temp.modifiers.testFlag(Qt::ControlModifier), tempList, KEY_LEFTCTRL); testAndAppend(temp.modifiers.testFlag(Qt::AltModifier), tempList, KEY_LEFTALT); testAndAppend(temp.modifiers.testFlag(Qt::MetaModifier), tempList, KEY_LEFTMETA); } tempList.append(temp.virtualkey); write_uinput_event(keyboardFileHandler, EV_KEY, temp.virtualkey, 1, true); } if (tempList.size() > 0) { QListIterator tempiter(tempList); tempiter.toBack(); while (tempiter.hasPrevious()) { unsigned int currentcode = tempiter.previous(); bool sync = !tempiter.hasPrevious() ? true : false; write_uinput_event(keyboardFileHandler, EV_KEY, currentcode, 0, sync); } } } } } void UInputEventHandler::testAndAppend(bool tested, QList &tempList, unsigned int key) { if (tested) { tempList.append(key); write_uinput_event(keyboardFileHandler, EV_KEY, key, 1, false); } } int UInputEventHandler::getKeyboardFileHandler() { return keyboardFileHandler; } int UInputEventHandler::getMouseFileHandler() { return mouseFileHandler; } int UInputEventHandler::getSpringMouseFileHandler() { return springMouseFileHandler; } const QString UInputEventHandler::getUinputDeviceLocation() { return uinputDeviceLocation; } AntiMicroX-antimicrox-2888bf6/src/eventhandlers/uinputeventhandler.h000066400000000000000000000055311377703515000260150ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UINPUTEVENTHANDLER_H #define UINPUTEVENTHANDLER_H #include "baseeventhandler.h" class UInputEventHandler : public BaseEventHandler { Q_OBJECT public: explicit UInputEventHandler(QObject *parent = nullptr); ~UInputEventHandler(); virtual bool init() override; virtual bool cleanup() override; virtual void sendKeyboardEvent(JoyButtonSlot *slot, bool pressed) override; virtual void sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed) override; virtual void sendMouseEvent(int xDis, int yDis) override; virtual void sendMouseAbsEvent(int xDis, int yDis, int screen) override; virtual void sendMouseSpringEvent(int xDis, int yDis, int width, int height) override; virtual void sendMouseSpringEvent(int xDis, int yDis) override; virtual QString getName() override; virtual QString getIdentifier() override; virtual void printPostMessages() override; virtual void sendTextEntryEvent(QString maintext) override; int getKeyboardFileHandler(); int getMouseFileHandler(); int getSpringMouseFileHandler(); const QString getUinputDeviceLocation(); protected: int openUInputHandle(); void setKeyboardEvents(int filehandle); void setRelMouseEvents(int filehandle); void setSpringMouseEvents(int filehandle); void populateKeyCodes(int filehandle); void createUInputKeyboardDevice(int filehandle); void createUInputMouseDevice(int filehandle); void createUInputSpringMouseDevice(int filehandle); void closeUInputDevice(int filehandle); void write_uinput_event(int filehandle, int type, int code, int value, bool syn = true); private slots: #ifdef WITH_X11 void x11ResetMouseAccelerationChange(); #endif private: int keyboardFileHandler; int mouseFileHandler; int springMouseFileHandler; QString uinputDeviceLocation; bool cleanupUinputEvHand(); void testAndAppend(bool tested, QList &tempList, unsigned int key); void initDevice(int &device, QString name, bool &result); }; #endif // UINPUTEVENTHANDLER_H AntiMicroX-antimicrox-2888bf6/src/eventhandlers/xtesteventhandler.cpp000066400000000000000000000154441377703515000261770ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "xtesteventhandler.h" #include "antkeymapper.h" #include "globalvariables.h" #include "joybuttonslot.h" #include "messagehandler.h" #include #include #include #include "x11extras.h" XTestEventHandler::XTestEventHandler(QObject *parent) : BaseEventHandler(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } XTestEventHandler::~XTestEventHandler() { qInstallMessageHandler(MessageHandler::myMessageOutput); } bool XTestEventHandler::init() { qInstallMessageHandler(MessageHandler::myMessageOutput); X11Extras *instance = X11Extras::getInstance(); if (instance != nullptr) { instance->x11ResetMouseAccelerationChange(GlobalVariables::X11Extras::xtestMouseDeviceName); } return true; } bool XTestEventHandler::cleanup() { qInstallMessageHandler(MessageHandler::myMessageOutput); return true; } void XTestEventHandler::sendKeyboardEvent(JoyButtonSlot *slot, bool pressed) { qInstallMessageHandler(MessageHandler::myMessageOutput); Display *display = X11Extras::getInstance()->display(); JoyButtonSlot::JoySlotInputAction device = slot->getSlotMode(); int code = slot->getSlotCode(); if (device == JoyButtonSlot::JoyKeyboard) { int tempcode = XKeysymToKeycode(display, static_cast(code)); if (tempcode > 0) { XTestFakeKeyEvent(display, tempcode, pressed, 0); XFlush(display); } } } void XTestEventHandler::sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed) { qInstallMessageHandler(MessageHandler::myMessageOutput); Display *display = X11Extras::getInstance()->display(); JoyButtonSlot::JoySlotInputAction device = slot->getSlotMode(); int code = slot->getSlotCode(); if (device == JoyButtonSlot::JoyMouseButton) { XTestFakeButtonEvent(display, code, pressed, 0); XFlush(display); } } void XTestEventHandler::sendMouseEvent(int xDis, int yDis) { qInstallMessageHandler(MessageHandler::myMessageOutput); Display *display = X11Extras::getInstance()->display(); XTestFakeRelativeMotionEvent(display, xDis, yDis, 0); XFlush(display); } void XTestEventHandler::sendMouseAbsEvent(int xDis, int yDis, int screen) { qInstallMessageHandler(MessageHandler::myMessageOutput); Display *display = X11Extras::getInstance()->display(); XTestFakeMotionEvent(display, screen, xDis, yDis, 0); XFlush(display); } QString XTestEventHandler::getName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return QString("XTest"); } QString XTestEventHandler::getIdentifier() { qInstallMessageHandler(MessageHandler::myMessageOutput); return QString("xtest"); } void XTestEventHandler::sendTextEntryEvent(QString maintext) { qInstallMessageHandler(MessageHandler::myMessageOutput); AntKeyMapper *mapper = AntKeyMapper::getInstance(); if ((mapper != nullptr) && mapper->getKeyMapper()) { Display *display = X11Extras::getInstance()->display(); QtX11KeyMapper *keymapper = qobject_cast(mapper->getKeyMapper()); for (int i = 0; i < maintext.size(); i++) { QtX11KeyMapper::charKeyInformation temp = keymapper->getCharKeyInformation(maintext.at(i)); int tempcode = XKeysymToKeycode(display, static_cast(temp.virtualkey)); if (tempcode > 0) { QList tempList; if ((temp.modifiers != Qt::NoModifier) && temp.modifiers.testFlag(Qt::ShiftModifier)) { int shiftcode = XKeysymToKeycode(display, XK_Shift_L); int modifiercode = shiftcode; XTestFakeKeyEvent(display, modifiercode, 1, 0); tempList.append(modifiercode); } if ((temp.modifiers != Qt::NoModifier) && temp.modifiers.testFlag(Qt::ControlModifier)) { int controlcode = XKeysymToKeycode(display, XK_Control_L); int modifiercode = controlcode; XTestFakeKeyEvent(display, modifiercode, 1, 0); tempList.append(modifiercode); } if ((temp.modifiers != Qt::NoModifier) && temp.modifiers.testFlag(Qt::AltModifier)) { int altcode = XKeysymToKeycode(display, XK_Alt_L); int modifiercode = altcode; XTestFakeKeyEvent(display, modifiercode, 1, 0); tempList.append(modifiercode); } if ((temp.modifiers != Qt::NoModifier) && temp.modifiers.testFlag(Qt::MetaModifier)) { int metacode = XKeysymToKeycode(display, XK_Meta_L); int modifiercode = metacode; XTestFakeKeyEvent(display, modifiercode, 1, 0); tempList.append(modifiercode); } XTestFakeKeyEvent(display, tempcode, 1, 0); tempList.append(tempcode); XFlush(display); if (tempList.size() > 0) { QListIterator tempiter(tempList); tempiter.toBack(); while (tempiter.hasPrevious()) { int currentcode = tempiter.previous(); XTestFakeKeyEvent(display, currentcode, 0, 0); } XFlush(display); } } } } } void XTestEventHandler::sendMouseSpringEvent(int xDis, int yDis, int width, int height) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(xDis); Q_UNUSED(yDis); Q_UNUSED(width); Q_UNUSED(height); } void XTestEventHandler::sendMouseSpringEvent(int, int) { qInstallMessageHandler(MessageHandler::myMessageOutput); } void XTestEventHandler::printPostMessages() { qInstallMessageHandler(MessageHandler::myMessageOutput); } AntiMicroX-antimicrox-2888bf6/src/eventhandlers/xtesteventhandler.h000066400000000000000000000033531377703515000256400ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XTESTEVENTHANDLER_H #define XTESTEVENTHANDLER_H #include "baseeventhandler.h" class JoyButtonSlot; class XTestEventHandler : public BaseEventHandler { Q_OBJECT public: explicit XTestEventHandler(QObject *parent = nullptr); virtual ~XTestEventHandler(); bool init() override; bool cleanup() override; void sendKeyboardEvent(JoyButtonSlot *slot, bool pressed) override; void sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed) override; void sendMouseEvent(int xDis, int yDis) override; void sendMouseAbsEvent(int xDis, int yDis, int screen) override; void sendMouseSpringEvent(int xDis, int yDis, int width, int height) override; void sendMouseSpringEvent(int xDis, int yDis) override; void sendTextEntryEvent(QString maintext) override; QString getName() override; QString getIdentifier() override; void printPostMessages() override; }; #endif // XTESTEVENTHANDLER_H AntiMicroX-antimicrox-2888bf6/src/extraprofilesettingsdialog.cpp000066400000000000000000000050201377703515000252200ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "extraprofilesettingsdialog.h" #include "ui_extraprofilesettingsdialog.h" #include "inputdevice.h" #include "messagehandler.h" #include ExtraProfileSettingsDialog::ExtraProfileSettingsDialog(InputDevice *device, QWidget *parent) : QDialog(parent) , ui(new Ui::ExtraProfileSettingsDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->device = device; ui->pressValueLabel->setText(QString::number(0.10, 'g', 3).append("").append(tr("s"))); if (device->getDeviceKeyPressTime() > 0) { int temppress = device->getDeviceKeyPressTime(); ui->keyPressHorizontalSlider->setValue(device->getDeviceKeyPressTime() / 10); ui->pressValueLabel->setText(QString::number(temppress / 1000.0, 'g', 3).append("").append(tr("s"))); } if (!device->getProfileName().isEmpty()) ui->profileNameLineEdit->setText(device->getProfileName()); connect(ui->keyPressHorizontalSlider, &QSlider::valueChanged, this, &ExtraProfileSettingsDialog::changeDeviceKeyPress); connect(ui->profileNameLineEdit, &QLineEdit::textChanged, device, &InputDevice::setProfileName); } ExtraProfileSettingsDialog::~ExtraProfileSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void ExtraProfileSettingsDialog::changeDeviceKeyPress(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int temppress = value * 10; device->setDeviceKeyPressTime(temppress); ui->pressValueLabel->setText(QString::number(temppress / 1000.0, 'g', 3).append("").append(tr("s"))); } InputDevice *ExtraProfileSettingsDialog::getDevice() const { return device; } AntiMicroX-antimicrox-2888bf6/src/extraprofilesettingsdialog.h000066400000000000000000000025501377703515000246720ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYDELAYDIALOG_H #define KEYDELAYDIALOG_H #include class InputDevice; class QWidget; namespace Ui { class ExtraProfileSettingsDialog; } class ExtraProfileSettingsDialog : public QDialog { Q_OBJECT public: explicit ExtraProfileSettingsDialog(InputDevice *device, QWidget *parent = nullptr); ~ExtraProfileSettingsDialog(); InputDevice *getDevice() const; private: Ui::ExtraProfileSettingsDialog *ui; InputDevice *device; private slots: void changeDeviceKeyPress(int value); }; #endif // KEYDELAYDIALOG_H AntiMicroX-antimicrox-2888bf6/src/extraprofilesettingsdialog.ui000066400000000000000000000075421377703515000250660ustar00rootroot00000000000000 ExtraProfileSettingsDialog 0 0 439 144 396 136 Extra Profile Settings true 10 10 20 0 Key Press Time: 1 100 10 Qt::Horizontal 0.00 ms 36 Profile Name: 50 Qt::Vertical QSizePolicy::Fixed 20 10 Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() ExtraProfileSettingsDialog accept() 248 254 157 274 buttonBox rejected() ExtraProfileSettingsDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/fakeclasses/000077500000000000000000000000001377703515000213365ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/fakeclasses/xbox360wireless.cpp000066400000000000000000000057051377703515000250400ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define MAKE_CONTROLLER_ID(nVID, nPID) (unsigned int)(nVID << 16 | nPID) #include "xbox360wireless.h" //#include "SDL-mirror/src/joystick/SDL_sysjoystick.h" Xbox360Wireless::Xbox360Wireless() { SDL_Joystick Xbox360; Xbox360.instance_id = 0; Xbox360.name = name(); Xbox360.player_index = 0; Xbox360.guid = joyGUID(); Xbox360.naxes = 6; Xbox360.nhats = 0; Xbox360.nbuttons = 15; // Xbox360.nballs = 0; if (Xbox360.naxes > 0) { Xbox360.axes = (SDL_JoystickAxisInfo *)SDL_calloc(Xbox360.naxes, sizeof(SDL_JoystickAxisInfo)); } if (Xbox360.nhats > 0) { Xbox360.hats = (Uint8 *)SDL_calloc(Xbox360.nhats, sizeof(Uint8)); } // if (Xbox360.nballs > 0) { // Xbox360.balls = (struct balldelta *) SDL_calloc(Xbox360.balls, sizeof(*Xbox360.balls)); // } if (Xbox360.nbuttons > 0) { Xbox360.buttons = (Uint8 *)SDL_calloc(Xbox360.nbuttons, sizeof(Uint8)); } Xbox360.attached = SDL_TRUE; Xbox360.is_game_controller = SDL_TRUE; Xbox360.epowerlevel = SDL_JOYSTICK_POWER_MEDIUM; Xbox360.ref_count = 1; Xbox360.next = NULL; // _SDL_JoystickDriver - it's faked class so there is no need to use detection from system level result = &Xbox360; } Xbox360Wireless::~Xbox360Wireless() { SDL_free(result->name); /* Free the data associated with this joystick */ SDL_free(result->axes); SDL_free(result->hats); SDL_free(result->balls); SDL_free(result->buttons); SDL_free(result); } char *Xbox360Wireless::GUID() { return "030000005e040000e002000000000000"; } char *Xbox360Wireless::name() { return "Xbox Wireless Controller"; } unsigned int Xbox360Wireless::deviceId() { return MAKE_CONTROLLER_ID(0x045e, 0x0291); } int Xbox360Wireless::controllerType() { return 31; // k_eControllerType_XBox360Controller } SDL_JoystickType Xbox360Wireless::joystickType() { return SDL_JoystickType::SDL_JOYSTICK_TYPE_GAMECONTROLLER; } SDL_JoystickGUID Xbox360Wireless::joyGUID() { return SDL_JoystickGetGUIDFromString(GUID()); } SDL_Joystick *Xbox360Wireless::getResult() { return result; } AntiMicroX-antimicrox-2888bf6/src/fakeclasses/xbox360wireless.h000066400000000000000000000061041377703515000244770ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XBOX360WIRELESS_H #define XBOX360WIRELESS_H #include typedef struct _SDL_JoystickAxisInfo { Sint16 initial_value; /* Initial axis state */ Sint16 value; /* Current axis state */ Sint16 zero; /* Zero point on the axis (-32768 for triggers) */ SDL_bool has_initial_value; /* Whether we've seen a value on the axis yet */ SDL_bool sent_initial_value; /* Whether we've sent the initial axis value */ } SDL_JoystickAxisInfo; struct _SDL_Joystick { SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */ char *name; /* Joystick name - system dependent */ int player_index; /* Joystick player index, or -1 if unavailable */ SDL_JoystickGUID guid; /* Joystick guid */ int naxes; /* Number of axis controls on the joystick */ SDL_JoystickAxisInfo *axes; int nhats; /* Number of hats on the joystick */ Uint8 *hats; /* Current hat states */ int nballs; /* Number of trackballs on the joystick */ struct balldelta { int dx; int dy; } * balls; /* Current ball motion deltas */ int nbuttons; /* Number of buttons on the joystick */ Uint8 *buttons; /* Current button states */ SDL_bool attached; SDL_bool is_game_controller; SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */ SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */ SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */ struct _SDL_JoystickDriver *driver; struct joystick_hwdata *hwdata; /* Driver dependent information */ int ref_count; /* Reference count for multiple opens */ struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */ }; class Xbox360Wireless { public: Xbox360Wireless(); ~Xbox360Wireless(); char *GUID(); char *name(); unsigned int deviceId(); int controllerType(); SDL_JoystickType joystickType(); SDL_JoystickGUID joyGUID(); SDL_Joystick *getResult(); private: SDL_Joystick *result; }; #endif AntiMicroX-antimicrox-2888bf6/src/flashbuttonwidget.cpp000066400000000000000000000101141377703515000233100ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "flashbuttonwidget.h" #include "messagehandler.h" #include #include #include #include #include #include FlashButtonWidget::FlashButtonWidget(QWidget *parent) : QPushButton(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); isflashing = false; m_displayNames = false; leftAlignText = false; } FlashButtonWidget::FlashButtonWidget(bool displayNames, QWidget *parent) : QPushButton(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); isflashing = false; m_displayNames = displayNames; leftAlignText = false; } void FlashButtonWidget::flash() { qInstallMessageHandler(MessageHandler::myMessageOutput); isflashing = true; this->style()->unpolish(this); this->style()->polish(this); emit flashed(isflashing); } void FlashButtonWidget::unflash() { qInstallMessageHandler(MessageHandler::myMessageOutput); isflashing = false; this->style()->unpolish(this); this->style()->polish(this); emit flashed(isflashing); } void FlashButtonWidget::refreshLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); setText(generateLabel()); qDebug() << "label has been set: " << generateLabel(); } bool FlashButtonWidget::isButtonFlashing() { qInstallMessageHandler(MessageHandler::myMessageOutput); return isflashing; } void FlashButtonWidget::toggleNameDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); m_displayNames = !m_displayNames; refreshLabel(); } void FlashButtonWidget::setDisplayNames(bool display) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_displayNames = display; } bool FlashButtonWidget::isDisplayingNames() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_displayNames; } void FlashButtonWidget::paintEvent(QPaintEvent *event) { // qInstallMessageHandler(MessageHandler::myMessageOutput); QPainter painter(this); QFont tempScaledFont = painter.font(); QFont temp; tempScaledFont.setPointSize(temp.pointSize()); QFontMetrics fm(tempScaledFont); bool reduce = false; while ((this->width() < fm.width(text())) && (tempScaledFont.pointSize() >= 7)) { tempScaledFont.setPointSize(tempScaledFont.pointSize() - 1); painter.setFont(tempScaledFont); fm = painter.fontMetrics(); reduce = true; } bool changeFontSize = this->font().pointSize() != tempScaledFont.pointSize(); if (changeFontSize) { if (reduce && !leftAlignText) { leftAlignText = !leftAlignText; setStyleSheet("text-align: left;"); this->style()->unpolish(this); this->style()->polish(this); } else if (!reduce && leftAlignText) { leftAlignText = !leftAlignText; setStyleSheet("text-align: center;"); this->style()->unpolish(this); this->style()->polish(this); } this->setFont(tempScaledFont); } QPushButton::paintEvent(event); } void FlashButtonWidget::retranslateUi() { qInstallMessageHandler(MessageHandler::myMessageOutput); refreshLabel(); } bool FlashButtonWidget::ifDisplayNames() { return m_displayNames; } AntiMicroX-antimicrox-2888bf6/src/flashbuttonwidget.h000066400000000000000000000034471377703515000227700ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FLASHBUTTONWIDGET_H #define FLASHBUTTONWIDGET_H #include class QWidget; class QPaintEvent; class FlashButtonWidget : public QPushButton { Q_OBJECT Q_PROPERTY(bool isflashing READ isButtonFlashing) public: explicit FlashButtonWidget(QWidget *parent = nullptr); explicit FlashButtonWidget(bool displayNames, QWidget *parent = nullptr); bool isButtonFlashing(); void setDisplayNames(bool display); bool isDisplayingNames(); protected: virtual void paintEvent(QPaintEvent *event); virtual QString generateLabel() = 0; virtual void retranslateUi(); bool ifDisplayNames(); signals: void flashed(bool flashing); public slots: void refreshLabel(); void toggleNameDisplay(); virtual void disableFlashes() = 0; virtual void enableFlashes() = 0; protected slots: void flash(); void unflash(); private: bool isflashing; bool m_displayNames; bool leftAlignText; }; #endif // FLASHBUTTONWIDGET_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/000077500000000000000000000000001377703515000220675ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontroller.cpp000066400000000000000000000303471377703515000256170ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gamecontroller.h" #include "antimicrosettings.h" #include "common.h" #include "gamecontrollerdpad.h" #include "gamecontrollerset.h" #include "globalvariables.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joycontrolstick.h" #include "messagehandler.h" //#include "logger.h" #include #include #include #include GameController::GameController(SDL_GameController *controller, int deviceIndex, AntiMicroSettings *settings, int counterUniques, QObject *parent) : InputDevice(SDL_GameControllerGetJoystick(controller), deviceIndex, settings, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->controller = controller; this->counterUniques = counterUniques; SDL_Joystick *joyhandle = SDL_GameControllerGetJoystick(controller); joystickID = SDL_JoystickInstanceID(joyhandle); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { GameControllerSet *controllerset = new GameControllerSet(this, i, this); getJoystick_sets().insert(i, controllerset); enableSetConnections(controllerset); } } QString GameController::getName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return QString(tr("Game Controller")).append(" ").append(QString::number(getRealJoyNumber())); } QString GameController::getSDLName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { temp = SDL_GameControllerName(controller); } return temp; } QString GameController::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::GameController::xmlName; } QString GameController::getGUIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getRawGUIDString(); } QString GameController::getVendorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getRawVendorString(); } QString GameController::getProductIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getRawProductIDString(); } QString GameController::getUniqueIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getRawUniqueIDString(); } QString GameController::getProductVersion() { return getRawProductVersion(); } QString GameController::getRawGUIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { SDL_Joystick *joyhandle = SDL_GameControllerGetJoystick(controller); if (joyhandle != nullptr) { SDL_JoystickGUID tempGUID = SDL_JoystickGetGUID(joyhandle); char guidString[65] = {'0'}; SDL_JoystickGetGUIDString(tempGUID, guidString, sizeof(guidString)); temp = QString(guidString); } } return temp; } QString GameController::getRawVendorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { Uint16 tempVendor = SDL_GameControllerGetVendor(controller); char buffer[50]; sprintf(buffer, "%u", tempVendor); temp = QString(buffer); } return temp; } QString GameController::getRawProductIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { Uint16 tempProduct = SDL_GameControllerGetProduct(controller) + counterUniques; char buffer[50]; sprintf(buffer, "%u", tempProduct); temp = QString(buffer); } return temp; } QString GameController::getRawProductVersion() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { Uint16 tempProductVersion = SDL_GameControllerGetProductVersion(controller); char buffer[50]; sprintf(buffer, "%u", tempProductVersion); temp = QString(buffer); } return temp; } QString GameController::getRawUniqueIDString() { return (getRawGUIDString() + getRawVendorString() + getRawProductIDString()); } void GameController::closeSDLDevice() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((controller != nullptr) && SDL_GameControllerGetAttached(controller)) { SDL_GameControllerClose(controller); controller = nullptr; } } int GameController::getNumberRawButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); return SDL_CONTROLLER_BUTTON_MAX; } int GameController::getNumberRawAxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "Controller has " << SDL_CONTROLLER_AXIS_MAX << " raw axes"; return SDL_CONTROLLER_AXIS_MAX; } int GameController::getNumberRawHats() { qInstallMessageHandler(MessageHandler::myMessageOutput); return 0; } void GameController::setCounterUniques(int counter) { counterUniques = counter; } void GameController::fillContainers(QHash &buttons, QHash &axes, QList &hatButtons) { for (int i = 0; i < SDL_JoystickNumHats(getJoyHandle()); i++) { SDL_GameControllerButton currentButton = static_cast(i); SDL_GameControllerButtonBind bound = SDL_GameControllerGetBindForButton(this->controller, currentButton); qDebug() << "Hat " << (i + 1); if (bound.bindType == SDL_CONTROLLER_BINDTYPE_HAT) { hatButtons.append(bound); } } for (int i = 0; i < SDL_JoystickNumButtons(getJoyHandle()); i++) { qDebug() << "Button " << (i + 1); SDL_GameControllerButton currentButton = static_cast(i); SDL_GameControllerButtonBind bound = SDL_GameControllerGetBindForButton(this->controller, currentButton); if (bound.bindType == SDL_CONTROLLER_BINDTYPE_BUTTON) { buttons.insert(bound.value.button, currentButton); } } for (int i = 0; i < SDL_JoystickNumAxes(getJoyHandle()); i++) { qDebug() << "Axis " << (i + 1); SDL_GameControllerAxis currentAxis = static_cast(i); SDL_GameControllerButtonBind bound = SDL_GameControllerGetBindForAxis(this->controller, currentAxis); if (bound.bindType == SDL_CONTROLLER_BINDTYPE_AXIS) { axes.insert(bound.value.axis, currentAxis); } } } QString GameController::getBindStringForAxis(int index, bool) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); SDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForAxis(controller, static_cast(index)); if (bind.bindType == SDL_CONTROLLER_BINDTYPE_BUTTON) { temp.append(QString("Button %1").arg(bind.value.button)); } else if (bind.bindType == SDL_CONTROLLER_BINDTYPE_AXIS) { temp.append(QString("Axis %1").arg(bind.value.axis + 1)); } return temp; } QString GameController::getBindStringForButton(int index, bool trueIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); SDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForButton(controller, static_cast(index)); int offset = trueIndex ? 0 : 1; int bindInt = static_cast(bind.bindType); switch (bindInt) { case SDL_CONTROLLER_BINDTYPE_BUTTON: temp.append(QString("Button %1").arg(bind.value.button + offset)); break; case SDL_CONTROLLER_BINDTYPE_AXIS: temp.append(QString("Axis %1").arg(bind.value.axis + offset)); break; case SDL_CONTROLLER_BINDTYPE_HAT: temp.append(QString("Hat %1.%2").arg(bind.value.hat.hat + offset).arg(bind.value.hat.hat_mask)); break; } return temp; } SDL_GameControllerButtonBind GameController::getBindForAxis(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); return SDL_GameControllerGetBindForAxis(controller, static_cast(index)); } SDL_GameControllerButtonBind GameController::getBindForButton(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); return SDL_GameControllerGetBindForButton(controller, static_cast(index)); } void GameController::buttonClickEvent(int) { qInstallMessageHandler(MessageHandler::myMessageOutput); } void GameController::buttonReleaseEvent(int) { qInstallMessageHandler(MessageHandler::myMessageOutput); } void GameController::axisActivatedEvent(int, int, int) { qInstallMessageHandler(MessageHandler::myMessageOutput); } SDL_JoystickID GameController::getSDLJoystickID() { qInstallMessageHandler(MessageHandler::myMessageOutput); return joystickID; } /** * @brief Check if device is using the SDL Game Controller API * @return Status showing if device is using the Game Controller API */ bool GameController::isGameController() { qInstallMessageHandler(MessageHandler::myMessageOutput); return true; } /** * @brief Check if GUID passed matches the expected GUID for a device. * Needed for xinput GUID abstraction. * @param GUID string * @return if GUID is considered a match. */ // bool GameController::isRelevantGUID(QString tempGUID) //{ // qInstallMessageHandler(MessageHandler::myMessageOutput); // return InputDevice::isRelevantGUID(tempGUID); //} bool GameController::isRelevantUniqueID(QString tempUniqueID) { qInstallMessageHandler(MessageHandler::myMessageOutput); return InputDevice::isRelevantUniqueID(tempUniqueID); } void GameController::rawButtonEvent(int index, bool pressed) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool knownbutton = getRawbuttons().contains(index); if (!knownbutton && pressed) { rawbuttons.insert(index, pressed); emit rawButtonClick(index); } else if (knownbutton && !pressed) { rawbuttons.remove(index); emit rawButtonRelease(index); } } void GameController::rawAxisEvent(int index, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool knownaxis = getAxisvalues().contains(index); if (!knownaxis && (fabs(value) > rawAxisDeadZone)) { axisvalues.insert(index, value); emit rawAxisActivated(index, value); } else if (knownaxis && (fabs(value) < rawAxisDeadZone)) { axisvalues.remove(index); emit rawAxisReleased(index, value); } emit rawAxisMoved(index, value); } void GameController::rawDPadEvent(int index, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool knowndpad = getDpadvalues().contains(index); if (!knowndpad && (value != 0)) { dpadvalues.insert(index, value); emit rawDPadButtonClick(index, value); } else if (knowndpad && (value == 0)) { dpadvalues.remove(index); emit rawDPadButtonRelease(index, value); } } QHash const &GameController::getRawbuttons() { return rawbuttons; } QHash const &GameController::getAxisvalues() { return axisvalues; } QHash const &GameController::getDpadvalues() { return dpadvalues; } SDL_GameController *GameController::getController() const { return controller; } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontroller.h000066400000000000000000000070631377703515000252630ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLER_H #define GAMECONTROLLER_H #include #include class QXmlStreamReader; class QXmlStreamWriter; class AntiMicroSettings; // holds information about gamecontrollers class GameController : public InputDevice { Q_OBJECT public: explicit GameController(SDL_GameController *controller, int deviceIndex, AntiMicroSettings *settings, int counterUniques, QObject *parent = nullptr); virtual QString getName() override; virtual QString getSDLName() override; virtual QString getXmlName() override; // GUID available on SDL 2. virtual QString getGUIDString() override; virtual QString getVendorString() override; virtual QString getProductIDString() override; virtual QString getUniqueIDString() override; virtual QString getProductVersion() override; virtual QString getRawGUIDString() override; virtual QString getRawUniqueIDString() override; virtual QString getRawVendorString() override; virtual QString getRawProductIDString() override; virtual QString getRawProductVersion() override; virtual bool isGameController() override; virtual void closeSDLDevice() override; virtual SDL_JoystickID getSDLJoystickID() override; virtual int getNumberRawButtons() override; virtual int getNumberRawAxes() override; virtual int getNumberRawHats() override; void setCounterUniques(int counter) override; QString getBindStringForAxis(int index, bool trueIndex = true); QString getBindStringForButton(int index, bool trueIndex = true); SDL_GameControllerButtonBind getBindForAxis(int index); SDL_GameControllerButtonBind getBindForButton(int index); // bool isRelevantGUID(QString tempGUID); bool isRelevantUniqueID(QString tempUniqueID); void rawButtonEvent(int index, bool pressed); void rawAxisEvent(int index, int value); void rawDPadEvent(int index, int value); QHash const &getRawbuttons(); QHash const &getAxisvalues(); QHash const &getDpadvalues(); SDL_GameController *getController() const; void fillContainers(QHash &buttons, QHash &axes, QList &hatButtons); protected slots: virtual void axisActivatedEvent(int setindex, int axisindex, int value) override; virtual void buttonClickEvent(int buttonindex) override; virtual void buttonReleaseEvent(int buttonindex) override; private: QHash rawbuttons; QHash axisvalues; QHash dpadvalues; int counterUniques; SDL_JoystickID joystickID; SDL_GameController *controller; }; #endif // GAMECONTROLLER_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollerdpad.cpp000066400000000000000000000044231377703515000264440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gamecontrollerdpad.h" #include "globalvariables.h" #include "joybutton.h" #include "messagehandler.h" #include "setjoystick.h" #include "xml/joydpadxml.h" #include GameControllerDPad::GameControllerDPad(JoyButton *upButton, JoyButton *downButton, JoyButton *leftButton, JoyButton *rightButton, int index, int originset, SetJoystick *parentSet, QObject *parent) : VDPad(upButton, downButton, leftButton, rightButton, index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } QString GameControllerDPad::getName(bool forceFullFormat, bool displayName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); if (!getDpadName().isEmpty() && displayName) { if (forceFullFormat) { label.append(tr("DPad")).append(" "); } label.append(getDpadName()); } else if (!getDefaultDpadName().isEmpty()) { if (forceFullFormat) { label.append(tr("DPad")).append(" "); } label.append(getDefaultDpadName()); } else { label.append(tr("DPad")).append(" "); label.append(QString::number(getRealJoyNumber())); } return label; } QString GameControllerDPad::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::GameControllerDPad::xmlName; } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollerdpad.h000066400000000000000000000027211377703515000261100ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERDPAD_H #define GAMECONTROLLERDPAD_H #include "vdpad.h" class QXmlStreamReader; class JoyButton; class SetJoystick; class DPad; // holds information about gamecontroller dpad class GameControllerDPad : public VDPad { Q_OBJECT public: explicit GameControllerDPad(JoyButton *upButton, JoyButton *downButton, JoyButton *leftButton, JoyButton *rightButton, int index, int originset, SetJoystick *parentSet, QObject *parent = nullptr); virtual QString getName(bool forceFullFormat, bool displayName); virtual QString getXmlName(); // GameControllerDPadXml class }; #endif // GAMECONTROLLERDPAD_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollerset.cpp000066400000000000000000000302361377703515000263300ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska . */ #include "gamecontrollerset.h" #include "gamecontroller/xml/gamecontrollertriggerxml.h" #include "gamecontrollerdpad.h" #include "gamecontrollertrigger.h" #include "inputdevice.h" #include "joycontrolstick.h" #include "messagehandler.h" #include "xml/joyaxisxml.h" #include "xml/joybuttonxml.h" #include "xml/joydpadxml.h" #include #include GameControllerSet::GameControllerSet(InputDevice *device, int index, QObject *parent) : SetJoystick(device, index, false, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); resetSticks(); } void GameControllerSet::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); resetSticks(); } void GameControllerSet::resetSticks() { SetJoystick::reset(); populateSticksDPad(); } void GameControllerSet::populateSticksDPad() { qInstallMessageHandler(MessageHandler::myMessageOutput); // Left Stick Assignment JoyAxis *axisX = getJoyAxis(SDL_CONTROLLER_AXIS_LEFTX); JoyAxis *axisY = getJoyAxis(SDL_CONTROLLER_AXIS_LEFTY); JoyControlStick *stick1 = new JoyControlStick(axisX, axisY, 0, getIndex(), this); stick1->setDefaultStickName("L Stick"); addControlStick(0, stick1); // Right Stick Assignment axisX = getJoyAxis(SDL_CONTROLLER_AXIS_RIGHTX); axisY = getJoyAxis(SDL_CONTROLLER_AXIS_RIGHTY); JoyControlStick *stick2 = new JoyControlStick(axisX, axisY, 1, getIndex(), this); stick2->setDefaultStickName("R Stick"); addControlStick(1, stick2); // Assign DPad buttons as a virtual DPad. Allows rougelike controls // to be assigned. JoyButton *buttonUp = getJoyButton(SDL_CONTROLLER_BUTTON_DPAD_UP); JoyButton *buttonDown = getJoyButton(SDL_CONTROLLER_BUTTON_DPAD_DOWN); JoyButton *buttonLeft = getJoyButton(SDL_CONTROLLER_BUTTON_DPAD_LEFT); JoyButton *buttonRight = getJoyButton(SDL_CONTROLLER_BUTTON_DPAD_RIGHT); GameControllerDPad *controllerDPad = new GameControllerDPad(buttonUp, buttonDown, buttonLeft, buttonRight, 0, getIndex(), this, this); controllerDPad->setDefaultDPadName("DPad"); addVDPad(0, controllerDPad); // Give default names to buttons getJoyButton(SDL_CONTROLLER_BUTTON_A)->setDefaultButtonName("A"); getJoyButton(SDL_CONTROLLER_BUTTON_B)->setDefaultButtonName("B"); getJoyButton(SDL_CONTROLLER_BUTTON_X)->setDefaultButtonName("X"); getJoyButton(SDL_CONTROLLER_BUTTON_Y)->setDefaultButtonName("Y"); getJoyButton(SDL_CONTROLLER_BUTTON_BACK)->setDefaultButtonName(tr("Back")); getJoyButton(SDL_CONTROLLER_BUTTON_GUIDE)->setDefaultButtonName(tr("Guide")); getJoyButton(SDL_CONTROLLER_BUTTON_START)->setDefaultButtonName(tr("Start")); getJoyButton(SDL_CONTROLLER_BUTTON_LEFTSTICK)->setDefaultButtonName(tr("LS Click")); getJoyButton(SDL_CONTROLLER_BUTTON_RIGHTSTICK)->setDefaultButtonName(tr("RS Click")); getJoyButton(SDL_CONTROLLER_BUTTON_LEFTSHOULDER)->setDefaultButtonName(tr("L Shoulder")); getJoyButton(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)->setDefaultButtonName(tr("R Shoulder")); // Give default names to triggers getJoyAxis(SDL_CONTROLLER_AXIS_TRIGGERLEFT)->setDefaultAxisName(tr("L Trigger")); getJoyAxis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT)->setDefaultAxisName(tr("R Trigger")); } template void readConf(T *x, QXmlStreamReader *xml) { if (x != nullptr) { x->readConfig(xml); } else { xml->skipCurrentElement(); } } void GameControllerSet::readConfDpad(QXmlStreamReader *xml, QList &hatButtons, bool vdpadExists, bool dpadExists) { int index = xml->attributes().value("index").toString().toInt(); index = index - 1; bool found = false; QListIterator iter(hatButtons); while (iter.hasNext()) { if (iter.next().value.hat.hat == index) { found = true; iter.toBack(); } } VDPad *dpad = nullptr; JoyDPadXml *dpadXml = nullptr; if (found) { dpad = getVDPad(0); dpadXml = new JoyDPadXml(dpad); } if ((dpad != nullptr) && !vdpadExists) { dpadXml->readConfig(xml); } else { xml->skipCurrentElement(); } } void GameControllerSet::readJoystickConfig(QXmlStreamReader *xml, QHash &buttons, QHash &axes, QList &hatButtons) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == "set")) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "set"))) { bool dpadExists = false; bool vdpadExists = false; if ((xml->name() == "button") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); JoyButton *button = nullptr; JoyButtonXml *joyButtonXml = nullptr; if (buttons.contains(index - 1)) { SDL_GameControllerButton current = buttons.value(index - 1); button = getJoyButton(current); joyButtonXml = new JoyButtonXml(button); } readConf(joyButtonXml, xml); } else if ((xml->name() == "axis") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); GameControllerTrigger *trigger = nullptr; GameControllerTriggerXml *gameContrTriggerXml = nullptr; if (axes.contains(index - 1)) { SDL_GameControllerAxis current = axes.value(index - 1); trigger = qobject_cast(getJoyAxis(static_cast(current))); gameContrTriggerXml = new GameControllerTriggerXml(trigger); } if (trigger != nullptr) { gameContrTriggerXml->readJoystickConfig(xml); delete gameContrTriggerXml; } else { xml->skipCurrentElement(); } } else if ((xml->name() == "dpad") && xml->isStartElement()) { readConfDpad(xml, hatButtons, vdpadExists, dpadExists); } else if ((xml->name() == "stick") && xml->isStartElement()) { getElemFromXml("stick", xml); } else if ((xml->name() == "vdpad") && xml->isStartElement()) { readConfDpad(xml, hatButtons, vdpadExists, dpadExists); } else if ((xml->name() == "name") && xml->isStartElement()) { QString temptext = xml->readElementText(); if (!temptext.isEmpty()) { setName(temptext); } } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } } void GameControllerSet::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == "set")) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && xml->name() != "set")) { if ((xml->name() == "button") && xml->isStartElement()) { getElemFromXml("button", xml); } else if ((xml->name() == "trigger") && xml->isStartElement()) { getElemFromXml("trigger", xml); } else if ((xml->name() == "stick") && xml->isStartElement()) { getElemFromXml("stick", xml); } else if ((xml->name() == "dpad") && xml->isStartElement()) { getElemFromXml("dpad", xml); } else if ((xml->name() == "name") && xml->isStartElement()) { QString temptext = xml->readElementText(); if (!temptext.isEmpty()) { setName(temptext); } } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } } void GameControllerSet::getElemFromXml(QString elemName, QXmlStreamReader *xml) { int index = xml->attributes().value("index").toString().toInt(); if (elemName == "button") { JoyButton *button = getJoyButton(index - 1); JoyButtonXml *joyButtonXml = new JoyButtonXml(button, this); readConf(joyButtonXml, xml); } else if (elemName == "dpad") { GameControllerDPad *vdpad = qobject_cast(getVDPad(index - 1)); JoyDPadXml *dpadXml = new JoyDPadXml(vdpad); readConf(dpadXml, xml); // if (!dpadXml.isNull()) delete dpadXml; } else if (elemName == "trigger") { GameControllerTrigger *axis = nullptr; GameControllerTriggerXml *triggerAxisXml = nullptr; switch (index - 1) { // for older profiles case 0: axis = qobject_cast(getJoyAxis(SDL_CONTROLLER_AXIS_TRIGGERLEFT)); triggerAxisXml = new GameControllerTriggerXml(axis, this); readConf(triggerAxisXml, xml); break; // for older profiles case 1: axis = qobject_cast(getJoyAxis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT)); triggerAxisXml = new GameControllerTriggerXml(axis, this); readConf(triggerAxisXml, xml); break; case 4: axis = qobject_cast(getJoyAxis(SDL_CONTROLLER_AXIS_TRIGGERLEFT)); triggerAxisXml = new GameControllerTriggerXml(axis, this); readConf(triggerAxisXml, xml); break; case 5: axis = qobject_cast(getJoyAxis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT)); triggerAxisXml = new GameControllerTriggerXml(axis, this); readConf(triggerAxisXml, xml); break; } } else if (elemName == "stick") { if (index > 0) { index -= 1; JoyControlStick *stick = getJoyStick(index); readConf(stick, xml); } else { xml->skipCurrentElement(); } } } void GameControllerSet::refreshAxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); deleteAxes(); for (int i = 0; i < getInputDevice()->getNumberRawAxes(); i++) { if ((i == static_cast(SDL_CONTROLLER_AXIS_TRIGGERLEFT)) || (i == static_cast(SDL_CONTROLLER_AXIS_TRIGGERRIGHT))) { GameControllerTrigger *trigger = new GameControllerTrigger(i, getIndex(), this, this); getAxes()->insert(i, trigger); enableAxisConnections(trigger); } else { JoyAxis *axis = new JoyAxis(i, getIndex(), this, this); getAxes()->insert(i, axis); enableAxisConnections(axis); } } } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollerset.h000066400000000000000000000037111377703515000257730ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERSET_H #define GAMECONTROLLERSET_H #include "setjoystick.h" #include class QXmlStreamReader; class InputDevice; class GameControllerSet : public SetJoystick { Q_OBJECT public: explicit GameControllerSet(InputDevice *device, int index, QObject *parent = nullptr); virtual void refreshAxes(); virtual void readConfig(QXmlStreamReader *xml); // GameControllerSetXml virtual void readJoystickConfig(QXmlStreamReader *xml, QHash &buttons, QHash &axes, QList &hatButtons); // GameControllerSetXml class protected: void populateSticksDPad(); public slots: virtual void reset(); private: void getElemFromXml(QString elemName, QXmlStreamReader *xml); // GameControllerSetXml class void readConfDpad(QXmlStreamReader *xml, QList &hatButtons, bool vdpadExists, bool dpadExists); // GameControllerSetXml class void resetSticks(); }; #endif // GAMECONTROLLERSET_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollertrigger.cpp000066400000000000000000000104761377703515000272040ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska . */ //#include #include "gamecontrollertrigger.h" #include "gamecontrollertriggerbutton.h" #include "globalvariables.h" #include "messagehandler.h" #include "xml/joyaxisxml.h" #include #include #include #include const GameControllerTrigger::ThrottleTypes GameControllerTrigger::DEFAULTTHROTTLE = GameControllerTrigger::PositiveHalfThrottle; GameControllerTrigger::GameControllerTrigger(int index, int originset, SetJoystick *parentSet, QObject *parent) : JoyAxis(index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); naxisbutton = new GameControllerTriggerButton(this, 0, originset, parentSet, this); paxisbutton = new GameControllerTriggerButton(this, 1, originset, parentSet, this); reset(index); } void GameControllerTrigger::reset(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); reset(); m_index = index; } void GameControllerTrigger::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); deadZone = GlobalVariables::GameControllerTrigger::AXISDEADZONE; isActive = false; eventActive = false; maxZoneValue = GlobalVariables::GameControllerTrigger::AXISMAXZONE; throttle = this->DEFAULTTHROTTLE; paxisbutton->reset(); naxisbutton->reset(); activeButton = nullptr; lastKnownThottledValue = 0; lastKnownRawValue = 0; adjustRange(); setCurrentRawValue(currentThrottledDeadValue); currentThrottledValue = calculateThrottledValue(currentRawValue); axisName.clear(); pendingEvent = false; pendingValue = currentRawValue; pendingIgnoreSets = false; } QString GameControllerTrigger::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::GameControllerTrigger::xmlName; } QString GameControllerTrigger::getPartialName(bool forceFullFormat, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); if (!axisName.isEmpty() && displayNames) { label.append(axisName); if (forceFullFormat) { label.append(" ").append(tr("Trigger")); } } else if (!defaultAxisName.isEmpty()) { label.append(defaultAxisName); if (forceFullFormat) { label.append(" ").append(tr("Trigger")); } } else { label.append(tr("Trigger")).append(" "); label.append(QString::number(getRealJoyIndex() - SDL_CONTROLLER_AXIS_TRIGGERLEFT)); } return label; } void GameControllerTrigger::correctJoystickThrottle() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (this->throttle != static_cast(PositiveHalfThrottle)) { this->setThrottle(static_cast(PositiveHalfThrottle)); setCurrentRawValue(currentThrottledDeadValue); currentThrottledValue = calculateThrottledValue(currentRawValue); } } int GameControllerTrigger::getDefaultDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::GameControllerTrigger::AXISDEADZONE; } int GameControllerTrigger::getDefaultMaxZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::GameControllerTrigger::AXISMAXZONE; } JoyAxis::ThrottleTypes GameControllerTrigger::getDefaultThrottle() { qInstallMessageHandler(MessageHandler::myMessageOutput); return static_cast(this->DEFAULTTHROTTLE); } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollertrigger.h000066400000000000000000000031541377703515000266440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERTRIGGER_H #define GAMECONTROLLERTRIGGER_H #include "joyaxis.h" class QXmlStreamReader; class QXmlStreamWriter; class SetJoystick; class GameControllerTrigger : public JoyAxis { Q_OBJECT public: explicit GameControllerTrigger(int index, int originset, SetJoystick *parentSet, QObject *parent = nullptr); virtual QString getXmlName(); // GameControllerTriggerXml class virtual QString getPartialName(bool forceFullFormat, bool displayNames); virtual int getDefaultDeadZone(); virtual int getDefaultMaxZone(); virtual ThrottleTypes getDefaultThrottle(); static const ThrottleTypes DEFAULTTHROTTLE; public slots: virtual void reset(); virtual void reset(int index); protected: void correctJoystickThrottle(); }; #endif // GAMECONTROLLERTRIGGER_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollertriggerbutton.cpp000066400000000000000000000047721377703515000304420ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska . */ #include "gamecontrollertriggerbutton.h" #include "globalvariables.h" #include "inputdevice.h" #include "joyaxis.h" #include "messagehandler.h" #include "setjoystick.h" #include "xml/joybuttonxml.h" #include #include GameControllerTriggerButton::GameControllerTriggerButton(JoyAxis *axis, int index, int originset, SetJoystick *parentSet, QObject *parent) : JoyAxisButton(axis, index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } QString GameControllerTriggerButton::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::GameControllerTriggerButton::xmlName; } void GameControllerTriggerButton::readJoystickConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == GlobalVariables::JoyAxisButton::xmlName)) { disconnect(this, &GameControllerTriggerButton::slotsChanged, m_parentSet->getInputDevice(), &InputDevice::profileEdited); xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != GlobalVariables::JoyAxisButton::xmlName))) { JoyButtonXml *joyButtonXml = new JoyButtonXml(this); bool found = joyButtonXml->readButtonConfig(xml); if (!found) { xml->skipCurrentElement(); } xml->readNextStartElement(); } connect(this, &GameControllerTriggerButton::slotsChanged, m_parentSet->getInputDevice(), &InputDevice::profileEdited); } } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/gamecontrollertriggerbutton.h000066400000000000000000000026511377703515000301010ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERBUTTON_H #define GAMECONTROLLERBUTTON_H #include "joybuttontypes/joyaxisbutton.h" class QXmlStreamReader; class SetJoystick; class JoyAxis; class GameControllerTriggerButton : public JoyAxisButton { Q_OBJECT public: explicit GameControllerTriggerButton(JoyAxis *axis, int index, int originset, SetJoystick *parentSet, QObject *parent = nullptr); virtual QString getXmlName(); // GameContrTriggerBtnXml class void readJoystickConfig(QXmlStreamReader *xml); // GameContrTriggerBtnXml class }; #endif // GAMECONTROLLERBUTTON_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/xml/000077500000000000000000000000001377703515000226675ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/gamecontroller/xml/gamecontrollerdpadxml.cpp000066400000000000000000000033011377703515000277570ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gamecontrollerdpadxml.h" #include "messagehandler.h" #include "gamecontroller/gamecontrollerdpad.h" #include #include GameControllerDPadXml::GameControllerDPadXml(GameControllerDPad *gameContrDpad, QObject *parent) : JoyDPadXml(gameContrDpad, parent) { dpadXml = new JoyDPadXml(gameContrDpad, this); } void GameControllerDPadXml::readJoystickConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == GlobalVariables::VDPad::xmlName)) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != GlobalVariables::VDPad::xmlName))) { bool found = dpadXml->readMainConfig(xml); if (!found) { xml->skipCurrentElement(); } xml->readNextStartElement(); } } } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/xml/gamecontrollerdpadxml.h000066400000000000000000000023371377703515000274340ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERDPADXML_H #define GAMECONTROLLERDPADXML_H #include "vdpad.h" #include "xml/joydpadxml.h" class GameControllerDPad; class QXmlStreamReader; class GameControllerDPadXml : public JoyDPadXml { Q_OBJECT public: explicit GameControllerDPadXml(GameControllerDPad *gameContrDpad, QObject *parent = nullptr); void readJoystickConfig(QXmlStreamReader *xml); private: JoyDPadXml *dpadXml; }; #endif // GAMECONTROLLERDPADXML_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/xml/gamecontrollertriggerxml.cpp000066400000000000000000000115601377703515000305200ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska . */ #include "gamecontrollertriggerxml.h" #include "gamecontroller/gamecontrollertrigger.h" #include "gamecontroller/gamecontrollertriggerbutton.h" #include "xml/joyaxisxml.h" #include "xml/joybuttonxml.h" #include "messagehandler.h" #include #include #include #include GameControllerTriggerXml::GameControllerTriggerXml(GameControllerTrigger *gameContrTrigger, QObject *parent) : JoyAxisXml(gameContrTrigger, parent) { m_gameContrTrigger = gameContrTrigger; joyButtonXmlNAxis = new JoyButtonXml(gameContrTrigger->getNAxisButton(), this); joyButtonXmlPAxis = new JoyButtonXml(gameContrTrigger->getPAxisButton(), this); } void GameControllerTriggerXml::readJoystickConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == GlobalVariables::JoyAxis::xmlName)) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != GlobalVariables::JoyAxis::xmlName))) { bool found = readMainConfig(xml); if (!found && (xml->name() == GlobalVariables::JoyAxisButton::xmlName) && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); GameControllerTriggerButton *triggerButton = nullptr; qDebug() << "Index for axis in readJoystickConfig is: " << index; switch (index) { case 1: found = true; triggerButton = qobject_cast(m_gameContrTrigger->getNAxisButton()); triggerButton->readJoystickConfig(xml); break; case 2: found = true; triggerButton = qobject_cast(m_gameContrTrigger->getPAxisButton()); triggerButton->readJoystickConfig(xml); break; } } if (!found) { xml->skipCurrentElement(); } xml->readNextStartElement(); } } if (m_gameContrTrigger->getThrottle() != static_cast(JoyAxis::PositiveHalfThrottle)) { m_gameContrTrigger->setThrottle(static_cast(JoyAxis::PositiveHalfThrottle)); m_gameContrTrigger->setCurrentRawValue(m_gameContrTrigger->getCurrentThrottledDeadValue()); m_gameContrTrigger->updateCurrentThrottledValue( m_gameContrTrigger->calculateThrottledValue(m_gameContrTrigger->getCurrentRawValue())); } } void GameControllerTriggerXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool currentlyDefault = m_gameContrTrigger->isDefault(); xml->writeStartElement(m_gameContrTrigger->getXmlName()); xml->writeAttribute("index", QString::number((m_gameContrTrigger->getRealJoyIndex()) - SDL_CONTROLLER_AXIS_TRIGGERLEFT)); if (!currentlyDefault && (m_gameContrTrigger->getDeadZone() != GlobalVariables::GameControllerTrigger::AXISDEADZONE)) { xml->writeTextElement("deadZone", QString::number(m_gameContrTrigger->getDeadZone())); } if (!currentlyDefault && (m_gameContrTrigger->getMaxZoneValue() != GlobalVariables::GameControllerTrigger::AXISMAXZONE)) { xml->writeTextElement("maxZone", QString::number(m_gameContrTrigger->getMaxZoneValue())); } xml->writeStartElement("throttle"); switch (m_gameContrTrigger->getThrottle()) { case -2: xml->writeCharacters("negativehalf"); break; case -1: xml->writeCharacters("negative"); break; case 0: xml->writeCharacters("normal"); break; case 1: xml->writeCharacters("positive"); break; case 2: xml->writeCharacters("positivehalf"); break; } xml->writeEndElement(); if (!currentlyDefault) { joyButtonXmlNAxis->writeConfig(xml); joyButtonXmlPAxis->writeConfig(xml); } xml->writeEndElement(); } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/xml/gamecontrollertriggerxml.h000066400000000000000000000024631377703515000301670ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERTRIGGERXML_H #define GAMECONTROLLERTRIGGERXML_H #include "xml/joyaxisxml.h" class GameControllerTrigger; class GameControllerTriggerXml : public JoyAxisXml { public: explicit GameControllerTriggerXml(GameControllerTrigger *gameContrTrigger, QObject *parent = 0); void readJoystickConfig(QXmlStreamReader *xml); virtual void writeConfig(QXmlStreamWriter *xml); private: GameControllerTrigger *m_gameContrTrigger; JoyButtonXml *joyButtonXmlNAxis; JoyButtonXml *joyButtonXmlPAxis; }; #endif // GAMECONTROLLERTRIGGERXML_H AntiMicroX-antimicrox-2888bf6/src/gamecontroller/xml/gamecontrollerxml.cpp000066400000000000000000000632331377703515000271400ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gamecontrollerxml.h" #include "gamecontroller/gamecontroller.h" #include "common.h" #include "globalvariables.h" #include "messagehandler.h" //#include "logger.h" #include "gamecontroller/gamecontrollerdpad.h" #include "gamecontroller/gamecontrollerset.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joycontrolstick.h" #include #include #include #include GameControllerXml::GameControllerXml(GameController *gameController, QObject *parent) : InputDeviceXml(gameController, parent) { m_gameController = gameController; } void GameControllerXml::readJoystickConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = 0; int buttonIndex = 0; QString temp = QString(); if (xml->isStartElement() && (xml->name() == "joystick")) { m_gameController->transferReset(); QHash buttons; QHash axes; QList hatButtons; m_gameController->fillContainers(buttons, axes, hatButtons); xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "joystick"))) { if ((xml->name() == "sets") && xml->isStartElement()) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "sets"))) { if ((xml->name() == "set") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); index = index - 1; if ((index >= 0) && (index < m_gameController->getJoystick_sets().size())) { GameControllerSet *currentSet = qobject_cast( m_gameController->getJoystick_sets().value(index)); // static_cast currentSet->readJoystickConfig(xml, buttons, axes, hatButtons); } } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } else if ((xml->name() == "names") && xml->isStartElement()) { bool dpadNameExists = false; bool vdpadNameExists = false; xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "names"))) { if ((xml->name() == "buttonname") && xml->isStartElement()) { assignVariablesShort(xml, index, temp); if ((index >= 0) && !temp.isEmpty()) { SDL_GameControllerButton current = buttons.value(index); if (static_cast(current) != -1) { m_gameController->setButtonName(current, temp); } } } else if ((xml->name() == "axisbuttonname") && xml->isStartElement()) { assignVariables(xml, index, buttonIndex, temp, true); if ((index >= 0) && !temp.isEmpty()) { SDL_GameControllerAxis current = axes.value(index); int currentInt = static_cast(current); switch (currentInt) { case SDL_CONTROLLER_AXIS_LEFTX: case SDL_CONTROLLER_AXIS_LEFTY: { m_gameController->setStickButtonName(0, buttonIndex, temp); break; } case SDL_CONTROLLER_AXIS_RIGHTX: case SDL_CONTROLLER_AXIS_RIGHTY: { m_gameController->setStickButtonName(1, buttonIndex, temp); break; } case SDL_CONTROLLER_AXIS_TRIGGERLEFT: case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: { m_gameController->setAxisName(current, temp); } } } } else if ((xml->name() == "controlstickbuttonname") && xml->isStartElement()) { assignVariables(xml, index, buttonIndex, temp, false); if ((index >= 0) && !temp.isEmpty()) { m_gameController->setStickButtonName(index, buttonIndex, temp); } } else if ((xml->name() == "dpadbuttonname") && xml->isStartElement()) { assignVariables(xml, index, buttonIndex, temp, false); if ((index >= 0) && !temp.isEmpty()) { bool found = false; QListIterator iter(hatButtons); SDL_GameControllerButtonBind current; while (iter.hasNext()) { current = iter.next(); if (current.value.hat.hat == index) { found = true; iter.toBack(); } } if (found) { VDPad *dpad = m_gameController->getActiveSetJoystick()->getVDPad(0); if (dpad != nullptr) { JoyDPadButton *dpadbutton = dpad->getJoyButton(buttonIndex); if ((dpad != nullptr) && (dpadbutton != nullptr) && dpadbutton->getActionName().isEmpty()) { m_gameController->setVDPadButtonName(index, buttonIndex, temp); } } } } } else if ((xml->name() == "vdpadbuttonname") && xml->isStartElement()) { assignVariables(xml, index, buttonIndex, temp, false); if ((index >= 0) && !temp.isEmpty()) { bool found = false; QListIterator iter(hatButtons); SDL_GameControllerButtonBind current; while (iter.hasNext()) { current = iter.next(); if (current.value.hat.hat == index) { found = true; iter.toBack(); } } if (found) { VDPad *dpad = m_gameController->getActiveSetJoystick()->getVDPad(0); if (dpad != nullptr) { JoyDPadButton *dpadbutton = dpad->getJoyButton(buttonIndex); if ((dpad != nullptr) && (dpadbutton != nullptr) && dpadbutton->getActionName().isEmpty()) { m_gameController->setVDPadButtonName(index, buttonIndex, temp); } } } } } else if ((xml->name() == "axisname") && xml->isStartElement()) { assignVariablesShort(xml, index, temp); if ((index >= 0) && !temp.isEmpty()) { if (axes.contains(index)) { SDL_GameControllerAxis current = axes.value(index); m_gameController->setAxisName(static_cast(current), temp); } } } else if ((xml->name() == "controlstickname") && xml->isStartElement()) { assignVariablesShort(xml, index, temp); if ((index >= 0) && !temp.isEmpty()) { m_gameController->setStickName(index, temp); } } else if ((xml->name() == "dpadname") && xml->isStartElement()) { readJoystickConfigXmlLong(hatButtons, dpadNameExists, vdpadNameExists, xml); } else if ((xml->name() == "vdpadname") && xml->isStartElement()) { readJoystickConfigXmlLong(hatButtons, dpadNameExists, vdpadNameExists, xml); } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } else if ((xml->name() == "keyPressTime") && xml->isStartElement()) { QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); if (tempchoice >= 10) m_gameController->setDeviceKeyPressTime(tempchoice); } else if ((xml->name() == "profilename") && xml->isStartElement()) { QString temptext = xml->readElementText(); m_gameController->setProfileName(temptext); } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } m_gameController->reInitButtons(); } } void GameControllerXml::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == m_gameController->getXmlName())) { m_gameController->transferReset(); xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != m_gameController->getXmlName()))) { if ((xml->name() == "sets") && xml->isStartElement()) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "sets"))) { if ((xml->name() == "set") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); index = index - 1; if ((index >= 0) && (index < m_gameController->getJoystick_sets().size())) { m_gameController->getJoystick_sets().value(index)->readConfig(xml); } } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } else if ((xml->name() == "names") && xml->isStartElement()) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "names"))) { if ((xml->name() == "buttonname") && xml->isStartElement()) { readXmlNamesShort("buttonname", xml); } else if ((xml->name() == "triggerbuttonname") && xml->isStartElement()) { readXmlNamesLong("triggerbuttonname", xml); } else if ((xml->name() == "controlstickbuttonname") && xml->isStartElement()) { readXmlNamesMiddle("controlstickbuttonname", xml); } else if ((xml->name() == "dpadbuttonname") && xml->isStartElement()) { readXmlNamesMiddle("dpadbuttonname", xml); } else if ((xml->name() == "triggername") && xml->isStartElement()) { readXmlNamesLong("triggername", xml); } else if ((xml->name() == "controlstickname") && xml->isStartElement()) { readXmlNamesShort("controlstickname", xml); } else if ((xml->name() == "dpadname") && xml->isStartElement()) { readXmlNamesShort("dpadname", xml); } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } else if ((xml->name() == "keyPressTime") && xml->isStartElement()) { QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); if (tempchoice >= 10) { m_gameController->setDeviceKeyPressTime(tempchoice); } } else if ((xml->name() == "profilename") && xml->isStartElement()) { QString temptext = xml->readElementText(); m_gameController->setProfileName(temptext); } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } m_gameController->reInitButtons(); } else if (xml->isStartElement() && (xml->name() == "joystick")) { this->readJoystickConfig(xml); } } void GameControllerXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); xml->writeStartElement(m_gameController->getXmlName()); xml->writeAttribute("configversion", QString::number(PadderCommon::LATESTCONFIGFILEVERSION)); xml->writeAttribute("appversion", PadderCommon::programVersion); xml->writeComment("The SDL name for a joystick is included for informational purposes only."); xml->writeTextElement("sdlname", m_gameController->getSDLName()); xml->writeComment("The Unique ID for a joystick is included for informational purposes only."); xml->writeTextElement("uniqueID", m_gameController->getUniqueIDString()); // xml->writeComment("The GUID for a joystick is included for informational purposes only."); // xml->writeTextElement("guid", m_gameController->getGUIDString()); if (!m_gameController->getProfileName().isEmpty()) { xml->writeTextElement("profilename", m_gameController->getProfileName()); } xml->writeStartElement("names"); // SetJoystick *tempSet = m_gameController->getActiveSetJoystick(); writeXmlForButtons(tempSet, xml); writeXmlForAxes(tempSet, xml); writeXmlForSticks(tempSet, xml); writeXmlForVDpad(xml); xml->writeEndElement(); // if ((m_gameController->getDeviceKeyPressTime() > 0) && (m_gameController->getDeviceKeyPressTime() != GlobalVariables::InputDevice::DEFAULTKEYPRESSTIME)) { xml->writeTextElement("keyPressTime", QString::number(m_gameController->getDeviceKeyPressTime())); } xml->writeStartElement("sets"); QHashIterator currHash(m_gameController->getJoystick_sets()); while (currHash.hasNext()) { currHash.next(); currHash.value()->writeConfig(xml); } xml->writeEndElement(); xml->writeEndElement(); } void GameControllerXml::writeXmlForButtons(SetJoystick *tempSet, QXmlStreamWriter *xml) { QHashIterator currBtn(tempSet->getButtons()); while (currBtn.hasNext()) { currBtn.next(); if ((currBtn.value() != nullptr) && !currBtn.value()->getButtonName().isEmpty()) { xml->writeStartElement("buttonname"); xml->writeAttribute("index", QString::number(currBtn.value()->getRealJoyNumber())); xml->writeCharacters(currBtn.value()->getButtonName()); xml->writeEndElement(); } } } void GameControllerXml::writeXmlForAxes(SetJoystick *tempSet, QXmlStreamWriter *xml) { QHashIterator currAxis(*tempSet->getAxes()); while (currAxis.hasNext()) { currAxis.next(); if (currAxis.value() != nullptr) { if (!currAxis.value()->getAxisName().isEmpty()) { xml->writeStartElement("axisname"); xml->writeAttribute("index", QString::number(currAxis.value()->getRealJoyIndex())); xml->writeCharacters(currAxis.value()->getAxisName()); xml->writeEndElement(); } writeXmlAxBtn(currAxis.value(), currAxis.value()->getNAxisButton(), xml); writeXmlAxBtn(currAxis.value(), currAxis.value()->getPAxisButton(), xml); } } } void GameControllerXml::writeXmlAxBtn(JoyAxis *axis, JoyAxisButton *axisbutton, QXmlStreamWriter *xml) { if (!axisbutton->getButtonName().isEmpty()) { xml->writeStartElement("axisbuttonname"); xml->writeAttribute("index", QString::number(axis->getRealJoyIndex())); xml->writeAttribute("button", QString::number(axisbutton->getRealJoyNumber())); xml->writeCharacters(axisbutton->getButtonName()); xml->writeEndElement(); } } void GameControllerXml::writeXmlForSticks(SetJoystick *tempSet, QXmlStreamWriter *xml) { QHashIterator currStick(tempSet->getSticks()); while (currStick.hasNext()) { currStick.next(); if (currStick.value() != nullptr) { if (!currStick.value()->getStickName().isEmpty()) { xml->writeStartElement("controlstickname"); xml->writeAttribute("index", QString::number(currStick.value()->getRealJoyIndex())); xml->writeCharacters(currStick.value()->getStickName()); xml->writeEndElement(); } QHash *buttons = currStick.value()->getButtons(); QHashIterator iter(*buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if ((button != nullptr) && !button->getButtonName().isEmpty()) { xml->writeStartElement("controlstickbuttonname"); xml->writeAttribute("index", QString::number(currStick.value()->getRealJoyIndex())); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); xml->writeCharacters(button->getButtonName()); xml->writeEndElement(); } } } } } void GameControllerXml::writeXmlForVDpad(QXmlStreamWriter *xml) { QHashIterator currVDPad(m_gameController->getActiveSetJoystick()->getVdpads()); while (currVDPad.hasNext()) { currVDPad.next(); if (currVDPad.value() != nullptr) { if (!currVDPad.value()->getDpadName().isEmpty()) { xml->writeStartElement("dpadname"); xml->writeAttribute("index", QString::number(currVDPad.value()->getRealJoyNumber())); xml->writeCharacters(currVDPad.value()->getDpadName()); xml->writeEndElement(); } QHash *temp = currVDPad.value()->getButtons(); QHashIterator iter(*temp); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); if ((button != nullptr) && !button->getButtonName().isEmpty()) { xml->writeStartElement("dpadbutton"); xml->writeAttribute("index", QString::number(currVDPad.value()->getRealJoyNumber())); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); xml->writeCharacters(button->getButtonName()); xml->writeEndElement(); } } } } } void GameControllerXml::readXmlNamesShort(QString name, QXmlStreamReader *xml) { int index = -1; QString temp = QString(); assignVariablesShort(xml, index, temp); if ((index >= 0) && !temp.isEmpty()) { if (name == "buttonname") m_gameController->setButtonName(index, temp); else if (name == "controlstickname") m_gameController->setStickName(index, temp); else if (name == "dpadname") m_gameController->setVDPadName(index, temp); } } void GameControllerXml::readXmlNamesMiddle(QString name, QXmlStreamReader *xml) { int index = -1; int buttonIndex = -1; QString temp = QString(); assignVariables(xml, index, buttonIndex, temp, false); if ((name == "dpadbuttonname") && (index >= 0) && !temp.isEmpty()) m_gameController->setVDPadButtonName(index, buttonIndex, temp); else if ((name == "controlstickbuttonname") && (index >= 0) && !temp.isEmpty()) m_gameController->setStickButtonName(index, buttonIndex, temp); } void GameControllerXml::readXmlNamesLong(QString name, QXmlStreamReader *xml) { int index = xml->attributes().value("index").toString().toInt(); QString temp = xml->readElementText(); index = (index - 1) + SDL_CONTROLLER_AXIS_TRIGGERLEFT; if ((index == SDL_CONTROLLER_AXIS_TRIGGERLEFT || index == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) && !temp.isEmpty()) { if (name == "triggername") { m_gameController->setAxisName(index, temp); } else if (name == "triggerbuttonname") { int buttonIndex = xml->attributes().value("button").toString().toInt(); buttonIndex = buttonIndex - 1; m_gameController->setAxisButtonName(index, buttonIndex, temp); } } } void GameControllerXml::readJoystickConfigXmlLong(QList &hatButtons, bool &dpadNameExists, bool &vdpadNameExists, QXmlStreamReader *xml) { int index = -1; bool first = false; bool second = false; QString temp = QString(); assignVariablesShort(xml, index, temp); if (xml->name() == "vdpadname") { first = dpadNameExists; second = vdpadNameExists; } else if (xml->name() == "dpadname") { first = vdpadNameExists; second = dpadNameExists; } if ((index >= 0) && !temp.isEmpty() && !first) { bool found = false; QListIterator iter(hatButtons); SDL_GameControllerButtonBind current; while (iter.hasNext()) { current = iter.next(); if (current.value.hat.hat == index) { found = true; iter.toBack(); } } if (found) { second = true; VDPad *dpad = m_gameController->getActiveSetJoystick()->getVDPad(0); if (dpad != nullptr) { if (dpad->getDpadName().isEmpty()) m_gameController->setVDPadName(index, temp); } } } } inline void GameControllerXml::assignVariables(QXmlStreamReader *xml, int &index, int &buttonIndex, QString &temp, bool buttonDecreased) { index = xml->attributes().value("index").toString().toInt(); buttonIndex = xml->attributes().value("button").toString().toInt(); temp = xml->readElementText(); index = index - 1; if (buttonDecreased) buttonIndex = buttonIndex - 1; } inline void GameControllerXml::assignVariablesShort(QXmlStreamReader *xml, int &index, QString &temp) { index = xml->attributes().value("index").toString().toInt(); temp = xml->readElementText(); index = index - 1; } AntiMicroX-antimicrox-2888bf6/src/gamecontroller/xml/gamecontrollerxml.h000066400000000000000000000057051377703515000266050ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERXML_H #define GAMECONTROLLERXML_H #include "gamecontroller/gamecontroller.h" #include "xml/inputdevicexml.h" class SetJoystick; class QXmlStreamReader; class QXmlStreamWriter; class JoyAxisButton; class JoyAxis; class GameControllerXml : public InputDeviceXml { Q_OBJECT public: explicit GameControllerXml(GameController *gameController, QObject *parent = nullptr); protected: void readJoystickConfig(QXmlStreamReader *xml); // GameControllerXml class public slots: virtual void readConfig(QXmlStreamReader *xml) override; // GameControllerXml class virtual void writeConfig(QXmlStreamWriter *xml) override; // GameControllerXml class private: GameController *m_gameController; void writeXmlForButtons(SetJoystick *tempSet, QXmlStreamWriter *xml); // GameControllerXml class void writeXmlForAxes(SetJoystick *tempSet, QXmlStreamWriter *xml); // GameControllerXml class void writeXmlAxBtn(JoyAxis *axis, JoyAxisButton *naxisbutton, QXmlStreamWriter *xml); // GameControllerXml class void writeXmlForSticks(SetJoystick *tempSet, QXmlStreamWriter *xml); // GameControllerXml class void writeXmlForVDpad(QXmlStreamWriter *xml); // GameControllerXml class void readXmlNamesShort(QString name, QXmlStreamReader *xml); // GameControllerXml class void readXmlNamesMiddle(QString name, QXmlStreamReader *xml); // GameControllerXml class void readXmlNamesLong(QString name, QXmlStreamReader *xml); // GameControllerXml class void readJoystickConfigXmlLong(QList &hatButtons, bool &dpadNameExists, bool &vdpadNameExists, QXmlStreamReader *xml); // GameControllerXml class inline void assignVariables(QXmlStreamReader *xml, int &index, int &buttonIndex, QString &temp, bool buttonDecreased); // GameControllerXml class inline void assignVariablesShort(QXmlStreamReader *xml, int &index, QString &temp); // GameControllerXml class }; #endif // GAMECONTROLLERXML_H AntiMicroX-antimicrox-2888bf6/src/gamecontrollerexample.cpp000066400000000000000000000104701377703515000241510ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska . */ #include "gamecontrollerexample.h" #include "messagehandler.h" #include #include #include #include #include struct ButtonImagePlacement { int x; int y; GameControllerExample::ButtonType buttontype; }; static ButtonImagePlacement buttonLocations[] = { {225, 98, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_A {252, 77, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_B {200, 77, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_X {227, 59, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_Y {102, 77, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_BACK {169, 77, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_START {137, 77, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_GUIDE {45, 23, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_LEFTSHOULDER {232, 21, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_RIGHTSHOULDER {44, 90, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_LEFTSTICK {179, 135, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_RIGHTSTICK {44, 90, GameControllerExample::AxisX}, // SDL_CONTROLLER_AXIS_LEFTX {44, 90, GameControllerExample::AxisY}, // SDL_CONTROLLER_AXIS_LEFTY {179, 135, GameControllerExample::AxisX}, // SDL_CONTROLLER_AXIS_RIGHTX {179, 135, GameControllerExample::AxisY}, // SDL_CONTROLLER_AXIS_RIGHTY {53, 0, GameControllerExample::Button}, // SDL_CONTROLLER_AXIS_TRIGGERLEFT {220, 0, GameControllerExample::Button}, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT {90, 110, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_DPAD_UP {68, 127, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_DPAD_DOWN {90, 146, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_DPAD_LEFT {109, 127, GameControllerExample::Button}, // SDL_CONTROLLER_BUTTON_DPAD_RIGHT }; GameControllerExample::GameControllerExample(QWidget *parent) : QWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); controllerimage = QImage(":/images/controllermap.png"); buttonimage = QImage(":/images/button.png"); axisimage = QImage(":/images/axis.png"); QTransform myTransform; myTransform.rotate(90); rotatedaxisimage = axisimage.transformed(myTransform); currentIndex = 0; connect(this, &GameControllerExample::indexUpdated, this, [=]() { update(); }); } void GameControllerExample::paintEvent(QPaintEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(event); QPainter paint(this); paint.drawImage(controllerimage.rect(), controllerimage); ButtonImagePlacement current = buttonLocations[currentIndex]; paint.setOpacity(0.85); switch (current.buttontype) { case Button: paint.drawImage(QRect(current.x, current.y, buttonimage.width(), buttonimage.height()), buttonimage); break; case AxisX: paint.drawImage(QRect(current.x, current.y, axisimage.width(), axisimage.height()), axisimage); break; case AxisY: paint.drawImage(QRect(current.x, current.y, rotatedaxisimage.width(), rotatedaxisimage.height()), rotatedaxisimage); break; } paint.setOpacity(1.0); } void GameControllerExample::setActiveButton(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (button <= MAXBUTTONINDEX) { currentIndex = button; emit indexUpdated(button); } } AntiMicroX-antimicrox-2888bf6/src/gamecontrollerexample.h000066400000000000000000000030031377703515000236100ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLEREXAMPLE_H #define GAMECONTROLLEREXAMPLE_H #include #include class QPaintEvent; class GameControllerExample : public QWidget { Q_OBJECT public: explicit GameControllerExample(QWidget *parent = nullptr); enum ButtonType { Button, AxisX, AxisY, }; static const int MAXBUTTONINDEX = 20; protected: virtual void paintEvent(QPaintEvent *event); signals: void indexUpdated(int index); public slots: void setActiveButton(int button); private: QImage controllerimage; QImage buttonimage; QImage axisimage; QImage rotatedaxisimage; int currentIndex; }; #endif // GAMECONTROLLEREXAMPLE_H AntiMicroX-antimicrox-2888bf6/src/gamecontrollermappingdialog.cpp000066400000000000000000000617451377703515000253440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska . */ #include "gamecontrollermappingdialog.h" #include "ui_gamecontrollermappingdialog.h" #include "antimicrosettings.h" #include "common.h" #include "inputdevice.h" #include "messagehandler.h" #include #include #include #include #include #include #include #include #include #include #include #include static QHash initAliases() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temp; temp.insert(0, "a"); temp.insert(1, "b"); temp.insert(2, "x"); temp.insert(3, "y"); temp.insert(4, "back"); temp.insert(5, "start"); temp.insert(6, "guide"); temp.insert(7, "leftshoulder"); temp.insert(8, "rightshoulder"); temp.insert(9, "leftstick"); temp.insert(10, "rightstick"); temp.insert(11, "leftx"); temp.insert(12, "lefty"); temp.insert(13, "rightx"); temp.insert(14, "righty"); temp.insert(15, "lefttrigger"); temp.insert(16, "righttrigger"); temp.insert(17, "dpup"); temp.insert(18, "dpleft"); temp.insert(19, "dpdown"); temp.insert(20, "dpright"); return temp; } static QHash initButtonPlacement() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temp; temp.insert(SDL_CONTROLLER_BUTTON_A, 0); temp.insert(SDL_CONTROLLER_BUTTON_B, 1); temp.insert(SDL_CONTROLLER_BUTTON_X, 2); temp.insert(SDL_CONTROLLER_BUTTON_Y, 3); temp.insert(SDL_CONTROLLER_BUTTON_BACK, 4); temp.insert(SDL_CONTROLLER_BUTTON_START, 5); temp.insert(SDL_CONTROLLER_BUTTON_GUIDE, 6); temp.insert(SDL_CONTROLLER_BUTTON_LEFTSHOULDER, 7); temp.insert(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, 8); temp.insert(SDL_CONTROLLER_BUTTON_LEFTSTICK, 9); temp.insert(SDL_CONTROLLER_BUTTON_RIGHTSTICK, 10); temp.insert(SDL_CONTROLLER_BUTTON_DPAD_UP, 17); temp.insert(SDL_CONTROLLER_BUTTON_DPAD_LEFT, 18); temp.insert(SDL_CONTROLLER_BUTTON_DPAD_DOWN, 19); temp.insert(SDL_CONTROLLER_BUTTON_DPAD_RIGHT, 20); return temp; } static QHash initAxisPlacement() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temp; temp.insert(SDL_CONTROLLER_AXIS_LEFTX, 11); temp.insert(SDL_CONTROLLER_AXIS_LEFTY, 12); temp.insert(SDL_CONTROLLER_AXIS_RIGHTX, 13); temp.insert(SDL_CONTROLLER_AXIS_RIGHTY, 14); temp.insert(SDL_CONTROLLER_AXIS_TRIGGERLEFT, 15); temp.insert(SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 16); return temp; } QHash GameControllerMappingDialog::tempaliases = initAliases(); QHash GameControllerMappingDialog::buttonPlacement = initButtonPlacement(); QHash GameControllerMappingDialog::axisPlacement = initAxisPlacement(); GameControllerMappingDialog::GameControllerMappingDialog(InputDevice *device, AntiMicroSettings *settings, QWidget *parent) : QDialog(parent) , ui(new Ui::GameControllerMappingDialog) , helper(device) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); buttonGrabs = 0; usingGameController = false; this->device = device; this->settings = settings; getHelperLocal().moveToThread(device->thread()); PadderCommon::lockInputDevices(); QMetaObject::invokeMethod(device, "haltServices"); QMetaObject::invokeMethod(&helper, "setupDeadZones", Qt::BlockingQueuedConnection); GameController *controller = qobject_cast(device); if (controller != nullptr) { usingGameController = true; populateGameControllerBindings(controller); ui->mappingStringPlainTextEdit->document()->setPlainText(generateSDLMappingString()); } QString tempWindowTitle = QString(tr("Game Controller Mapping (%1) (#%2)")).arg(device->getSDLName()).arg(device->getRealJoyNumber()); setWindowTitle(tempWindowTitle); enableDeviceConnections(); ui->buttonMappingTableWidget->setCurrentCell(0, 0); ui->axisDeadZoneComboBox->clear(); populateAxisDeadZoneComboBox(); currentDeadZoneValue = 20000; int index = ui->axisDeadZoneComboBox->findData(currentDeadZoneValue); if (index != -1) ui->axisDeadZoneComboBox->setCurrentIndex(index); connect(device, &InputDevice::destroyed, this, &GameControllerMappingDialog::obliterate); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &GameControllerMappingDialog::saveChanges); connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &GameControllerMappingDialog::discardMapping); connect(ui->buttonMappingTableWidget, &QTableWidget::itemSelectionChanged, this, &GameControllerMappingDialog::changeButtonDisplay); connect(ui->axisDeadZoneComboBox, static_cast(&QComboBox::currentIndexChanged), this, &GameControllerMappingDialog::changeAxisDeadZone); connect(this, &GameControllerMappingDialog::finished, this, &GameControllerMappingDialog::enableButtonEvents); PadderCommon::unlockInputDevices(); } GameControllerMappingDialog::~GameControllerMappingDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void GameControllerMappingDialog::buttonAssign(int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Only perform assignment if no other control is currently active. if (ui->buttonMappingTableWidget->currentRow() > -1) { QTableWidgetItem *item = ui->buttonMappingTableWidget->currentItem(); int column = ui->buttonMappingTableWidget->currentColumn(); int row = ui->buttonMappingTableWidget->currentRow(); if (item == nullptr) { item = new QTableWidgetItem(QString("Button %1").arg(buttonindex + 1)); ui->buttonMappingTableWidget->setItem(row, column, item); } QList templist; templist.append(QVariant(0)); templist.append(QVariant(buttonindex)); QAbstractItemModel *model = ui->buttonMappingTableWidget->model(); QModelIndexList matchlist = model->match(model->index(0, 0), Qt::UserRole, templist, 1, Qt::MatchExactly); foreach (const QModelIndex &index, matchlist) { QTableWidgetItem *existingItem = ui->buttonMappingTableWidget->item(index.row(), index.column()); if (existingItem != nullptr) { existingItem->setText(""); existingItem->setData(Qt::UserRole, QVariant()); } } QList tempvalue; tempvalue.append(QVariant(0)); tempvalue.append(QVariant(buttonindex)); item->setData(Qt::UserRole, tempvalue); item->setText(QString("Button %1").arg(buttonindex + 1)); if (row < (ui->buttonMappingTableWidget->rowCount() - 1)) ui->buttonMappingTableWidget->setCurrentCell(row + 1, column); ui->mappingStringPlainTextEdit->document()->setPlainText(generateSDLMappingString()); } } void GameControllerMappingDialog::axisAssign(int axis, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool skip = false; if (usingGameController && getEventTriggerAxesLocal().contains(axis) && (value < (-currentDeadZoneValue))) { skip = true; getEventTriggerAxesLocal().removeAll(axis); } if (!skip && (ui->buttonMappingTableWidget->currentRow() > -1)) { QTableWidgetItem *item = ui->buttonMappingTableWidget->currentItem(); int column = ui->buttonMappingTableWidget->currentColumn(); int row = ui->buttonMappingTableWidget->currentRow(); if (usingGameController && (value > currentDeadZoneValue) && !getEventTriggerAxesLocal().contains(axis)) { getEventTriggerAxesLocal().append(axis); } else if (usingGameController && (value < currentDeadZoneValue)) { skip = true; } if (!skip) { if (item == nullptr) { item = new QTableWidgetItem(QString("Axis %1").arg(axis + 1)); ui->buttonMappingTableWidget->setItem(row, column, item); } QList templist; templist.append(QVariant(axis + 1)); templist.append(QVariant(0)); QAbstractItemModel *model = ui->buttonMappingTableWidget->model(); QModelIndexList matchlist = model->match(model->index(0, 0), Qt::UserRole, templist, 1, Qt::MatchExactly); foreach (const QModelIndex &index, matchlist) { QTableWidgetItem *existingItem = ui->buttonMappingTableWidget->item(index.row(), index.column()); if (existingItem != nullptr) { existingItem->setText(""); existingItem->setData(Qt::UserRole, QVariant()); } } QList tempvalue; tempvalue.append(QVariant(axis + 1)); tempvalue.append(QVariant(0)); item->setData(Qt::UserRole, tempvalue); item->setText(QString("Axis %1").arg(axis + 1)); if (row < (ui->buttonMappingTableWidget->rowCount() - 1)) ui->buttonMappingTableWidget->setCurrentCell(row + 1, column); ui->mappingStringPlainTextEdit->document()->setPlainText(generateSDLMappingString()); } } } void GameControllerMappingDialog::dpadAssign(int dpad, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ui->buttonMappingTableWidget->currentRow() > -1) { QTableWidgetItem *item = ui->buttonMappingTableWidget->currentItem(); int column = ui->buttonMappingTableWidget->currentColumn(); int row = ui->buttonMappingTableWidget->currentRow(); if (item == nullptr) { item = new QTableWidgetItem(QString("Hat %1.%2").arg(dpad + 1).arg(buttonindex)); ui->buttonMappingTableWidget->setItem(row, column, item); } QList templist; templist.append(QVariant(-dpad - 1)); templist.append(QVariant(buttonindex)); QAbstractItemModel *model = ui->buttonMappingTableWidget->model(); QModelIndexList matchlist = model->match(model->index(0, 0), Qt::UserRole, templist, 1, Qt::MatchExactly); foreach (const QModelIndex &index, matchlist) { QTableWidgetItem *existingItem = ui->buttonMappingTableWidget->item(index.row(), index.column()); if (existingItem != nullptr) { existingItem->setText(""); existingItem->setData(Qt::UserRole, QVariant()); } } QList tempvalue; tempvalue.append(QVariant(-dpad - 1)); tempvalue.append(QVariant(buttonindex)); item->setData(Qt::UserRole, tempvalue); item->setText(QString("Hat %1.%2").arg(dpad + 1).arg(buttonindex)); if (row < (ui->buttonMappingTableWidget->rowCount() - 1)) ui->buttonMappingTableWidget->setCurrentCell(row + 1, column); ui->mappingStringPlainTextEdit->document()->setPlainText(generateSDLMappingString()); } } void GameControllerMappingDialog::saveChanges() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString mappingString = generateSDLMappingString(); settings->getLock()->lock(); // settings->setValue(QString("Mappings/").append(device->getGUIDString()), mappingString); // settings->setValue(QString("Mappings/%1%2").arg(device->getGUIDString()).arg("Disable"), "0"); device->convertToUniqueMappSett(settings, QString("Mappings/").append(device->getGUIDString()), QString("Mappings/").append(device->getUniqueIDString())); device->convertToUniqueMappSett(settings, QString("Mappings/%1%2").arg(device->getGUIDString()).arg("Disable"), QString("Mappings/%1%2").arg(device->getUniqueIDString()).arg("Disable")); settings->setValue(QString("Mappings/").append(device->getUniqueIDString()), mappingString); settings->setValue(QString("Mappings/%1%2").arg(device->getUniqueIDString()).arg("Disable"), "0"); settings->sync(); bool displayMapping = settings->runtimeValue("DisplaySDLMapping", false).toBool(); settings->getLock()->unlock(); if (displayMapping) { QTextStream out(stdout); out << generateSDLMappingString(); } emit mappingUpdate(mappingString, device); } void GameControllerMappingDialog::populateGameControllerBindings(GameController *controller) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (controller != nullptr) { qDebug() << "Controller has " << controller->getNumberButtons() << " buttons"; for (int i = 0; i < controller->getNumberButtons(); i++) { int associatedRow = buttonPlacement.value(static_cast(i)); SDL_GameControllerButtonBind bind = controller->getBindForButton(i); QString temptext = bindingString(bind); qDebug() << "Button " << (i + 1) << ": " << temptext; if (!temptext.isEmpty()) { QList tempvariant = bindingValues(bind); QTableWidgetItem *item = new QTableWidgetItem(); ui->buttonMappingTableWidget->setItem(associatedRow, 0, item); item->setText(temptext); item->setData(Qt::UserRole, tempvariant); } } qDebug() << "Controller has " << controller->getNumberAxes() << " axes"; for (int i = 0; i < controller->getNumberAxes(); i++) { int associatedRow = axisPlacement.value(static_cast(i)); SDL_GameControllerButtonBind bind = controller->getBindForAxis(i); QString temptext = bindingString(bind); qDebug() << "Ax " << (i + 1) << ": " << temptext; if (!temptext.isEmpty()) { QList tempvariant = bindingValues(bind); QTableWidgetItem *item = new QTableWidgetItem(); ui->buttonMappingTableWidget->setItem(associatedRow, 0, item); item->setText(temptext); item->setData(Qt::UserRole, tempvariant); } } } } QString GameControllerMappingDialog::bindingString(SDL_GameControllerButtonBind bind) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); switch (bind.bindType) { case SDL_CONTROLLER_BINDTYPE_BUTTON: temp.append(QString("Button %1").arg(bind.value.button + 1)); break; case SDL_CONTROLLER_BINDTYPE_AXIS: temp.append(QString("Axis %1").arg(bind.value.axis + 1)); break; case SDL_CONTROLLER_BINDTYPE_HAT: temp.append(QString("Hat %1.%2").arg(bind.value.hat.hat + 1).arg(bind.value.hat.hat_mask)); break; default: break; } return temp; } QList GameControllerMappingDialog::bindingValues(SDL_GameControllerButtonBind bind) { qInstallMessageHandler(MessageHandler::myMessageOutput); QList temp; switch (bind.bindType) { case SDL_CONTROLLER_BINDTYPE_BUTTON: temp.append(QVariant(0)); temp.append(QVariant(bind.value.button)); break; case SDL_CONTROLLER_BINDTYPE_AXIS: temp.append(QVariant(bind.value.axis + 1)); temp.append(QVariant(0)); break; case SDL_CONTROLLER_BINDTYPE_HAT: temp.append(QVariant(-bind.value.hat.hat - 1)); temp.append(QVariant(bind.value.hat.hat_mask)); break; default: break; } return temp; } void GameControllerMappingDialog::discardMapping(QAbstractButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); disableDeviceConnections(); QDialogButtonBox::ButtonRole currentRole = ui->buttonBox->buttonRole(button); if (currentRole == QDialogButtonBox::DestructiveRole) { QMessageBox msgBox; msgBox.setWindowTitle(tr("Discard Controller Mapping?")); msgBox.setText(tr("Discard mapping for this controller?\n\nIf discarded, the controller will be reverted to a " "joystick once you refresh all joysticks.")); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); int status = msgBox.exec(); if (status == QMessageBox::Yes) { removeControllerMapping(); close(); } else { enableDeviceConnections(); } } } void GameControllerMappingDialog::removeControllerMapping() { qInstallMessageHandler(MessageHandler::myMessageOutput); settings->getLock()->lock(); settings->beginGroup("Mappings"); // settings->remove(device->getGUIDString()); settings->remove(device->getUniqueIDString()); // settings->remove(QString("%1Disable").arg(device->getGUIDString())); settings->remove(QString("%1Disable").arg(device->getUniqueIDString())); settings->endGroup(); settings->sync(); settings->getLock()->unlock(); } void GameControllerMappingDialog::enableDeviceConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(device, &InputDevice::rawButtonClick, this, &GameControllerMappingDialog::buttonAssign); connect(device, &InputDevice::rawButtonRelease, this, &GameControllerMappingDialog::buttonRelease); connect(device, &InputDevice::rawAxisMoved, this, &GameControllerMappingDialog::updateLastAxisLineEditRaw); connect(device, &InputDevice::rawAxisActivated, this, &GameControllerMappingDialog::axisAssign); connect(device, &InputDevice::rawAxisReleased, this, &GameControllerMappingDialog::axisRelease); connect(device, &InputDevice::rawDPadButtonClick, this, &GameControllerMappingDialog::dpadAssign); connect(device, &InputDevice::rawDPadButtonRelease, this, &GameControllerMappingDialog::dpadRelease); } void GameControllerMappingDialog::disableDeviceConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(device, &InputDevice::rawButtonClick, this, nullptr); disconnect(device, &InputDevice::rawButtonRelease, this, nullptr); disconnect(device, &InputDevice::rawAxisMoved, this, nullptr); disconnect(device, &InputDevice::rawAxisActivated, this, nullptr); disconnect(device, &InputDevice::rawAxisReleased, this, nullptr); disconnect(device, &InputDevice::rawDPadButtonClick, this, nullptr); disconnect(device, &InputDevice::rawDPadButtonRelease, this, nullptr); } void GameControllerMappingDialog::enableButtonEvents(int code) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(code); bool invoked = QMetaObject::invokeMethod(&helper, "restoreDeviceDeadZones", Qt::BlockingQueuedConnection); if (invoked) qDebug() << "the member restoreDeviceDeadZones could be invoked"; else qDebug() << "the member restoreDeviceDeadZones could not be invoked"; // QMetaObject::invokeMethod(&helper, "restoreDeviceDeadZones", Qt::BlockingQueuedConnection); } QString GameControllerMappingDialog::generateSDLMappingString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QStringList templist = QStringList(); // templist.append(device->getGUIDString()); templist.append(device->getUniqueIDString()); templist.append(device->getSDLName()); templist.append(QString("platform:").append(device->getSDLPlatform())); for (int i = 0; i < ui->buttonMappingTableWidget->rowCount(); i++) { QTableWidgetItem *item = ui->buttonMappingTableWidget->item(i, 0); if (item != nullptr) { QString mapNative = QString(); QList tempassociation = item->data(Qt::UserRole).toList(); if (tempassociation.size() == 2) { int bindingType = tempassociation.value(0).toInt(); if (bindingType == 0) { mapNative.append("b"); mapNative.append(QString::number(tempassociation.value(1).toInt())); } else if (bindingType > 0) { mapNative.append("a"); mapNative.append(QString::number(tempassociation.value(0).toInt() - 1)); } else if (bindingType < 0) { mapNative.append("h"); mapNative.append(QString::number(tempassociation.value(0).toInt() + 1)); mapNative.append(".").append(QString::number(tempassociation.value(1).toInt())); } } if (!mapNative.isEmpty()) { QString sdlButtonName = tempaliases.value(i); QString temp = QString("%1:%2").arg(sdlButtonName).arg(mapNative); templist.append(temp); } } } return templist.join(",").append(","); } void GameControllerMappingDialog::obliterate() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(this, &GameControllerMappingDialog::finished, this, &GameControllerMappingDialog::enableButtonEvents); this->done(QDialogButtonBox::DestructiveRole); } void GameControllerMappingDialog::changeButtonDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->gameControllerDisplayWidget->setActiveButton(ui->buttonMappingTableWidget->currentRow()); } /** * @brief TODO: Possibly remove. This was used for decrementing a reference * count. * @param axis * @param value */ void GameControllerMappingDialog::axisRelease(int axis, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(axis); Q_UNUSED(value); } /** * @brief TODO: Possibly remove. This was used for decrementing a reference * count. * @param buttonindex */ void GameControllerMappingDialog::buttonRelease(int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(buttonindex); } /** * @brief TODO: Possibly remove. This was used for decrementing a reference * count. * @param dpad * @param buttonindex */ void GameControllerMappingDialog::dpadRelease(int dpad, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(dpad); Q_UNUSED(buttonindex); } void GameControllerMappingDialog::populateAxisDeadZoneComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < 28; i++) { int temp = (i * 1000) + 5000; ui->axisDeadZoneComboBox->addItem(QString::number(temp), temp); } } void GameControllerMappingDialog::changeAxisDeadZone(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); int value = ui->axisDeadZoneComboBox->itemData(index).toInt(); if ((value >= 5000) && (value <= 32000)) { QMetaObject::invokeMethod(&helper, "raiseDeadZones", Qt::BlockingQueuedConnection, Q_ARG(int, value)); currentDeadZoneValue = value; } } void GameControllerMappingDialog::updateLastAxisLineEdit(JoyAxis *tempAxis, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (abs(value) >= 2000) { QString axisText = QString(); if (device->isGameController()) { GameController *controller = qobject_cast(device); axisText = QString("%1: %2").arg(controller->getBindStringForAxis(tempAxis->getIndex(), true)).arg(value); } else { axisText = QString("Axis %1: %2").arg(tempAxis->getRealJoyIndex()).arg(value); } ui->lastAxisEventLineEdit->setText(axisText); } } void GameControllerMappingDialog::updateLastAxisLineEditRaw(int index, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (abs(value) >= 2000) { QString axisText = QString("Axis %1: %2").arg(index + 1).arg(value); ui->lastAxisEventLineEdit->setText(axisText); } } GameControllerMappingDialogHelper &GameControllerMappingDialog::getHelperLocal() { return helper; } QList &GameControllerMappingDialog::getEventTriggerAxesLocal() { return eventTriggerAxes; } AntiMicroX-antimicrox-2888bf6/src/gamecontrollermappingdialog.h000066400000000000000000000060041377703515000247740ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERMAPPINGDIALOG_H #define GAMECONTROLLERMAPPINGDIALOG_H #include "gamecontroller/gamecontroller.h" #include "uihelpers/gamecontrollermappingdialoghelper.h" #include class InputDevice; class AntiMicroSettings; class QWidget; class QAbstractButton; namespace Ui { class GameControllerMappingDialog; } class GameControllerMappingDialog : public QDialog { Q_OBJECT public: explicit GameControllerMappingDialog(InputDevice *device, AntiMicroSettings *settings, QWidget *parent = nullptr); ~GameControllerMappingDialog(); static QHash tempaliases; static QHash buttonPlacement; static QHash axisPlacement; protected: void populateGameControllerBindings(GameController *controller); void removeControllerMapping(); void enableDeviceConnections(); void disableDeviceConnections(); QString generateSDLMappingString(); void populateAxisDeadZoneComboBox(); QString bindingString(SDL_GameControllerButtonBind bind); QList bindingValues(SDL_GameControllerButtonBind bind); private: Ui::GameControllerMappingDialog *ui; signals: void mappingUpdate(QString mapping, InputDevice *device); private slots: void buttonAssign(int buttonindex); void axisAssign(int axis, int value); void dpadAssign(int dpad, int buttonindex); void buttonRelease(int buttonindex); void axisRelease(int axis, int value); void dpadRelease(int dpad, int buttonindex); void saveChanges(); void discardMapping(QAbstractButton *button); void enableButtonEvents(int code); void obliterate(); void changeButtonDisplay(); void changeAxisDeadZone(int index); void updateLastAxisLineEdit(JoyAxis *tempAxis, int value); void updateLastAxisLineEditRaw(int index, int value); private: GameControllerMappingDialogHelper &getHelperLocal(); QList &getEventTriggerAxesLocal(); InputDevice *device; AntiMicroSettings *settings; int buttonGrabs; QList eventTriggerAxes; GameControllerMappingDialogHelper helper; int currentDeadZoneValue; bool usingGameController; }; #endif // GAMECONTROLLERMAPPINGDIALOG_H AntiMicroX-antimicrox-2888bf6/src/gamecontrollermappingdialog.ui000066400000000000000000000314641377703515000251720ustar00rootroot00000000000000 GameControllerMappingDialog 0 0 918 600 600 400 Game Controller Mapping 40 20 <html><head/><body><p>antimicrox makes use of the <a href="https://wiki.libsdl.org/CategoryGameController"><span style=" text-decoration: underline; color:#0057ae;">Game Controller API</span></a> provided by SDL 2 in order to abstract various gamepads to fit a unified standard. In order to make a button assignment, please highlight the mapping cell for the appropriate button row below. You can then press a button or move an axis on your gamepad and the cell will update with the physical button or axis that will be used.</p><p>antimicrox will use the mapping that you specify to save a mapping string that will be loaded into SDL.</p></body></html> true true QFrame::Sunken 1 true QAbstractItemView::NoEditTriggers false false false QAbstractItemView::SingleSelection QAbstractItemView::SelectItems Qt::ElideRight true Qt::SolidLine false true true 21 1 true false 100 true true true false 30 true 20 false false A B X Y Back Start Guide Left Shoulder Right Shoulder Left Stick Click Right Stick Click Left Stick X Left Stick Y Right Stick X Right Stick Y Left Trigger Right Trigger DPad Up DPad Left DPad Down DPad Right Mapping 75 true SDL 2 Game Controller Mapping String 0 0 0 0 16777215 100 true 20 300 200 Last Axis Event: true Current Axis Detection Dead Zone: 5000 10000 15000 20000 25000 30000 32000 Qt::Vertical 20 40 Qt::Horizontal Qt::Horizontal QDialogButtonBox::Close|QDialogButtonBox::Discard|QDialogButtonBox::Save GameControllerExample QWidget
gamecontrollerexample.h
1
buttonBox accepted() GameControllerMappingDialog accept() 248 254 157 274 buttonBox rejected() GameControllerMappingDialog reject() 316 260 286 274
AntiMicroX-antimicrox-2888bf6/src/globalvariables.cpp000066400000000000000000000207561377703515000227210ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "globalvariables.h" #include "common.h" #include // ---- JOYBUTTON --- // const QString GlobalVariables::JoyButton::xmlName = "button"; // Set default values for many properties. const int GlobalVariables::JoyButton::ENABLEDTURBODEFAULT = 100; const double GlobalVariables::JoyButton::DEFAULTMOUSESPEEDMOD = 1.0; double GlobalVariables::JoyButton::mouseSpeedModifier = GlobalVariables::JoyButton::DEFAULTMOUSESPEEDMOD; const int GlobalVariables::JoyButton::DEFAULTKEYREPEATDELAY = 600; // 600 ms const int GlobalVariables::JoyButton::DEFAULTKEYREPEATRATE = 40; // 40 ms. 25 times per second const bool GlobalVariables::JoyButton::DEFAULTTOGGLE = false; const int GlobalVariables::JoyButton::DEFAULTTURBOINTERVAL = 0; const bool GlobalVariables::JoyButton::DEFAULTUSETURBO = false; const int GlobalVariables::JoyButton::DEFAULTMOUSESPEEDX = 50; const int GlobalVariables::JoyButton::DEFAULTMOUSESPEEDY = 50; const int GlobalVariables::JoyButton::DEFAULTSETSELECTION = -1; const int GlobalVariables::JoyButton::DEFAULTSPRINGWIDTH = 0; const int GlobalVariables::JoyButton::DEFAULTSPRINGHEIGHT = 0; const double GlobalVariables::JoyButton::DEFAULTSENSITIVITY = 1.0; const int GlobalVariables::JoyButton::DEFAULTWHEELX = 20; const int GlobalVariables::JoyButton::DEFAULTWHEELY = 20; const bool GlobalVariables::JoyButton::DEFAULTCYCLERESETACTIVE = false; const int GlobalVariables::JoyButton::DEFAULTCYCLERESET = 0; const bool GlobalVariables::JoyButton::DEFAULTRELATIVESPRING = false; const double GlobalVariables::JoyButton::DEFAULTEASINGDURATION = 0.5; const double GlobalVariables::JoyButton::MINIMUMEASINGDURATION = 0.2; const double GlobalVariables::JoyButton::MAXIMUMEASINGDURATION = 5.0; const int GlobalVariables::JoyButton::MINCYCLERESETTIME = 10; const int GlobalVariables::JoyButton::MAXCYCLERESETTIME = 60000; const int GlobalVariables::JoyButton::DEFAULTMOUSEHISTORYSIZE = 10; const double GlobalVariables::JoyButton::DEFAULTWEIGHTMODIFIER = 0.2; const int GlobalVariables::JoyButton::MAXIMUMMOUSEHISTORYSIZE = 100; const double GlobalVariables::JoyButton::MAXIMUMWEIGHTMODIFIER = 1.0; const int GlobalVariables::JoyButton::MAXIMUMMOUSEREFRESHRATE = 16; int GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE = (5 * 20); const int GlobalVariables::JoyButton::DEFAULTIDLEMOUSEREFRESHRATE = 100; const double GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE = 2.0; const double GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD = 10.0; const double GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD = 100.0; const double GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER = 0.0; const double GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION = 0.1; const int GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS = 0; // Keep references to active keys and mouse buttons. QHash GlobalVariables::JoyButton::activeKeys; QHash GlobalVariables::JoyButton::activeMouseButtons; // History buffers used for mouse smoothing routine. QList GlobalVariables::JoyButton::mouseHistoryX; QList GlobalVariables::JoyButton::mouseHistoryY; // Carry over remainder of a cursor move for the next mouse event. double GlobalVariables::JoyButton::cursorRemainderX = 0.0; double GlobalVariables::JoyButton::cursorRemainderY = 0.0; double GlobalVariables::JoyButton::weightModifier = 0; // Mouse history buffer size int GlobalVariables::JoyButton::mouseHistorySize = 1; int GlobalVariables::JoyButton::mouseRefreshRate = 5; int GlobalVariables::JoyButton::springModeScreen = -1; int GlobalVariables::JoyButton::gamepadRefreshRate = 10; // ---- ANTIMICROSETTINGS --- // const bool GlobalVariables::AntimicroSettings::defaultDisabledWinEnhanced = false; const bool GlobalVariables::AntimicroSettings::defaultAssociateProfiles = true; const int GlobalVariables::AntimicroSettings::defaultSpringScreen = -1; const int GlobalVariables::AntimicroSettings::defaultSDLGamepadPollRate = 10; // unsigned // ---- INPUTDEVICE ---- // const int GlobalVariables::InputDevice::NUMBER_JOYSETS = 8; const int GlobalVariables::InputDevice::DEFAULTKEYPRESSTIME = 100; const int GlobalVariables::InputDevice::RAISEDDEADZONE = 20000; const int GlobalVariables::InputDevice::DEFAULTKEYREPEATDELAY = 660; // 660 ms const int GlobalVariables::InputDevice::DEFAULTKEYREPEATRATE = 40; // 40 ms. 25 times per second // QRegExp GlobalVariables::InputDevice::emptyGUID("^[0]+$"); QRegExp GlobalVariables::InputDevice::emptyUniqueID("^[0]+$"); // ---- JOYAXIS ---- // // Set default values for many properties. const int GlobalVariables::JoyAxis::AXISMIN = -32767; const int GlobalVariables::JoyAxis::AXISMAX = 32767; const int GlobalVariables::JoyAxis::AXISDEADZONE = 6000; const int GlobalVariables::JoyAxis::AXISMAXZONE = 32000; // Speed in pixels/second const float GlobalVariables::JoyAxis::JOYSPEED = 20.0; const QString GlobalVariables::JoyAxis::xmlName = "axis"; #ifdef WITH_X11 // ---- X11EXTRAS ---- // const QString GlobalVariables::X11Extras::mouseDeviceName = PadderCommon::mouseDeviceName; const QString GlobalVariables::X11Extras::keyboardDeviceName = PadderCommon::keyboardDeviceName; const QString GlobalVariables::X11Extras::xtestMouseDeviceName = QString("Virtual core XTEST pointer"); QString GlobalVariables::X11Extras::_customDisplayString = QString(""); #endif // ---- GameController ---- // const QString GlobalVariables::GameController::xmlName = "gamecontroller"; // ---- GameControllerDPad ---- // const QString GlobalVariables::GameControllerDPad::xmlName = "dpad"; // ---- GameControllerTrigger ---- // const int GlobalVariables::GameControllerTrigger::AXISDEADZONE = 2000; const int GlobalVariables::GameControllerTrigger::AXISMAXZONE = 32000; const QString GlobalVariables::GameControllerTrigger::xmlName = "trigger"; // ---- GameControllerTriggerButton ---- // const QString GlobalVariables::GameControllerTriggerButton::xmlName = "triggerbutton"; // ---- InputDaemon ---- // const int GlobalVariables::InputDaemon::GAMECONTROLLERTRIGGERRELEASE = 16384; // ---- VDPad ---- // const QString GlobalVariables::VDPad::xmlName = "vdpad"; // ---- SetJoystick ---- // const int GlobalVariables::SetJoystick::MAXNAMELENGTH = 30; const int GlobalVariables::SetJoystick::RAISEDDEADZONE = 20000; // ---- Joystick ---- // const QString GlobalVariables::Joystick::xmlName = "joystick"; // ---- JoyDPad ---- // const QString GlobalVariables::JoyDPad::xmlName = "dpad"; const int GlobalVariables::JoyDPad::DEFAULTDPADDELAY = 0; // ---- JoyControlStick ---- // // Define Pi here. const double GlobalVariables::JoyControlStick::PI = acos(-1.0); // Set default values used for stick properties. const int GlobalVariables::JoyControlStick::DEFAULTDEADZONE = 8000; const int GlobalVariables::JoyControlStick::DEFAULTMAXZONE = GlobalVariables::GameControllerTrigger::AXISMAXZONE; const int GlobalVariables::JoyControlStick::DEFAULTDIAGONALRANGE = 45; const double GlobalVariables::JoyControlStick::DEFAULTCIRCLE = 0.0; const int GlobalVariables::JoyControlStick::DEFAULTSTICKDELAY = 0; // ---- JoyButtonSlot ---- // const int GlobalVariables::JoyButtonSlot::JOYSPEED = 20; const QString GlobalVariables::JoyButtonSlot::xmlName = "slot"; const int GlobalVariables::JoyButtonSlot::MAXTEXTENTRYDISPLAYLENGTH = 40; // ---- AdvanceButtonDialog ---- // const int GlobalVariables::AdvanceButtonDialog::MINIMUMTURBO = 2; // ---- JoyAxisButton ---- // const QString GlobalVariables::JoyAxisButton::xmlName = "axisbutton"; // ---- JoyControlStickButton ---- // const QString GlobalVariables::JoyControlStickButton::xmlName = "stickbutton"; // ---- JoyControlStickModifierButton ---- // const QString GlobalVariables::JoyControlStickModifierButton::xmlName = "stickmodifierbutton"; // ---- JoyDPadButton ---- // const QString GlobalVariables::JoyDPadButton::xmlName = "dpadbutton"; AntiMicroX-antimicrox-2888bf6/src/globalvariables.h000066400000000000000000000135341377703515000223620ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GLOBALVARIABLES_H #define GLOBALVARIABLES_H #include #include namespace GlobalVariables { class JoyButton { public: static const QString xmlName; static int IDLEMOUSEREFRESHRATE; static int mouseHistorySize; // Get active mouse movement refresh rate static int mouseRefreshRate; static int springModeScreen; // gamepad poll rate used by the application in ms static int gamepadRefreshRate; static double cursorRemainderX; static double cursorRemainderY; static double mouseSpeedModifier; // Weight modifier in the range of 0.0 - 1.0 static double weightModifier; static const bool DEFAULTTOGGLE; static const bool DEFAULTUSETURBO; static const bool DEFAULTCYCLERESETACTIVE; static const bool DEFAULTRELATIVESPRING; static const double DEFAULTMOUSESPEEDMOD; static const double DEFAULTSENSITIVITY; static const double DEFAULTEASINGDURATION; static const double MINIMUMEASINGDURATION; static const double MAXIMUMEASINGDURATION; static const double DEFAULTWEIGHTMODIFIER; static const double MAXIMUMWEIGHTMODIFIER; static const double DEFAULTEXTRACCELVALUE; static const double DEFAULTMINACCELTHRESHOLD; static const double DEFAULTMAXACCELTHRESHOLD; static const double DEFAULTSTARTACCELMULTIPLIER; static const double DEFAULTACCELEASINGDURATION; // Define default values for many properties. static const int ENABLEDTURBODEFAULT; static const int DEFAULTKEYREPEATDELAY; // unsigned static const int DEFAULTKEYREPEATRATE; // unsigned static const int DEFAULTTURBOINTERVAL; static const int DEFAULTMOUSESPEEDX; static const int DEFAULTMOUSESPEEDY; static const int DEFAULTSETSELECTION; static const int DEFAULTSPRINGWIDTH; static const int DEFAULTSPRINGHEIGHT; static const int DEFAULTWHEELX; static const int DEFAULTWHEELY; static const int DEFAULTCYCLERESET; static const int DEFAULTMOUSEHISTORYSIZE; static const int MAXIMUMMOUSEHISTORYSIZE; static const int MAXIMUMMOUSEREFRESHRATE; static const int DEFAULTIDLEMOUSEREFRESHRATE; static const int MINCYCLERESETTIME; static const int MAXCYCLERESETTIME; static const int DEFAULTSPRINGRELEASERADIUS; static QHash activeKeys; static QHash activeMouseButtons; static QList mouseHistoryX; static QList mouseHistoryY; }; class AntimicroSettings { public: static const bool defaultDisabledWinEnhanced; static const bool defaultAssociateProfiles; static const int defaultSpringScreen; static const int defaultSDLGamepadPollRate; }; class InputDevice { public: static const int NUMBER_JOYSETS; static const int DEFAULTKEYPRESSTIME; static const int RAISEDDEADZONE; static const int DEFAULTKEYREPEATDELAY; static const int DEFAULTKEYREPEATRATE; // static QRegExp emptyGUID; static QRegExp emptyUniqueID; }; class JoyAxis { public: static const int AXISMIN; static const int AXISMAX; static const int AXISDEADZONE; static const int AXISMAXZONE; static const float JOYSPEED; static const QString xmlName; }; #ifdef WITH_X11 class X11Extras { public: static const QString mouseDeviceName; static const QString keyboardDeviceName; static const QString xtestMouseDeviceName; static QString _customDisplayString; }; #endif class GameController { public: static const QString xmlName; }; class GameControllerDPad { public: static const QString xmlName; }; class GameControllerTrigger { public: static const int AXISDEADZONE; static const int AXISMAXZONE; static const QString xmlName; }; class GameControllerTriggerButton { public: static const QString xmlName; }; class InputDaemon { public: static const int GAMECONTROLLERTRIGGERRELEASE; }; class VDPad { public: static const QString xmlName; }; class SetJoystick { public: static const int MAXNAMELENGTH; static const int RAISEDDEADZONE; }; class Joystick { public: static const QString xmlName; }; class JoyDPad { public: static const QString xmlName; static const int DEFAULTDPADDELAY; // unsigned }; class JoyControlStick { public: static const double PI; // Define default values for stick properties. static const int DEFAULTDEADZONE; static const int DEFAULTMAXZONE; static const int DEFAULTDIAGONALRANGE; static const double DEFAULTCIRCLE; static const int DEFAULTSTICKDELAY; }; class JoyButtonSlot { public: static const int JOYSPEED; static const QString xmlName; static const int MAXTEXTENTRYDISPLAYLENGTH; }; class AdvanceButtonDialog { public: static const int MINIMUMTURBO; }; class JoyAxisButton { public: static const QString xmlName; }; class JoyControlStickButton { public: static const QString xmlName; }; class JoyControlStickModifierButton { public: static const QString xmlName; }; class JoyDPadButton { public: static const QString xmlName; }; } // namespace GlobalVariables #endif // GLOBALVARIABLES_H AntiMicroX-antimicrox-2888bf6/src/icons/000077500000000000000000000000001377703515000201655ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/README.txt000066400000000000000000000015671377703515000216740ustar00rootroot00000000000000The icons bundled with this application are using icons bundled primarily with the Mist icon theme. These icons are licensed under the LGPL version 2.1. The assests for the Mist icon theme, bundled in with the full gnome-themes package, can be found at http://ftp.gnome.org/pub/GNOME/sources/gnome-themes/. The full text of the LGPL version 2.1 license can be read in the included lgpl-2.1.txt file. Any icons not bundled with Mist are from the Oxygen icon theme. Those icons are licensed under the LGPL version 3. The full text of the LGPL version 3 license can be read in the included lgpl-3.0.txt file. The full Oxygen icon theme can be downloaded from http://download.kde.org/stable/4.10.2/src/oxygen-icons-4.10.2.tar.xz. Additionally, you can got the Oxygen theme website located at http://www.oxygen-icons.org/. Main icon of application is made by Freepik from www.flaticon.com. AntiMicroX-antimicrox-2888bf6/src/icons/actions/000077500000000000000000000000001377703515000216255ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/actions/about_antimicrox.png000066400000000000000000000012171377703515000257030ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rzbLMc\i/lG4E=WnCxIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/application_exit.png000066400000000000000000000011631377703515000256700ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rzhIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/archive_insert.png000066400000000000000000000006611377703515000253430ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs B(xtIME+6Sw1IDATxڕJ@vZ( >VY iD-bY]PILpYB>8~sf`Of xd/oH a4aB(bq]"0MxT%zb1J XXZV+4r"S;Q A2m\_ $V[ ]o|t}l_n"#B `vW_c |'6^!:]'S~~<Fڙ\+mRN$eCgv*r2K IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/calibration.png000066400000000000000000000013241377703515000246220ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz-x+?4*hW J= ZNylIWm=Zc_nh#s BYsT>LtX>i<[KK;a-T&,X|YA@mIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/dialog_cancel.png000066400000000000000000000015201377703515000250750ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs:tEXtSoftwarewww.inkscape.org<IDATxڥMHqƟ|:3~jiA u D vB'!(I:DI*iV~E&+NL u鹼&=f ] +\[;wm M싗A^ߖXgc_촃wA ay`P-in>UfCYi޾!X.CQ1&TU8XAƆo 1-)'++>_6Sڝ&EY햤,a< G|mfǀR~)Z@ln131e䪱k[ZDI OOPЄ8m?. [y m+Ʀg-Cnēb0 kAAGMeq  at5h8,466!2 &n'`sr-Ag#2Y !j?$WVpKefvXTUU !ѯ qDJH~#/S̅7HbjSVO7qr$3l4"6@#Xq hK=E}KoocA&8B阋ᚚUNs VIQIK)J1{"؊].F 4IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/dialog_close.png000066400000000000000000000014551377703515000247640ustar00rootroot00000000000000PNG  IHDRabKGD pHYs B(xtIME IDATxe[hήlGjc9-.EXJ22ɱ( ||H  XZLnvss m~}DC}1qj 7ZwMc12l.w~`K߷n߯ʊ+gθ6223Gx\lK&>X..TJKK%=믱%Oj zYanJG"8$8bMy椚mu:f.37#;;{-MNHK{4GtԷόZҾi[٧ic]Ⴋ5LO),WD\qO5AZ JAtW?̪j̊R*ZuUJK,Sz|@·;zUj&RC 1 9&BVsO30u.~uTm2Cfw))X8ZE&>K%W?v#jSvv@3yw)n)buYWH_d%@oЄe.|QQ`[~1|Ɋt]Q"Qd?8ɛ 6 @z#̔Y@%Z[QIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/dialog_ok.png000066400000000000000000000011311377703515000242570ustar00rootroot00000000000000PNG  IHDR(-SsBITO pHYs:tEXtSoftwarewww.inkscape.org<PLTE;7 5 9 #5>777 <;:: : 9 ; : ?"B!C"? = ; : 7 %K7Y'M1U2M5V5Z5\3Z0W4V9_5S1F0@1>4?/Mv*DS,Hi-F]3LW5LZ6R^;ToD_yD`MjzOjPmQkRoTpUqVpZv[v[w]z_|`}b}b~bbc{defgghiioptt}~ȫm-tRNS !.38G2sC2] `IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/document_close.png000066400000000000000000000012461377703515000253410ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs:tEXtSoftwarewww.inkscape.org<#IDATxukAJ~R1UIsAx[[<޼+*BVE%л? H5X"BnwV6yy2!c YG t`+?]m!* n5 c4Y8ۻ872T R^+J{}߇>*NNB!ΪB9ߑʸTZ[Wxs:.*Riv \OSҴg `lBN$<#+%T0cI6l[aH⑰eYh4rDR^'\tJAgj#C۶ ݵ(< pg$,-O_أxIRccQIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/document_open.png000066400000000000000000000014201377703515000251670ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<tEXtTitleFolders!T`AtEXtAuthorLapo Calamandreiߑ*)tEXtDescriptionBased of Jakub Steiner designsIDAT8KQ7:%$6bm$& ZԲۢ-AVeѦM!)*lѢRK%xfs}[O-)yQ.""f疘nXjMLbQ g~ebn9 0#_z! 0A@D6jiNx IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/document_open_folder.png000066400000000000000000000012231377703515000265230ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs B(xtIME)frIDAT8ˍKQ}]mm\"4V.o"EFEAIi{=g{Z)D}=}9=d)If{1( 6<7u_dvs_̠aEhǂD "Is݋㶳ӢMY`8=:ĥ )(ATeqi M6)1|P@D>0v8EO{{ng1ʻ*(ֶP]Fݢj9o(Ah,e*.^)"/|Z_eh?ZHkOL\ռ1B=a V>-fnߺAhP3>|\pgr lɣ)+f dy>Ƞ"ZAaEf*u[-P~(B>ЎCĎ8p6u4X 9!m.`n"wapHШ޽>@gcat2ΝlL )"UcR7dž0,1IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/document_revert.png000066400000000000000000000016641377703515000255470ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<tEXtTitlePaper SheetstEXtAuthorLapo Calamandreiߑ*'tEXtDescriptionwith a HUGE help from JakubTIDAT8mKhTI[V1|I FDžA42>p .m  d bP 1 3A("jۤ_tkֽU.EWV !Nk-XO n۸~-~TIkNXҕ-%=ϫTZƇ Ldػ7 $Y6Z>{: 5AaAƠ`r)%,_)2}@|g6&ChB._DWW GKsY91@ZhƂXCJjQR$US[#Rk0@ ň(JS3N$^R3*X g迻|2J(i Rh-m4l#{WbVDkPCA"uol?{gc\8̫kI 5wH) w~?z܆ H_3^U@)dbx 5x!ɇv<(u}]GTLMd 6z9p .m  d bP 1 3A("jۤ_tkֽU.EWV !Nk-XO n۸~-~TIkNXҕ-%=ϫTZƇ Ldػ7 $Y6Z>{: 5AaAƠ`r)%,_)2}@|g6&ChB._DWW GKsY91@ZhƂXCJjQR$US[#Rk0@ ň(JS3N$^R3*X g迻|2J(i Rh-m4l#{WbVDkPCA"uol?{gc\8̫kI 5wH) w~?z܆ H_3^U@)dbx 5x!ɇv<(u}]GTLMd 6z9cdO9=zNm ADx}#""_;YmK&AI"fMdvZ~6ϘYl5kT]H@)iXO>|4r}bz h4m><0992i8N)W0M ӴF044Lr%8_6̄IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/document_save_as.png000066400000000000000000000014051377703515000256520ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<tEXtTitleFile ManagerNstEXtAuthorLapo Calamandreiߑ*tEXtCreation Time2009-11-22&IDAT8KTQg9FIk%0( A1hQ-V-"uQ E6BjEB?ʦd&gDg=-A<#ZJuUlMY%tC.zdpΦ6JN!rwW^3}׺7ꆴK+ڢJ+nH[膼 *7F>=ݖ(\nH5ا+ݐj>Z'ھ qg - %p:^?.ujyZu :r!LpxR(m~7wͦ-fak?׷{O?[OsI+}:_I?YaAC  p(ėQRTXP|VKEΤf~ԫ_n06>Ff!|d"Ci{t_ j>h}fy1CL}D|b#OfCQ$QNNi=!#KKm"_,t}>Ú`f p U+Z<H!~ UP׫ef[9)) TJLj_vfz$O;gKKUJ=]c 2k #soEc+0$ L_oD)Sn,Ϳ``eqV& Ew#9)mHL$cllu"%3I@ MBdc#OPTr:d)-K-L誄HTۼo|xIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/edit_clear_list.png000066400000000000000000000012351377703515000254620ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs B(xtIME9eIDAT8˝KTQ?f4 b1,`hQ2V`̠]-jT(mM3HB,f,̼wZD/r/|Ͻt:q ;n լ! `* oe=bcZ_'TcKJg5RZkHXP@L$I`{ ƀ7e". ACZ٣cV׵Iȱ ~_+*.&ҊXXcvhq|i63jkܞ.>cq})<×'9/_&3c{ƿ-L ЦS+KbLP6ab,nw0(=K6ʣkٚ__1@ٕa1ɕ 7`* lj` _e/+5֦#Z^]RTU1}ѬswݮC w2z(l1'EO<ۑP(x;O'뾞ijjv-m׳G_wy ޞi_ָIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/edit_delete.png000066400000000000000000000020071377703515000246010ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<tEXtTitleAccessibility Preferences-=tEXtAuthorAndreas Nilsson+tEXtSourcehttp://www.andreasn.sezIDAT8eO\ew>/2%c`J@Lw5$ t4´XH غ M[XV2m| mHe(ISf`:}`%>s6\׵Ua8,"Ȓ eoysq.7Ƣۗ}ޥTa$Շ{W 6{{gOPEmm0miLh}y/[P|\y>cPU ۷؛CۺZ;YLTwp^!va3;?F[&1?ln;btӞ{R!v82kkU"| Ϟ:9xcpbP L^#_E8N O"zZ *8,^@U4 jR\) "RN:Y֋Enܼ\YAAl.<V v4NMׇL bOҬVU"i$><42S? E}6Kcvmo|&֎UeјnJ:?#~g= ]]e]%*֚A*cu$:o 4~$NsH4Ͽl, 7&c̏0a\#HWMCA:}4eX05eIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/edit_table_delete_row.png000066400000000000000000000015371377703515000266460ustar00rootroot00000000000000PNG  IHDR(-SsRGB pHYs B(xtIME$*PLTE <<<CC;;;;;;;;;유z{;;;슋߷rr;;;򎏶脄݃把喖tt;;;<<<~jjdey{_TtRNS@@@@@@@Gkkkkkkkksss||VbKGD:N IDAT]; PDs_n *Z*J0ܝB D$>5f`vxSVc? e-n?BOh -mܡCLtI& N)m單d2"r#ڽ0ų~AJWrh;Q%P/u*/ Ru8c.IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/edit_table_insert_row_below.png000066400000000000000000000015241377703515000300740ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs B(xtIME  ,D_XIDAT8˥]efk,Oud! $!:P̃)6Z0hj! <w]֠X[p޻5Ϻ↛I%T̟oHRqٳPj_iǁjop8& ]h?ZJٰ̍}å]==vF8IJsSE{=ϝwdT/⍂ăPұmk֣5x-tnx%6mk-=:uR'IÁ?Vk3*̿! b )l()R %Iߌ~/-#s+I,Wк=X9n ĄA}JCٮ\06&/r)Kk ;])yhSȰ"upҝD"~$32kLvtO)WԨz >uBUZ 5+[){FPBrYh%F|> 1Teɹ`_'(&IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/games_config_custom.png000066400000000000000000000021301377703515000263420ustar00rootroot00000000000000PNG  IHDRa pHYs oybKGDIDATU}PWxt]t]rNˍ "/HкRL!`-ŋ!y_E_**-?a1m֨4Vljb*tRzZ2aCZj9)ҔmI Riqq&>c4ł I$ +B8gW䮀JE%RSy ʨEZ欵}̃9E-fn.--QscJ,S^.Xuu6l'7NL3E%oGGGd4֔L&lh:^ʼ@-0jdϜ7v޳5>>A-..Ȉhb|M-- ܁ecJan9Y\Q |DUxl!햟ڂȮa6XJ\.8'ƀc0hP?_ ۂiRf8>XQQ\?hcuӃ3a'4p qZBd(`4y2k*/Э-zvzL<^ršZ |ʈA"^ϒX,^154>LnY՘s~kn>Ѓ`Cvzs5>UjjjfZ_uke*v9ޛi gP QΙI'oH%H111ɖaRTQv]w)8T!k0G wZZZ˲5[ׯ6яǠ#^a}CBBB!xႬ,˲ /$$$pcDyp۹ D2 #Q<O R)o""zTXtSoftwarex+//.NN,H/J6XS\IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/games_config_options.png000066400000000000000000000020551377703515000265310ustar00rootroot00000000000000PNG  IHDRa pHYs oybKGDIDATxumlSUǟsϹ}oұŷƲF$`D9~`(n1LpGsTc_ T]Z6M:5F6&aڷ޾{=4K'wlyl3H zһ=^ӅSR܅ӟMu`a{5e9׋QxEjP(FUUvJ KSp:/\! "<L44l8$J(0A\3O <-lΎd15>ozهIQ՟{H.WKK70fpD^*QKk`y,&z\U?ghߊyXSUj +UޣnB7NgyCfѴC`/̈37ћ7je2\:.P\[vwDBP1åe++1z 5wo) R<1ާ֨1A _A dR`0GNquWDHJ²,1#TXTܳ1vVVV~o\/ GK& ={^{mFS}сc*A(Fп3LKĴ&%|>}EE߾ zRC BtߋtV-NZ97tr"zTXtSoftwarex+//.NN,H/J6XS\IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/github_page.png000066400000000000000000000014431377703515000246130ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz ͺiL y]|t>W=._v<0xL*L<*0+5/qZ%]N+?̒vuԖq<V߄dh8IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/join_slots.png000066400000000000000000000031551377703515000245220ustar00rootroot00000000000000PNG  IHDRauzTXtRaw profile type exifx[* Y, `9K,~$IN!BH>A\lC0^4O1v|} C֏7 \\|r/7qX 1ABΫf(uRP^)PdYgs+,U#9;qw3B\ػhHhot|>|Λ}er ɟ)q~.Sk콭o}@FVQ\3az74-l -l W[V(J7RNm BX3vSr2uV.efXhM_ϕc%OiL3"qQcOh_چJe9]Vе'-DFf)oA0@rB2+(#rv s2 |ceC `=X G}D eqE$J4$|qeuU4jԤ95ƘbN@I!i)d8ʰ!Yxq_d .qIK.(⋔PĒJ\]1QCki8)oB[jֺK]{F[;A6j歅ȋ\D v.|7p ֕9DvzB>?{?* ēiCCPICC profilex}=H@_?E*"vqPĊVBЪɥB$Qp-8XupqU?@]%1ݽ;_/3 fdBV+ϊb >y?G7gnXSy8JB|Nrlvz}ݬnl_.uK6N%!Κw[Iv3̩~^ |Ti;XT2W:v4lS9ıS:ܲIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/key_checker.png000066400000000000000000000014071377703515000246110ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz|?XD#-B"IzM; ?/^dsa6~~9_uR C<7Y̡h+6XM%)m] mf K^g 6]C6eIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/settings.png000066400000000000000000000013131377703515000241710ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz5K$$&'|czo"M nIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/sliders.png000066400000000000000000000013261377703515000240020ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOSKE**vqP,8jP! :GhҐ8 .κ: x_Rh8{B4c tL'b6"_@}EHf1+I)=uSyߟխ-Df6:Ԧmp'tAG+q.,̨IGb+mJF.Ш94N3p:0IzŎm⺥){0dȦJAZB7[k՛[@f"e}n4rkY9bKGDyX pHYs B(xtIMEVIDAT8ӱNBAУтJCac!ƎJcbG/PVb ΞR-$@3lS Lvٹ3h9(7U @funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz-{C<$%901?aw(B3 $|iq'~m&ؙ7HY M axd+kcK&py 9hQ 98bKy|dl;IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/text_field.png000066400000000000000000000005171377703515000244650ustar00rootroot00000000000000PNG  IHDR(-SsBITO pHYs:tEXtSoftwarewww.inkscape.org<HPLTE fz g h h/UwgihihghLtRNS224Gxxxxxyz{|}~ZWIDATY@*mM%.Ѳ9W *zGy=:G u#mi}Q D%8ݖ:t{, IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/view_fullscreen.png000066400000000000000000000010571377703515000255320ustar00rootroot00000000000000PNG  IHDR(-SsBITO pHYs B(xtEXtSoftwarewww.inkscape.org<tEXtTitleOptical Drive>g PLTEU@@33MF PGQ"JKG!LILH"J"L L I"L!J#L"J#M#M#N J%O!K J#M!K$N!K!K#N$N%O(Q"L"L#M K!K J#M Jüaxy2tRNS &)+/19IJL[hvy|| oIDATu`G3l[UJ}ВDD !жi0,Q,8Ju<|h!;Y#wqNW<Ԩo7R\<:C/!I<}B1O|RΏ6 BreF7ZH{IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/view_refresh.png000066400000000000000000000013371377703515000250270ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rz).200(1 g PdB; p3)6$`?`.@꒻pKچeY A<aBٕIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/actions/wiki.png000066400000000000000000000015641377703515000233040ustar00rootroot00000000000000PNG  IHDRaiCCPICC profile(}=HPOS";8DNDE EjVL^MGbYWWAqrtRtK -bxsx>@funD\dW+2$) nzԜŀH< & ޴ VUs1.Hu71өyXhcYԈSXY+WY᜾uZCH`K BA%a#FN}_"B9PZ /):_c|;N>Wz_3ZZ.[\Olʮ%}S׼5qiV-PϻoOs~?rzI9c{QE\ 71fq.كVULe#eiv`gLK󽄟W3YTSӑ7~ '8 h)p/"kx=[q_.~8 y??U]zU71IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/antimicrox.ico000066400000000000000000010200761377703515000230440ustar00rootroot00000000000000 ( ( ,"bK9!\F(nS0{^6f:{^5nS0YD'K9 * _ */#u7*P="bJ)eM*gN+eM*aI)R>#8*0$w /8+wgO-ϑo?p@p@p@p@p@p@p@p@p@p@p@n?eL,5(q1&YC%fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ZD%3& #E5h : 7l>p@p@pU0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ W`J)p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@vZ3vZ3ޓp@p@p@f:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+Q<";p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Q>#P<#p@p@p@p@p@nS.fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ RT@$p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@']&\p@p@p@p@p@p@c8fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+E4l=p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@f: " "d:p@p@p@p@p@p@o?jP,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ +?0p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@hO-gN,Ɠp@p@p@p@p@p@p@p@z]4fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+8*vZ3p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@;-:,p@p@p@p@p@p@p@p@p@k=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+aI( ?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@m> > p@p@p@p@p@p@p@p@p@p@pU/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ YM:!p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@x\4x[4p@p@p@p@p@p@p@p@p@p@p@`7fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+?/b8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@VA%T@$p@p@p@p@p@p@p@p@p@p@p@p@l=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dK*>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@*c)bp@p@p@p@p@p@p@p@p@p@p@p@p@p@pT/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ YE4p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@f: & &f:p@p@p@p@p@p@p@p@p@p@p@p@p@p@|^5fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+7)jQ.ӓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jQ.jQ.˓p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@h;fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+\E'o?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@?0>/p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?hO,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+$ Pp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@n? D An?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@rV1fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+(jG6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@{]5{]5p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@|^5fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+7)_H)Óp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@YD&XC&p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@f:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+T?#d8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@,"i,!hp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@m=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fL*p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@h; * *h;p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@iO,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ / Gp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nT0mS/ϓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@qU0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+$d7)np@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@B2B3p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@wZ3fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+3&|J8 p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o? I Fn?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@|^5fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+4'P="p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@}_6}_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@b8fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+A1\F(p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@]G(\F(p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@f:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+S?#jQ.Փp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@0$p/$np@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@h;fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+_H(tX2p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@j< / -ifM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM*j=p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@G6F5p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@m>fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+gM+l>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o? N Lo?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@m>fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+jfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fL+d8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@?0?/p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@l=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+tX2p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@.#n-"lp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@j#p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@e9fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+P="P=#p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@wZ4$V#Tw[4p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@b7fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+B2H7p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@eM,$V%WeM,ȓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@|^5fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+4'-#dp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@c8Q>#(] . .(]O<#~_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@vZ2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%x Cp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@f:z]5x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4x\4z]5f:p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oT/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+!`p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@hO,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+,|^6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@l=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dK*XC&p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@e9fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+M: E5p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@{]5fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+5( Jp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@rV0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+%f k=p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?gN+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+aJ*Ɠp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@g:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+VA$B2p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@{]5fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+6( 3p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mS.fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ MtX3ߓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@k=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+`H(G6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nGmSk\k]lUnJp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nIlTk\k]lTnHp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@~_6fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+:, 8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jad]YWWWWWWX]bijoCp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oBigc]YWWWWWWY]cjdoAp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nS/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ SqV1ۓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nMcZWWWWWWWWWWWWWWXalWp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@lTbYWWWWWWWWWWWWWWYbmOp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jeM,ʓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oF`WWWWWWWWWWWWWWWWWWWWWWWWWW\mPp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mM^WWWWWWWWWWWWWWWWWWWWWWWWWW_nIp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@g;fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+XB%5(op@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nL\WWWWWWWWWWWWWWWWWWWWWWWWWWWWYk]p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@lWZWWWWWWWWWWWWWWWWWWWWWWWWWWWW[mRp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@x[3fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%l>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mOZWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXjbp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@k[YWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWYlTp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?iO,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ (ZE'p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nI[WWWWWWWWWWW[wãɬɭŦ~^WWWWWWWWWWWYlXp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mSYWWWWWWWWWWW]|ĥɭɭäy[WWWWWWWWWWWZmMp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@e9fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+N; (\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@^WWWWWWWWWWlĥʮ{WWWWWWWWWWZnIp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oE[WWWWWWWWWWtȫƨqWWWWWWWWWW]oBp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@uX2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+,!s f:p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@dWWWWWWWWWbƨ϶lWWWWWWWWW_p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@`WWWWWWWWWi̲ȬeWWWWWWWWWbp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@n?gN+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+eL+R>$p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@lVWWWWWWWWWyWWWWWWWWWhqp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ihWWWWWWWWW}WWWWWWWWWk]p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@b8fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+D3 Jp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@^WWWWWWWWWWWWWWWWYoEp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oB[WWWWWWWWWWWWWWWW\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@qV0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+%e~_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jdWWWWWWWWWWWWWWWWep@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@fzWWWWWWWWWWWWWWWWimp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@l=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dK* I7 p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@^WWWWWWWk}WWWWWWWYoBp@p@p@p@p@p@p@p@p@p@p@p@p@p@o@ZWWWWWWWwoWWWWWWW]p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@~`6fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+<. 8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mPWWWWWWWWѹ_WWWWWWWhmp@p@p@p@p@p@p@p@p@p@p@p@p@p@jeWWWWWWW\վYWWWWWWWlXp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nS/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ SqV1ۓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@dWWWWWWWWWWWWWW_p@p@p@p@p@p@p@p@p@p@p@p@p@p@aWWWWWWWWWWWWWWcp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jeM,ʓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@k_WWWWWWW̱WWWWWWWf}p@p@p@p@p@p@p@p@p@p@p@p@guWWWWWWW϶WWWWWWWigp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@g;fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+XB%4(np@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@gwWWWWWWWWWWWWWWbp@p@p@p@p@p@p@p@p@p@p@p@cWWWWWWWԾWWWWWWWfp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@x[3fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%l>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@dWWWWWWWfWWWWWW_p@p@p@p@p@p@p@p@p@p@p@p@`WWWWWW`XWWWWWWcp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?iO,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ (ZE'p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@cWWWWWWYqWWWWWW^p@p@p@p@p@p@p@p@p@p@p@p@_WWWWWWm`WWWWWWap@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@e9fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+N;!(\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@bWWWWWW^vWWWWWW]p@p@p@p@p@p@p@p@p@p@p@p@^WWWWWWreWWWWWW`p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@uX2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+,!s f:p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@cWWWWWWYqWWWWWW^p@p@p@p@p@p@p@p@p@p@p@p@_WWWWWWl_WWWWWWbp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@n>gN+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+eL+R>$p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@dWWWWWWWdWWWWWW_p@p@p@p@p@p@p@p@p@p@p@p@aWWWWWW^XWWWWWWcp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@b8fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+D3 Jp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@guWWWWWWWWWWWWWWcp@p@p@p@p@p@p@p@p@p@p@p@dWWWWWWWӼWWWWWWWf}p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@qV0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+%e}_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@k\WWWWWWWʮWWWWWWWf{p@p@p@p@p@p@p@p@p@p@p@p@hrWWWWWWWͳWWWWWWWjep@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@l=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dK* I7 p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oCXWWWWWWrWWWWWWWk[p@p@p@p@p@p@p@p@p@p@p@p@mRWWWWWWWuWWWWWWWnHp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@~`6fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+<. 8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@^WWWWWWW]WWWWWWYo@p@p@p@p@p@p@p@p@p@p@p@p@p@ZWWWWWWZWWWWWWW\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nS/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ SqV1ۓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@eWWWWWWWWWWWWWW`p@p@p@p@p@p@p@p@p@p@p@p@p@p@aWWWWWWWWWWWWWWdp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mQXWWWWWWWWtWWWWWWWWWiip@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jaWWWWWWWWWuWWWWWWWWWlWp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?iO,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ 'ZD'p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@fWWWWWWWWW^ŧȫeWWWWWWWWWap@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@bWWWWWWWWWd̲_WWWWWWWWWdp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@e9fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+N;!(\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@_WWWWWWWWWWg£ŧnWWWWWWWWWW[oEp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oC\WWWWWWWWWWnǫgWWWWWWWWWW^p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@tX2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+,!s f:p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oE]WWWWWWWWWWWWoǫȬävYWWWWWWWWWWWYmQp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mMZWWWWWWWWWWWXt£ǫȫ¢qWWWWWWWWWWWW[nHp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@n>gN+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+eL+R>$p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nJ\WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWYlYp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@lTZWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW[mNp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@c8fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+D3 Jp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nH]WWWWWWWWWWWWWWWWWWWWWWWWWWWWZlUp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@mP[WWWWWWWWWWWWWWWWWWWWWWWWWWWW\nKp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@qV0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+%e}_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oBbWWWWWWWWWWWWWWWWWWWWWWWWWW^nKp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nG`WWWWWWWWWWWWWWWWWWWWWWWWWW`oEp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@l=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+cK* I7p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ijZWWWWWWWWWWWWWWWWWWWWWWXfp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@fxYWWWWWWWWWWWWWWWWWWWWWWYgpp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@~`6fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+<. 8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oEdYWWWWWWWWWWWWWWWWWWWanLp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nJbXWWWWWWWWWWWWWWWWWWXcoFp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nS/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ SqV1ۓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@oFe]WWWWWWWWWWWWWWZcnMp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nKd[WWWWWWWWWWWWWW[enHp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Xɳp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@sA`~|]q@o?iO,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ 'ZD'p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@_ͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@xDvri;fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+M: (\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@_ͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@qdfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+,!s f:p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@_ͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Srm#p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Xͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@k\fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+D3 Jp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Tͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@wkfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+$d}_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Tͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@xmfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+cK* I7p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Tͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@n_fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+<. 7p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Tͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@XwxBfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ RqV1ۓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Tͷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@q@xmfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+^H(?0p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Uθp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@I}vk[2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+6) %o?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@sCdnnnnnnnnnn˹yyyyyyyyyxdp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@{Fk_iV0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ =dL+ɓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\vGp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@yDTYOiU0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+WB%4(np@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@íp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@c}~krCp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@uCyEtCp@p@p@p@p@p@p@p@p@p@p@p@p@x[3fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+iN;mNKjN;fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%l>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Uθp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@{O«ѼӿȲXp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@qAN\aaa[Lp@p@p@p@p@p@p@p@p@p@o?iO,fM+fM+fM+fM+fM+fM+fM+fM+fM-wQuUWWWUwQrfM-fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ 'ZD'p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@xӾqAp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@sBYaaaaaaaؑVq@p@p@p@p@p@p@p@p@e9fM+fM+fM+fM+fM+fM+fM+fM+gM2TWWWWWWWTgM1fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+M: (\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@DzѾtEp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ۓWaaaaaaaaa͌Rp@p@p@p@p@p@p@p@uX2fM+fM+fM+fM+fM+fM+fM+fM+SWWWWWWWWWSfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM++!r f:p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Įмp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@~Iaaaaaaaaaa`wEp@p@p@p@p@p@n>gN+fM+fM+fM+fM+fM+fM+fM+oOTWWWWWWWWWWWnOPfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+eL+Q>#p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@kp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ԐUaaaaaaaaaaaƉPp@p@p@p@p@p@b8fM+fM+fM+fM+fM+fM+fM+fM+~SWWWWWWWWWWW}RfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+D3 Ip@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@qBθ|Op@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@[aaaaaaaaaaaؑVp@p@p@p@p@p@qV0fM+fM+fM+fM+fM+fM+fM+fM+TWWWWWWWWWWWTfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+$d}_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@sp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@[aaaaaaaaaaaڒWp@p@p@p@p@l=fM+fM+fM+fM+fM+fM+fM+fM+fM+UWWWWWWWWWWWTfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+cK* I7p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@пϺp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ۓWaaaaaaaaaaǎRp@p@p@p@p@~`6fM+fM+fM+fM+fM+fM+fM+fM+fM+SWWWWWWWWWWWSfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+<. 7p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Up@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Laaaaaaaaaaa|Hp@p@p@p@p@nS/fM+fM+fM+fM+fM+fM+fM+fM+fM+tPeWWWWWWWWWWWrP`fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ RqU1ړp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\Ѽp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@zLqp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@q@[aaaaaaaaaܔXp@p@p@p@p@jfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+6) %o?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Zлp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Swp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@uCבV`aaa`ύSsBp@p@p@p@p@p@kQ-fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+iN;SVWWWVSiM9fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ =dL+ɓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@tEϻp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@sDgp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@uCJLJsBp@p@p@p@p@p@p@g:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+iM:sPcwQqsPciM8fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+VA$4(np@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Ӿ\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ѾsDp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@x[3fM+fM+fW9fcIfV7fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%l>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@eƲʷʷʷʷʷʷʷʷʷʸƯʷʷʷʷʷʷ˶˶˶˶Vp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@­ҿp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?iQ/f}ffffffsfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ 'ZD'p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Sqp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@kBffffffffffP/fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+M: #Up@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ɵĭp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@pfffffffffffM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+)m}_6p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@vH[p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@lfffffffffffffMfM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+cK) B2p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@Xmp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@vfffffffffffffM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+9+!l>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@VҾhp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?hfffffffffffffM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ 2M;!p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@tFî̸~Rp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@a7ffffffffffffffM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+C2 #l>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@xKìȲ~Sp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?kQ-ffffffffffffffM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ 7M;"p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@a7fM+fvffffffffffffwefM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+C3e:p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@m>iP,fM+fO.ffffffffffffM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dL* '3&rp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@T̸p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@x[3fM+fM+fM+fcJffffffffff]@fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%nT/ӓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@~R˶p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@i;fM+fM+fM+fM+fM+f^BffffffffY;fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+WB%  1j=p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@rCʷp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?mR.fM+fM+fM+fM+fM+fM+fM+f^Bfrffpf[>fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ B3'vp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@~Tp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@y[3fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+4'`I)p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@hʸппппппппппоï}Qp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@f:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+P<"vY3ݓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@jlR.fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+eL* ; Hjp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?tX1fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+#q!PhpT0fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dK* M (oU0ԓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ivZ2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dL*)}ZD'p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@e9jP-fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+N;  /&YvY3ߓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@k=tX2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+_H(%o2&pa8p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@m>z\4gM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+dK*3&7*uw[3p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@l=z\4hN,fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+aI)3'(]`I)Ño?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?g:vY2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+S?#-"x ;-{iQ-ґo?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@i<{]5kQ-fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+\E'5( 8* _R?$sW2ߑo?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@k=c8w[3kP-fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+bJ)D30$x 4 D9+pK9 R?$bK+nT0vZ3b8ha pHYsItEXtSoftwarewww.inkscape.org<FIDATxyUՙ޻APTpES Z:e1'L*:8ʦ&Nb8 D &(*t~^,w;s.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#|=K2L`0_ّ*c[(q,Œ1cax P i!CjW4khȧXp Pw9h#:&Wz/N@??QfB$ +#zxGk2huO>k3, _O_UqRP@u7f4LGn,#L!%UuV>XkS*+Y4F t1p")xkw?z5:J%xʂ%W*!_N,njt(M3zɽ^_$Jb,K);>ty%F8R.J ˈN1ax=nW,xdRJu9_Y6pۈqᴚ_kBqXdR<#c Mmʵ^ݻ7ܒ pڜLQr}ME_Lme_e9 l޾ǭ"- L!5Ս< !ΣV>0iϜ:_P^;#܆0z|Rs'^B9P7(2i'Kd;L rp@pIa$6{ZpE,$ QB$g4iUY'CJ3fAʪ:'W(L͛|ݕEX1bh֫/fp]UmVr?.gC)ϝXw,Khpg1e+Py/ƌ‚YST>@eõݏO1̉:nƢ갨_:WȽY.R4LDzAFSS~$W7ڞx7/tL#x؂bUTT1 e8+Ҟ7l~ڼg@ϴL`Xar-Ӽ (x VLn|"HkGƑ c9G9Ё=p$54aL0a@s f3g&|:OGb{h?ph@WLyp`^G 0X893cѓol_tcS!-h d,/X|&DХDb&3!ײtOV40p*!4X@p0Sd'?엛D h<ߕURh )sc5{ V`ߡ1p-\atW~U vt_w|17\fm,b[Y P+ U7J7Dxm8q&nڄc&MmQB#)x+x ҡR7`O{ 2uK9c9jVXVAQ)+xl۵?uLަ~U?{ NRu4Yѓ~BJ8N{mD)H 9DG cc1B)lYnoo{0 c;[Cy ;V𡏰Fֽo޼%Iڕͫv+mfV[=iuvYkܗwX-ᯬۂOh7t̉ T8n8*q2d/c}N}xEHeFh۟|:#&*-O_ם9ԦlSޗW@Gik<7kL9lz5K;ZsԠ:KE@x|k pżp)7㈮YrSwW~'_>EqL?ޔ= ,_A,nw4S^zU=ݼYeƿ@cTy( uՕju E1\&R֝0fhyLj dDA'L,|_`E-q0[8A~;qwa;ǗAXX+ 4b-3,m^g*͟-W`-})D TC!̭!/hGwy ̸b|L1P8\m> 6n )s y1iڪZ4V?l BI!,|"9vKYqŌb]W0ȆAQ%Q~ )0{ίR4XpyD[eU yZFr&s8B)RrAw8\ߞvu;O; f;L STQg fwn蘵O6f;: (e/pGki'FCovya^̣%0%u+9S;@[(e57#0.ұ^?l*D%cKocIOgu"qc2MUWKgyDӷH3G;'a &&.[:2sv퍢q3e #:61drRwIfR1d6#0 lHXv\u9R:;}e=5>VaYHjf}uBWU{P9pL”0mq1WSO!Pi~v7a Z|zi4wJ5h*|UR:ےkSJރ=ٶ ՙfvd'-C K!)AU)舙4b8tʨX++G1b_MuLn|"( O\Tζ}Cܰ E ^ԑ lFL~fсڶr6pm,$IsGb)!AVEN|cc}-@ "!Yol-ʡᘙZ'|O_&[9#rY3ꜷZʙ^RtGGCW'Q~C!`}{Gw嗪d?e1l`tHXR!L0~_G?܀g;To0o&lj$? xO&Zkn>z_SϬI8B*j aZC`G:r^ ~bwf܎7^?'*T*^공 oRPi'~kjؤ ^-/lvE#'^H@;:#`s@[ ۡݔmݍ4,9D{}y=UolE=:Kz&T#LMnۇ4L`;ewR\-aIK^0c8. 7ys?S}dcO9 d1hq( O4.Zɻyf+lq2 Z@q?e7Auo>﫠W`Vh3_~۫|Jx3+J!4c`GV .*wd/ VӲR'^Ҩʰy] ɛtEt4u/&\p5nQo+N7΂j >ÞBbiQT9.U >!BZf}:[e_~SSZ4kS)>+*BؖU`Y@v(=BH` 6c<< |'}DZ@.KTN1K*FKOΖ‘g@ wu:u.:o(%HsQBuKpքh>׶m4]GixdCsܟ B =^Mn2 ~7bRbxH,XrA*FNhg;4ߔJx eM?+`yk|EQ?^laQ&oS(Q>C{R#$w#~Ŋs )wW$Ճv5HTiEP$HFS-˖<~7 llt4 '*HK"Qaq+,6~}"e~&+C,@4)cR(Y HXpγBx>f[B+/!.m*.x2쟏"r}/A6I|uɹwo_1qgđD f<7 וDz.@|wL$7Ypʸ+!)aK7ϛA(xiբ9Ař? #zV(?}K;W-(tn*@~R1wwpPڢn(6T 6ҷ^hc+uj@=|<.M^ CK\הl [sR[ )21zbY j+(6d7~]#V6BD"Mt m+oz]u=(֊~G7+$c[B;0e/~%arEI\]h#%{\bܥփ[I]E~{±^X:/$HT(8OMA($5U W/z'̾lFM|Q'$jʇz eכFNjT7*%O}"h)VX9~⯬^[!5˿\JXhva*ң5 2_Yyj/a.A޷NfŒ9"F_G3~bٲF8_V-{;i& h7} JoZ8| 둝 7}gF4<߱, M@uOݿ192yQ ߍB9#H`6? 3/-3f4? saʶǑR !Vkh[3!IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/application/16x16/000077500000000000000000000000001377703515000232555ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/16x16/apps/000077500000000000000000000000001377703515000242205ustar00rootroot0000000000000016-apps-io.github.antimicrox.antimicrox.png000066400000000000000000000012401377703515000342510ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/16x16/appsPNG  IHDRasBIT|dWIDAT8ŒOQϼ@H)@T1ąA!ȎjqG• &raLX{ Nc( bKDR k:vf{.JL{s͹7DIԩc e3Ncn'Y} 7 җ/S8p+ eOwV?d;6Pr?ʹd: 6c% ӌSXBw:Qn8SyO_c)iQBg:£:6.$|Rx[ddף󳓎UH9 I߶ZRVy[tyn抹߼ sX .%%gO#7"jwZY$IENDB`AntiMicroX-antimicrox-2888bf6/src/icons/application/24x24/000077500000000000000000000000001377703515000232535ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/24x24/apps/000077500000000000000000000000001377703515000242165ustar00rootroot0000000000000024-apps-io.github.antimicrox.antimicrox.png000066400000000000000000000020361377703515000342520ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/24x24/appsPNG  IHDRw=sBIT|dIDATHT]OU~Μ- ||u IkQbbz1.4.ze&Djbi l;|/`7P:=>{Λ<> E'eᒊ3ۆid7n2kt3p!V<24$cЕD|~͕y7xp ߍ긹xM>+xѥMA- \w Yu9+ioqGM'8t ~[i('"Nv!3Ԝׁ7e8%.i8*] cYHe(*rB?UlY. Z!ziZN3X m࿽WpC8P0ⲠpؖSn_!VN ?b07/0,RN`ke 4 c~5) G(u|<#^M~{KХ)fW_jyL}Z[~L;Mύ 1Ƭ5`Y$ӻ 0Bڟު^,lfn~;rliiaԔ/JyB8Ik2B.kܾ# ~aIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/application/32x32/000077500000000000000000000000001377703515000232515ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/32x32/apps/000077500000000000000000000000001377703515000242145ustar00rootroot0000000000000032-apps-io.github.antimicrox.antimicrox.png000066400000000000000000000025471377703515000342560ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/32x32/appsPNG  IHDR szzsBIT|dIDATXUKlTUιywii 4--BbcZ5&b1ƕuv7.lcЅ PB_v>yu܇i"F7vX a.t56z7Z %%A H*@Dhs\vxJf{IC%P$1STUwP;9J-g Pʀ7 >a BеKB7!]P<Ԭ)AUYQI&mL]X{;ٛ<87<![0=%u˷qt6UAHHpO Ըz/w:^<AdE-c€yd >2-2 :@4c"Rfzx;ŰǏ㾹mR: oFL1XMlJ=Ǜ}sL,Ccu9>Wv !!1%缎GꄒR3uEN/P唐8L"0>A0D QDHAhLf0,g[ꕜjb_qB7&5T1,Tm>6)kx+Rd|gէp֬褻}ݙ8ٙ_i!q_zi A ۡnw%+qp4t[ٶgXlN'" {i7o4;QS)*rh _:8s&"KG5M@UrT2ao t>,#}s '9|<8yNűiOеNSY ]Ddb_ 9\x| 6Pd)7ͪJ<UI%/]Udq~=vcm Gu[Y2<= UIƲe~xiIENDB`AntiMicroX-antimicrox-2888bf6/src/icons/application/48x48/000077500000000000000000000000001377703515000232675ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/48x48/apps/000077500000000000000000000000001377703515000242325ustar00rootroot0000000000000048-apps-io.github.antimicrox.antimicrox.png000066400000000000000000000044211377703515000342740ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/icons/application/48x48/appsPNG  IHDR00WsBIT|dIDAThX[lT]?0]RA!! QJ4m($~$ԏFh~UU4QTQ"`BHlf0=w~ 6cc~yI#ͽ{}:wf1YbRhwVj}yf/-#ЈAMNM]$oS L78˂KZVѴ|+ b N" ZR3;54U),kyy?h!gK0JCM-4p_Go^dqɌ‡ Bఉy&e3&?KryaL-[h8j/Yr΃˶>{1hw <:C/&'M,m.WELfn[GvIo^ڹ /zUEp/^rPt[~rIC_'Qf4V`IC ^0)DG0P, R!xyWܪ rYAZ 18q17379)ቭ-j=p*˰41N%1h1M8D6$2ʸx!ӆ|8%>ރ_JspXAcD݂=.NaB$'n")kHf APTg.b8 Q sSOlˌwNn-yk`s,AGx:@LRxZ. ֱv,W Bΐ/$W%D*z;p{,s`sWfF/6nX= ҋ=PSE3p-.\UXY0KY>CMW~f LCIK+wZ 5Pu"̡g2&RYSӸpBe\bڿ;22T@$yc2PL`f9Ce8FnEyl/H6;8Öz|R"O=7i (|ؕ#8_o$(.;PL1Yơ['CZ ]SxhZd1^R*An óWBbX8y;lH߉~j%7l./wrEdw1^L]y5Pv^;+`xg60BD 9s p]`d#ZlA^qNHr Pu9 #5`` c 2P zu&5|uc\ڲZK s US(yS)죾` j@ 'Լp};˪׊<]I8\r7&K;FO]G^ E`|(0 6x6h߄x_mӓ݅lAοR ~X11xK&0HX,/AHius*N;>rPSևlXM, .[oݼZܯ 8&'ãi  %\䤀DHiԴJjT*E%JTh6$ )`cm1zcfvf~ci"u?̼~}~yɓ'O8gk^x4X^'!k#,k6) x&`S4QtНw'QX]<l S:tc?XQ5Y!ZDQ4e\ўv˛lǦKJ@UR9UI%][-#T Ӛ20Sʧt xO#`f,@l0$j4l) .=lsz",'㥉+ԦqMS XƄZle 4|` h-šMdW?r& DIbZUC "PlRvRo‹` #* ĠSi&*:*`w,}fx̝_.\1%A QYMN8,72e"s "Qɥn= d3{H `n;l(wrzb{SP`Niә%8i&`#2~"oO@)p@阾C |bn*fwL ZbC ֏íǂ} 3M@LQzB:`?s) "d @J4EzаMVGlZF Lq WH?8n!x fESfՒq,6,dj^ gB,hJo_kRXrW.qJURP#i AX qK %BcCVW\1sg#{*2CН|$X`/[)+pŰ.*k\#ϼxPI D:x;eX AL"vg#'XEMwxwB؛Ih癿6?,'d7N.bX^hh.|v[t|7=bV!/h-.Iuj=w?׎Q_7^FwkDBqFyxv>6rȁgw(5];*EL7z9W'*G>r=TדV=@;\?=?_=G|L!9x{?ep^Ew!;uڹc%2?Dí9-UYt~k'uco!Tהکʱ0:$c!H!of@˱Mi+x?LT96.ŏ(M0ye)8~wy`-(Uك}'b>/8ZslR{y틽Zב{u-{<ݟÅqyHکq{)*0ň cEŧ mr߷/Tע۶3-kC#'_$w_\|Nšbkrd>rl(0нFLr79Ը _pGoM'OAntiMicroX-antimicrox-2888bf6/src/icons/lgpl-2.1.txt000066400000000000000000000636421377703515000221750ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! AntiMicroX-antimicrox-2888bf6/src/icons/lgpl-3.0.txt000066400000000000000000000167431377703515000221750ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. AntiMicroX-antimicrox-2888bf6/src/images/000077500000000000000000000000001377703515000203175ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/images/16x16/000077500000000000000000000000001377703515000211045ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/images/16x16/antimicrox.ico000066400000000000000000000021761377703515000237630ustar00rootroot00000000000000 h(  ;-j(I J* lI7 p@n?%C"DeL+fM+3'b7p@p@b8  b8oT/fM+YC&l>p@p@p@fM,  fM,p@sW1fM+dK*w[3ғp@p@p@p@lUiho@o@ihlUp@o?lQ-fM+S>#D4{p@p@p@mNεii϶mOh;fM+fM+0$| !o?p@p@lUȬjk¢lUy\4fM+eL* "oT0ēp@xKshlfoFoEfhlMjP-fM+M: :,itEϾxp@^]p@{GQrQ^fM+)j nBȴpp@Űìp@xEy}nPPbJ)?0rwImp@p@p@p@p@f:f]AeL*,!s 6D4yH7~H7~H7~H7B23'0$z 8AntiMicroX-antimicrox-2888bf6/src/images/16x16/io.github.antimicrox.antimicrox.png000066400000000000000000000012401377703515000300270ustar00rootroot00000000000000PNG  IHDRasBIT|dWIDAT8ŒOQϼ@H)@T1ąA!ȎjqG• &raLX{ Nc( bKDR k:vf{.JL{s͹7DIԩc e3Ncn'Y} 7 җ/S8p+ eOwV?d;6Pr?ʹd: 6c% ӌSXBw:Qn8SyO_c)iQBg:£:6.$|Rx[ddף󳓎UH9 I߶ZRVy[tyn抹߼ sX .%%gO#7"jwZY$IENDB`AntiMicroX-antimicrox-2888bf6/src/images/24x24/000077500000000000000000000000001377703515000211025ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/images/24x24/antimicrox.ico000066400000000000000000000046361377703515000237640ustar00rootroot00000000000000 (0  5   7mS/p@l>/#S!UcK)fM+M: ;-ip@p@p@h;    nS/fM+fM+fM+* lrV1ȓp@p@p@p@pU1oU0ćg:fM+fM+fM+PfM+fM+fM+bJ)l=p@p@p@p@p@m>7*b        6)am>p@m>fM+fM+fM+cK)vY3ϓp@p@p@p@p@p@p@p@o@p@p@p@p@o@o@p@p@p@h;fM+fM+fM+S>"G6~p@p@p@p@p@p@lXfvbo@o@bvflXp@p@z]4fM+fM+fM+3&#o?p@p@p@p@p@chnhlbp@o?kP-fM+fM+eL* &qU1Ɠp@p@p@p@p@fĦfxgw˰ep@g:fM+fM+fM+Pp@p@X̷YmPjcoCp@p@oCjcmPqA\iP,fM+fM+cK) fN,p@`Ʋ\p@p@yKyLp@p@q@xEfjQ;fM.fM+H72&Yp@˸Ůp@qBлsCp@J֐UtX1SrO_fM+$\ h;}P{Op@p@ìpAp@p@tHgfQ1fM+_H( 9,fo?TîTp@p@p@p@p@p@p@o?vZ3fp[fM+eL*)i8*ce:p@p@p@p@p@p@p@p@l>vY2fM+fM+]F'(f 1#>#>#>#>#>#>!> > > >3AntiMicroX-antimicrox-2888bf6/src/images/24x24/io.github.antimicrox.antimicrox.png000066400000000000000000000020361377703515000300310ustar00rootroot00000000000000PNG  IHDRw=sBIT|dIDATHT]OU~Μ- ||u IkQbbz1.4.ze&Djbi l;|/`7P:=>{Λ<> E'eᒊ3ۆid7n2kt3p!V<24$cЕD|~͕y7xp ߍ긹xM>+xѥMA- \w Yu9+ioqGM'8t ~[i('"Nv!3Ԝׁ7e8%.i8*] cYHe(*rB?UlY. Z!ziZN3X m࿽WpC8P0ⲠpؖSn_!VN ?b07/0,RN`ke 4 c~5) G(u|<#^M~{KХ)fW_jyL}Z[~L;Mύ 1Ƭ5`Y$ӻ 0Bڟު^,lfn~;rliiaԔ/JyB8Ik2B.kܾ# ~aIENDB`AntiMicroX-antimicrox-2888bf6/src/images/32x32/000077500000000000000000000000001377703515000211005ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/images/32x32/antimicrox.ico000066400000000000000000000102761377703515000237570ustar00rootroot00000000000000  ( @ eM,k={^6)K MWB$cK)H6 mS0p@p@p@l= /1bJ)fM+fM+fM+M: * Lp@p@p@p@p@y\5  tY2fM+fM+fM+fM+fM+ O`I)p@p@p@p@p@p@UA%UA%p@sW1fM+fM+fM+fM+E4b8p@p@p@p@p@p@o?,!O,!Oo?p@}_5fM+fM+fM+fM+[E&n>p@p@p@p@p@p@p@f:  f:p@p@b7fM+fM+fM+fM+fM+i          ">vY3ϓp@p@p@a7fM+fM+fM+fM+aI)sW2ʓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@x[3fM+fM+fM+fM+Q="H7p@p@p@p@p@p@p@p@p@nIc`eoBp@p@oBf~`cnJp@p@p@o?kQ-fM+fM+fM+fM+3' &o?p@p@p@p@p@p@p@oE[ɭ`p@p@`~ɭ[oEp@p@g;fM+fM+fM+fM+fM+ (rW2ɓp@p@p@p@p@p@p@gvhlRmQigwp@p@x[3fM+fM+fM+fM+Q=">/np@p@p@p@p@p@p@etk\k[wep@o?iO,fM+fM+fM+fM+,!q m>p@p@p@p@p@p@lScȫ[oBoA[϶blTp@e9fM+fM+fM+fM+dK* gO-p@p@p@p@p@p@p@hl[^\lXp@p@lW\^[hmp@p@uX2fM+fM+fM+fM+J73'\p@p@p@p@lϹDZp@p@o@p@p@p@p@p@p@o@p@p@MghP,fM+fM+fM+fM+%_ jfpfM+fM+fM+#Z@1sn>p@p@p@p@p@p@p@p@p@p@p@p@p@l=mS.fM+fM+fM+dK*/#w 3^H)d9n?n?n?n?n?n?n?n?o?j<}^5hO,fM+fM+]F'C3 6??AntiMicroX-antimicrox-2888bf6/src/images/32x32/io.github.antimicrox.antimicrox.png000066400000000000000000000025471377703515000300360ustar00rootroot00000000000000PNG  IHDR szzsBIT|dIDATXUKlTUιywii 4--BbcZ5&b1ƕuv7.lcЅ PB_v>yu܇i"F7vX a.t56z7Z %%A H*@Dhs\vxJf{IC%P$1STUwP;9J-g Pʀ7 >a BеKB7!]P<Ԭ)AUYQI&mL]X{;ٛ<87<![0=%u˷qt6UAHHpO Ըz/w:^<AdE-c€yd >2-2 :@4c"Rfzx;ŰǏ㾹mR: oFL1XMlJ=Ǜ}sL,Ccu9>Wv !!1%缎GꄒR3uEN/P唐8L"0>A0D QDHAhLf0,g[ꕜjb_qB7&5T1,Tm>6)kx+Rd|gէp֬褻}ݙ8ٙ_i!q_zi A ۡnw%+qp4t[ٶgXlN'" {i7o4;QS)*rh _:8s&"KG5M@UrT2ao t>,#}s '9|<8yNűiOеNSY ]Ddb_ 9\x| 6Pd)7ͪJ<UI%/]Udq~=vcm Gu[Y2<= UIƲe~xiIENDB`AntiMicroX-antimicrox-2888bf6/src/images/48-apps-antimicrox_trayicon.png000066400000000000000000000100371377703515000263050ustar00rootroot00000000000000PNG  IHDR00WmzTXtRaw profile type exifxu 0DC7p|ii%q:Z:UIfH44xKx`0 $uޘ^s'6|VIޛ- V iTXtXML:com.adobe.xmp BsBIT|dOIDAThՙmUw\5C_720+í 4IJPA?i`If, I[DnV.Kwmumgwv90sys9) E9'V #8Ng8˝e$-X W'Uj֑'t`fC# /wD\W A碖<~.ME%H5cɯix\k%?H+#v%$GCr ǁO5lݻ@ߘu9zF6Pg'A[w[M ì+:Ċ8Sb`%P0ğbh R]S."z,)@)$ Lw.ZScs=ƣ>85!pRp9m40#} L :ۀIƘ0 V`G OvÀ>1:\$8]\ͭEE`uo ZDUh{ &Z8Ͱf0Ƞ|xJ ~9I"LȌ$H~CmpCh*Эa-x,Pz/4`r3?@]֩;"/Mpэ~ NkG pk9v"˱',߱WsqujKCLv01>#SЙ4'CR`t Vğ9å42ߠ5 O*m.T[$qǀ+Xe դ[L fңD/+CM~ s ;G%Ƚ*Ql_I~qW,/Ր)#"m2ιhs1sE[{)ȫbeoHXY6,foέД(늘 <\6{4Ie]HPg_G'[I=A\;CVt Qʛ76hN,fM+fM+fM+fM+fM+fM+cJ) =.np@p@p@p@p@p@p@p@p@m> : 9m>p@vY2fM+fM+fM+fM+fM+fM+fM+,"rdM,p@p@p@p@p@p@p@p@p@p@~`7~_7ݓp@p@c8fM+fM+fM+fM+fM+fM+fM+H7a7p@p@p@p@p@p@p@p@p@p@p@\F([E(p@p@p@ip@p@p@p@p@p@p@p@p@p@p@o?3'^2&\o?p@p@p@m>fM+fM+fM+fM+fM+fM+fM+dK*l>p@p@p@p@p@p@p@p@p@p@p@p@i< * (h;p@p@p@p@m>fM+fM+fM+fM+fM+fM+fM+fM+c8p@p@p@p@p@p@p@p@p@p@p@p@p@f:?0r 3 , , , , , , , , , , , , , , 3>/qe:p@p@p@p@p@jp@p@p@p@p@p@p@p@p@p@p@aj}]p@p@]j`p@p@p@n?hO,fM+fM+fM+fM+fM+fM+dK* iP-p@p@p@p@p@p@p@p@p@p@p@_x[p@p@\v_p@p@p@d9fM+fM+fM+fM+fM+fM+fM+L: 5(`p@p@p@p@p@p@p@p@p@p@p@d\i`p@p@`i]cp@p@p@tX1fM+fM+fM+fM+fM+fM+fM+(gk=p@p@p@p@p@p@p@p@p@p@mMXxWk_p@p@k\WuXmNp@p@m>gN+fM+fM+fM+fM+fM+fM+bJ)^H)p@p@p@p@p@p@p@p@p@p@p@jcYWdYXgvp@p@p@p@gtXYdWYjep@p@p@b7fM+fM+fM+fM+fM+fM+fM+D4* Mp@p@p@p@p@p@p@UttUp@nGfxcemNp@p@p@p@p@p@mMf~cfynHp@p@p@p@qU0fM+fM+fM+fM+fM+fM+fM+  Se:p@p@p@p@p@p@ĭĭp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@wDzwhR-fM+fM+fM+fM+fM+fM+_G'T@$p@p@p@p@p@p@ȵĭp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@IkZ2fM+fM+fM+fM+fM+fM+>.;p@p@p@|Pưɳ̶Ѿм|Op@p@p@p@rBklsCp@p@p@p@p@tCIp@Pwr?gM/rPaiM7fM+fM+fM+fM+ B}`6ޓp@p@a_p@p@p@p@ͺιp@p@p@p@p@XaNip@p@p@įįp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@n?mS/fffM+fM+fM+fM+cK) 8;-lo?p@p@qAwIvIqAp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?vY2fM+fM+fM+fM+fM+fM+eL*-!s9+gl=p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@n?vY2fM+fM+fM+fM+fM+fM+cJ)+ n *bJ*m>p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@o?c8lQ-fM+fM+fM+fM+fM+dK*G6 . -"R@1tG5|G5|G5|G5|G5|G5|G5|G5|G5|G5|G5|G5|F5}@1~6)~2&~2&~2&~2&~2&~/$y!V ????AntiMicroX-antimicrox-2888bf6/src/images/48x48/io.github.antimicrox.antimicrox.png000066400000000000000000000044211377703515000300450ustar00rootroot00000000000000PNG  IHDR00WsBIT|dIDAThX[lT]?0]RA!! QJ4m($~$ԏFh~UU4QTQ"`BHlf0=w~ 6cc~yI#ͽ{}:wf1YbRhwVj}yf/-#ЈAMNM]$oS L78˂KZVѴ|+ b N" ZR3;54U),kyy?h!gK0JCM-4p_Go^dqɌ‡ Bఉy&e3&?KryaL-[h8j/Yr΃˶>{1hw <:C/&'M,m.WELfn[GvIo^ڹ /zUEp/^rPt[~rIC_'Qf4V`IC ^0)DG0P, R!xyWܪ rYAZ 18q17379)ቭ-j=p*˰41N%1h1M8D6$2ʸx!ӆ|8%>ރ_JspXAcD݂=.NaB$'n")kHf APTg.b8 Q sSOlˌwNn-yk`s,AGx:@LRxZ. ֱv,W Bΐ/$W%D*z;p{,s`sWfF/6nX= ҋ=PSE3p-.\UXY0KY>CMW~f LCIK+wZ 5Pu"̡g2&RYSӸpBe\bڿ;22T@$yc2PL`f9Ce8FnEyl/H6;8Öz|R"O=7i (|ؕ#8_o$(.;PL1Yơ['CZ ]SxhZd1^R*An óWBbX8y;lH߉~j%7l./wrEdw1^L]y5Pv^;+`xg60BD 9s p]`d#ZlA^qNHr Pu9 #5`` c 2P zu&5|uc\ڲZK s US(yS)죾` j@ 'Լp};˪׊<]I8\r7&K;FO]G^ E`|(0 6x6h߄x_mӓ݅lAοR ~X11xK&0HX,/AHius*N;>rPSևlXM, .[oݼZܯ 8&'ãi p@p@p@p@p@d9 /4]F'fM+fM+fM+fM+fM+cK)'f 8m>p@p@p@p@p@p@p@a7[D&fM+fM+fM+fM+fM+fM+fM+dK* =vZ3ғp@p@p@p@p@p@p@p@p@_I)G6fM+fM+fM+fM+fM+fM+fM+fM+fM+T@#3'_p@p@p@p@p@p@p@p@p@p@p@6)d5(cb7fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+'euY3ѓp@p@p@p@p@p@p@p@p@p@p@i< '&ifM+fM+fM+fM+fM+fM+fM+fM+fM+fM+I6|^6ݓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@c9  c9p@p@p@p@p@jP-fM+fM+fM+fM+fM+fM+fM+fM+fM+YC%ifM+fM+fM+fM+fM+fM+fM+fM+fM+fM+H6B2yp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@f:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%~ -p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@lVhlifnHp@p@p@p@p@p@p@p@p@p@nGiehllWo@p@p@p@p@p@p@p@p@p@p@y[3fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+3w[4ԓp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ig[WWWWanHp@p@p@p@p@p@nHaWWWW[ihp@p@p@p@p@p@p@p@o?jP,fM+fM+fM+fM+fM+fM+fM+fM+fM+UA$B2yp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@gwWWn^W[nJp@p@p@p@nI[W^oWWfyp@p@p@p@p@p@p@f:fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+1%~ n?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@lTWYŧzW_p@p@p@p@`WxƩYWlVp@p@p@p@p@p@vY2fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ $kR/p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@aWcWmRp@p@mPWbWap@p@p@p@p@n?hN+fM+fM+fM+fM+fM+fM+fM+fM+fM+N;!8*fp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@[WWfxp@p@gvWW[p@p@p@p@p@c8fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+*ll=p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@ZWWep@p@eW£YYp@p@p@p@p@sW1fM+fM+fM+fM+fM+fM+fM+fM+fM+cK)aJ*p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@\WWhqp@p@hnWW\p@p@p@p@m>fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+G5-"Tp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@dW[XnHp@p@nGX[Wdp@p@p@p@a7fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+#Zh;p@p@p@p@p@p@p@p@p@p@p@p@p@p@nGZWͲeWdp@p@p@p@dWfӽWYnHp@p@p@p@oT/fM+fM+fM+fM+fM+fM+fM+fM+fM+`H( WB&p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@kZYWXiaWW`oAp@p@p@p@o@aWWaiXWYk\p@p@p@p@k=fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+@0#Bp@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@nKbZWW]hqp@p@p@p@p@p@p@p@ho]WWZbnLp@p@p@p@p@|^5fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+ Ga7p@p@p@p@p@p@p@p@p@ǯǯƮcp@p@p@p@oBo@p@p@p@p@p@p@p@p@p@p@p@p@o@oBp@p@p@p@p@sBSzElR.fM+fM+fM+fM+fM+fM+fM+fM+fM+\E&L:!p@p@p@p@p@p@p@p@p@ê~p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@r~iT/fM+fM+fM+fM+fM+fM+fM+fM+fM+8* 0p@p@p@p@p@p@p@p@p@͸~p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@od7fM+fM+fM+fM+fM+fM+fM+fM+fM+5vZ3ӓp@p@p@p@qAmrrɴnn\p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@XxZfM+fM+fM+fM+fM+fM+fM+fM+fM+UA$B2xp@p@p@p@iѼp@p@p@p@p@p@p@vêīzp@p@p@p@p@p@p@rAԏUܓWwDp@f:fM+gM2STlNEfM+fM+fM+fM+fM+1%~ n?p@p@p@mԿp@p@p@p@p@p@vxp@p@p@p@p@p@MaaҏTp@vY2fM+vQqWWSfM+fM+fM+fM+fM+ #kR/p@p@p@mԿp@p@p@p@p@p@DZp@p@p@p@p@p@|H`a‡On?hN+fM+pOVVWzQfM+fM+fM+fM+N;!8*fp@p@p@XѼѽp@p@p@p@p@p@Ůҿp@p@p@p@p@p@p@zF}Hp@g=fs_fW9fM+nNMqO[fM+fM+fM+fM+fM+*lj=p@p@p@p@p@p@͹p@p@p@p@p@p@p@p@p@mnp@p@p@p@p@p@p@p@p@p@qfffS3fM+fM+fM+fM+fM+fM+bJ)S?$p@p@p@p@p@p@͸p@p@p@p@p@p@p@p@p@p@k«mp@p@p@p@p@p@p@p@p@p@i/so?p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@p@d9fM+fM+fM+fM+fM+fM+fM+fM+fM+fM+.#y1&\in>n>n>n>n>n>n>n>n>n>n>n>n>n>m>l>h;`6pU0fM+fM+fM+fM+fM+fM+eL+\F'L9 3& )?????AntiMicroX-antimicrox-2888bf6/src/images/64x64/io.github.antimicrox.antimicrox.png000066400000000000000000000057331377703515000300500ustar00rootroot00000000000000PNG  IHDR@@iqsBIT|d IDATxylǿ9vfO'> %\䤀DHiԴJjT*E%JTh6$ )`cm1zcfvf~ci"u?̼~}~yɓ'O8gk^x4X^'!k#,k6) x&`S4QtНw'QX]<l S:tc?XQ5Y!ZDQ4e\ўv˛lǦKJ@UR9UI%][-#T Ӛ20Sʧt xO#`f,@l0$j4l) .=lsz",'㥉+ԦqMS XƄZle 4|` h-šMdW?r& DIbZUC "PlRvRo‹` #* ĠSi&*:*`w,}fx̝_.\1%A QYMN8,72e"s "Qɥn= d3{H `n;l(wrzb{SP`Niә%8i&`#2~"oO@)p@阾C |bn*fwL ZbC ֏íǂ} 3M@LQzB:`?s) "d @J4EzаMVGlZF Lq WH?8n!x fESfՒq,6,dj^ gB,hJo_kRXrW.qJURP#i AX qK %BcCVW\1sg#{*2CН|$X`/[)+pŰ.*k\#ϼxPI D:x;eX AL"vg#'XEMwxwB؛Ih癿6?,'d7N.bX^hh.|v[t|7=bV!/h-.Iuj=w?׎Q_7^FwkDBqFyxv>6rȁgw(5];*EL7z9W'*G>r=TדV=@;\?=?_=G|L!9x{?ep^Ew!;uڹc%2?Dí9-UYt~k'uco!Tהکʱ0:$c!H!of@˱Mi+x?LT96.ŏ(M0ye)8~wy`-(Uك}'b>/8ZslR{y틽Zב{u-{<ݟÅqyHکq{)*0ň cEŧ mr߷/Tע۶3-kC#'_$w_\|Nšbkrd>rl(0нFLr79Ը _pGoM'O$3=uOݺB!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!b&; ?%g[Rs`,%T_ QE>-ˎ8OpAB&gBp&g\n+A3 0V:йEQ*1_>.?u^=76kE%5W h@'C/( EeiLQc(Rf|k_Lz|؈{PvZ[xIchG߹DƘ";2r FJJ! \TC`ZRf|ā?>fE @m/k@4+;&BΆ:*J ʹ47draGǞƏoq%M Z1xs\혽 TJs20Rf;_˩#oLv<^4(_0j_pέ~8x^*@1;ai S&GɎXhP:+5gLQ41!*4 )Tri!d#o}ضgL/eDA @c=+.̬U}ʎٸCar X1EC/>rOn˲!PaDY.\ϲ P4_Hv<aThe0G>ۓvDv8>xPw՗~uޒkF!!g%PfPALCa LJ|WdBjCDZo/Z-Vv,xUEv -`))G^XPXo+Խl=)x:Dn8?| |Jv4(p1-N^s]7!F  Y1k~KQJ,y?|pJv44:ȎE);%;Ed*9>Luezrec!ٔrdG١4S^xS>,;kcJϲ Q}piVsLJPJca >Û87hO P͖dBrȌS5sG`,9[v,(,J!G$>zYv8$fͿh-} 'eBF(2XImύ{Iv8t=͟yPS=B c 8* Ak#XZ'oM#BU+n@(!;B BLu`97[ɑiX$ֳ|խ{ʎ"S"-(;:BX׼k؛iX h_}? !D>G(hw`/2eu.#-ݲc!S>J58\!;E^^ٱBG5JY6p-jPJv,^F @ot=_v$򇢈nD^vNj2J4gй;eAqPZl578Nաm`M /1#H ^˲Ci(Z 2CVH[sogU %n#,?npLd84<΅'ī870yx %VbL_}C~";/ /Dzˎ^v}9]OGs7oBJTE-x{Ra\v,^Aj0}uū_d,~=WvT;@IcBhɾWkc Jf(5g 6o>ێOx[`̓?7!nFP.dP@Oʎ h BEW^ঋVIO|DCi'U샢%Zm0K-X ^~7.q+ `~*~M}R -͏Hk2#>F"\ X3tT 080nKrM>_ gA Yt/7ȎÌd &/:R-C U-I S5uM"V/n*}OzH7ɲt9oxˎh |p Cvf4wyvl9$b`l]kOw] OͫL1ywӣ3 7?/!NC8~֯O> |&Wh\]G$^pefFouȎBv>w>\kcGm2wP}e+>";`:) .߳Z!N1gw!p˅֝ T4е|:CFwS?B|({<~eȪ 7:ylW~]vnD )@8.;BH󉦺SnIv׬n@OvnC )_(z9b1G褶\g\ ;n(^/pڗu-ZudA~ z;ItbR'8>#x&2yɑ7p V wDі9lX܂ Z !f1,׃ rA/|gxBGCX׉ WVN=:;"S(:zS4  ScX5`X5 x5{Bp6{_*;mZ =ˎ3V/k/ìvslO{p˰(Dd qt$oic)Xj3x[9~K ^]7l4=,򣷣s5f ˎKNOQ5b)bՁsoʎ-(-lMqRu^ٝ;xRٹ whp9&\8ZZ/ݲpJi'^/[MS};B5wj,m?hm}<: pdecEa yi^DȘz R e[jl?WQu@J=xY(N0yZ]2בi{I /FG";C0 ?2 yȾ熯k/ȎCOz_I1R+.}g3-6CMY 2[ڷ-+V6NXgeAH-f WS7Zةw_帥 Gm9'0E %ڗɎCN)Ov̔*}.]Ip34mGxv[;',?wY60dj!Enu~f/\ujb}GF;}7x^L]EiڂxM$o %ˎ.y>\vs ~QW3?Ι?a_ʺcy0 _Ku.Z{2_䀹]th,D$hTL3\)nءt K`m{[`"k]\^Ӳc)>lq,#XZUuZomGـgETɖ3D?>>ÓfCt+0f0,yؾ5`,p_ |*M@`+r?=|IغЋT_`Ra\v,Nkuo7^ gwB9J~Y?/} g}Q 3Ջ)j"ʏ{nlZ,}s^}kc9ZȎiMt.ZsU qkbwÒyw]sY,i#A%%P.TO_O2 t8EiПx;1h5Z L]r8WoP Or0,58Kڹ~1xƈ?Dqxum#4ׄ`,ta.XxUBqiO1]v` ׫Prq`>{ir ePvNkGΓ>ߙK7W.ľ#1- #ʅ@b:\qL#ҋPlT_? zzq ACbqrJ`E#4paQF9Tj1rhGcpZS%Xrvg`8driF Ҥ&vlKy"<7$W#ZN';W Hߊm%p ;%*-MmZAyyxg5"ۘ>Kٱ8t,Zs'Â暍OV["$bp|'}oX%!ںIT-ѻv`GIɗ:naZ^up%$; '5r:wO3fg&Ș9w=Xd5_ Euc?ba`_ \P 6G(޶Iv Nj >ke)Wn)U MԊ54Z65x S6bDUPCP4{Bk60ԿXY!_Ql87ً/;4MԪX.;z> LfKQ4N 鴴/Em5c@jz>h=ReEs(;4G1 Vt!!L*up0f)ZYk,=&S|h$~nSwR)7T iern8)dMhbbTPszg̰mܾ (֏h7B-3mqB~,ŏ5oP q8)'7X`zm{[raLEվ.-mkz W8H_yItlHWWRX`ɝ?12՘f[Oִi9J=6~Jl- %:!PvvkMH>{X~L!LLqgnhlʲcM(c!y ԁz0D@qحZ}QK+tpxGF,z.G+ϮsN!I* M!t#ra*WD"r J|\T1)T0.bx2Ll“i۱@8P_,Xp*x?Zda'bqC?R1.6 Ŋapv7eW+fMu< _@~:Nqx'6tpK?Rss%0|ߩȋp! `dQ 9ljf*@; "kqag9K:eWWӸm W4Ooa8pLv+LzvJ)J;jb\*~MfxJdCCWɎ ;@R?gT "r_?vԈv?moNR9ZWJi ??Zl_42x2ct Ȑ/bhL~]9 crU[ˍ o`|Uir&*VF 51;6dIl' 0-j|Gc|*#_b!7Jˏ C/8CxWr|L^Jx @ht{1{醁/!hܪ%Э̊!L m1}:Q P%cپrvb !R{7~|u,`2cn* = !7O`^<1M t9XhJFp usFE7K;=|m\ _+޽[9c;R׾w7lrݬx@pϋbq/Y8 K#vTe`%E]~?*/(;3jc90%Sp/t㙭{dtg^1 bM~:x _wtԒc6 C#?T_P lcQW0viū>? ,a@ AW+r(,EpEne&YC%m+nZò8PЏ+)l<&Yc0wpxO&&3ytZ蒡\]Ɩ]l-!eW܏~0&jqq9?vaرg) bnM^+FOS0@Bcx QHCؖ3-=a١XCZv'~6&q*ފHлkJ/g^kQUzb]8BA?Eyw`.P,W0cס!<ƾ[o hT0*94Jޑ dѩ|h`(`:g`ǶvPTR?xUCiX7haplu[vJs@8JQ^@$,; aSs㼂o`,-;+4"|Kz~;kҩ200Ϟ!T;dx@03[9nٴ4r it]ǿ8n_VB܂) ɹZ|T !Pdc3oa|_ H !!c' aE/:Q-^0;S C:dS^u[v츄d1|ϏC#} مCo 5W~8܈17\,vXO}blR^ZBkY.؎MXbC{=y|*wzBϽWvlB00yhG*_eCtͥ 3i IDATQ:z>gW.u $~8 fbV)XEӺPt|@!sI-9c ?9䜨%kV! u#48ϰڈ;Sڻq>4]b:^sD iTW_đeG!=҉nٱP?k|Q=#܄c$&;#ocag C<Ɍ?Ɓ㎞23hRv )wՏ~uXrRhN7.X-(ruOmyf q-$ E 93Jpu]>XN @5wy

(;Xu`,it@t vHL C*0TaLc+}@Wz=Mg0C1 wTpV xŲc8&X!e,+ ,*3:!0ElgPI̮,- ,* :؊:jxr aga['* 0*TJ':qX{ o՗~%qV+]' aԺ%yE`cxgtL 32Đi!'FdpR7㘎;?ь)ԢG*+(y+^Qf갼$peV`l7V4"\]h8oa Mr+7xɬU}Vvzu>4%0Gwχ:Ɂ ?c9vXXU9g(Ln)Wdr2%@q ½[X΢.,TW7M9M Wg1`CA0h!/CApYN࿌jG>ܜGCwV SJsS$~s)>n%dА=k:D8qL, Ɉe%5]QK?nބlHjhh)Xj8NiגiXq8{to'p~A 6~k#I+1\Q.b]? J9܊hL)5g39' n;=:CI9٢5tq|lCqZW8Js\p'86fHuC8Np#u#',. |a#%.(|,f&|3|tc;T;U;ʎפxiʘ&VD4Wt+egCl }-riNຬiM!Z}OV"`8I`[;iu:"vCH.[A kwAiHQ@=Úة<)$=ǀ=ǁ{ 4Nv~Am@u/z[d`ǀ]C`Fþ$O nU# =C=6~`eO7uK8<Gaӭ?cN5g!q󻡾vJўm M*x%__qUs C,T3%eC0 !ۓd?mS0WGgS:ϽMvDS neQ뎫0{[1y @/wBYw8S0-eQ.Ia/ZBQ*9sFi4s}y/X.>=a/TxasK0P\EQ;JC,'pyBa,sawQ18:G;(Gǡ+W2LA<`>3!0bp]!:͞KWQVJȝ7G,VtP@{T;ge!=mnEӓns?X|FTy^1Tȝ;?: k$B_DvUN` `A7ػ(P֡@Ph*J:PX m, mºٝ !xۼݯ~Ef R+/62c (>2eT1E?Uu14|D+Vbc'"뒜@ٽ ঌC~\ ~F g IF׭Ьd2|G pjƢ@(%33] /ظPZ*e}FK <V\AS9q%0ÚPT?t;.:ł!xB:ZP7-U篂Xmk`e?90vFΝgfW`E+ r iLn?ܝ=eMǼ+}sA!C:5gi+:u De 0L\u -9>fQ?q\O]f [ O#/FقLnϸ?@ yE3!P;1xmdnTĘr 6:m bk>g \f 6RlK{:5AFhLk;cEvGt-DzN/-u]ւU@i !k\?uJ{LҼ@*r2# P1> r5 ƨ7b;Jm {/qn"W0w$JSBay-*1SqK\`]A v4̀_-<#֛W:ڀsu̾Hƹ$ջ׌̙'.YϚL'0~:Ӄ91㪬dh#Dܙm~gRYNbL:Bk*RלT+;I_ʚL*9`@3fs\`E+1Pzts-Ygtki*U%ۤtt<k -K}N|0 s|TL^X'1G9-A𫼟0y9fuT-;P}nfKow_I;&! @7weW$gK&Es'75ߕ"Vz*ɭLΐ9أc9wu6M+̫3uS+WZIŒ5%JsP2QN%+q\1E9tݚ,*a"P yeNUI^۰|9:;${nDNâf&Ι \9oRŀaQH_HXu~ ׬d6mY~场_<'8LMS\rUaD(ԿVeQYm2!Nwtsֿ-#MfFcNhl~i.fgXja_cn*ջO_QBp} EEepkن/9u>oZs͂0q1R.v<@iv{ݯ[q.c\#XIϬlRs)*,65Y@V=q$éԜW:q.>f֘z'Sy{oˊsO칑\ , Yd§4nN DZC .::/<yu -~Bydf;`sc3pI0+U:I?@"н?qL\3hs3u7cAu*l[Jwu%-y'6bWPe!=Owr!Yt=Lv?.&%~@h xKe;ueiɏs:G ;D݊6;hEmQ?6ЊuʽØʕLEA#@!7΢#njY\Lf|iHݽ7@mL@D,he85I(5bWXs'&pf 㙢ɜPxOAlpC u#~aCפM*>?t`p {6"&2ETx*n/@ 3vqC u#!3M\<ȗtr a2OLʶo8M$= ]C} @˘y/?[TIR.PX̜SQOLQQ ;!жXo%hb]'P4B-IH?(M[t`-bTvw:\ 8b1Q@{T;Cm @"'@@Wҝ}.3E)Of 91ɡbpIGLl{tډܐX>UǴ4\.GN5*V&ẂջAs \c{v5g|G_f%_Fyp! no^zזL, Sπt-]+: @jG31_߅];IgkCg[C02$O好Z{ceG~ns9&(A0vdzl۝ZuİLl8!XDz__}Ĭ}67xi'da}A l폒/!wm<ڿeSBav 7<#(m-8y#hfb_I(^^*Ȏ֝,c#ڂ538;@̣ t!Ȗ}h9hcU.|5{jReh *Lh2"4Y)iY/!WX-JC4)EQQLhhΗz^[W;wWރHȐ@}'ٲ"ܕtt@![`uT); +J@L秓0.{GPiHD9Lgkn^ 2dC); h3PJqWard[/+[}ZBN# ,.0@p¯C3]p}CguiN΀Tp\sj;ƂF> IDAT/'GS1* #h.o5QK)%h  x\86w_uSgRѨEwK_9nk (BoFd~7yoLC.(SOMf[[1aĬi8zAM-9ty0jeT?0?zsT5_U/[ygu`Y >DJs;Pێro+xbؕ|8m{>o' ߎ{H̍Y26G* v8  @wlPb5=om۟Z^S'qw}ku'5m*gJUc!"uX6R0WV[ T`oa6x=Z( lxR߉+ɖ؍051a4a軷j Xc:Grz) CI+[~k o@M3):7+>2&;nvVTkjZ>-U{hCNaXZf{3]RAɂn%Э=㈟GV S<3j O E|cKjTR?_D!~ۛնWʚn3kIkkQpKuGgI^ 2|94G4τ>܀/oq[𛛆o$`Li?BfଧËEOw&HKaB!Un(W}|6hB! D1Z.g?&`}`vD!nBCc+$֮%X!_(Z#4vnZ|5{DK B9/DCjç{d΄C!?BC :/8ޝ0g \XDBISYPw=_yWk] Eۜ BR4Tߴ։ s|w%Bl9<ߝB!a!4P}RX=!'iJl3d-2LBR}>0EF`-YN;WNHB@Hv e' @{9r!Bލ#Z;JfYre`J$<<'~|r,Ǧ8 Cc 1B $8XV-YWYZlߝ-Svܹ!ˑU̝F3w~s;7 =V;s>5qxJ whsu!5&6 Bh%O$Hk-zo3^Ϸ@фgZ%iosy8U+j,O!*zּ& +Yľܱ<(}zEeMŴYjf{Ug<nV;78W^p8ƒɑɑT(И 5ؠQ eLO]\w3c>]C\W\+@ 9jl|9 \DJHh qsow{-wlw/lpBMtQ(F"?'M2Qyɪy{?D̹73HPW%G4ѴJzgzUByK ?i?A::o\x}v;?řNypwpF~*JT|oW磔I65A߉񮿸?޴鳮Ui !%vxf_wzUAym㖭`wBJ2hlVTTZtoi}wYF*.T8[QY3QPF"o~=UgTrx灗 z?ؗ橨|_eEzeyWȏpwӖ}|g%߿%YT$yU()7ÙMf6Q(&5o|]pytO%S1m^Y3} (uRޣ;/7r=vdBt#ܠWNWVS=R:wOTu`*8s?W 6N QЄ묱@8m~,#S(i$>mҪH!4]%cOBgTJI:2yT@)ȗPgRu >#'׫΁R ]cH|^K9R۵毳h$;R &bҤwL2: P,#n_񨔎:K0RMcX19]?}Uh~Q0Fwtf)#7s夻~C=GT( 7hi$UdTkݯ9S('ұֺ윑Pu|CQ`b|:L,ٱÓs͑3ݡtzq} kTpPˢ ye$GvWsmf^9"p9z0.RJuGl:: !,#3ںm#4P%RN:Aq;ۣs΃}Gw|Gu78Cnt":pﱞ#۾:{&>V9f.р (~i$[/mbqˬ\6:K>9 "M\*Fj۽3ёv9\^6n+396#n0SnH6=j{y9\]ĺRy,:`$>pEx}Ϻϩ`JΡpE:<Xp):R#IDftIw,3kfRaqP|z8(jf;iu!&}:]9L\ tPcwMF!t!HG[fA1̨wGKug1\Hحu˗M՝;m781$@*<ج6I-|v˪PrO7{ZA(ŀr3UO(\ \QOG>96 JR|woX˱̌HPI:Z|C6sֺ_/sl{J ۶6.t]$CBQ)tdث4P9'7sۿ4XB+*oװsp__îDm{T` < 1{LMdoǪO )9t(R:+53ɐ(WbJ!9~@l됚8Pɷk_P^hWٔ%)ҹoP6HPai?^uQ t}I9m[0= ǶֳK ;ۿ+]lF`+z@uD%Rh< 9L=~:s78#,@ib%~_t46yPpS.lΒ?%osկ\*.64kZH|ro .0IN`23ɑ++q۷(K`˽vzǶ w"M=a9'ɋywc7![2t盦ib7/e HG 8$Au+=VF*.p!P!D{+bTf!-mn[317-{~ߊ+~ ݴ̦ttdث:ғ8Snױ-@=rt ǶsƗ nu4|YP6$K"jݶ|NS< &_.;b1uB@たcѾg`W&ط }Ęwn#ᮦK|i?aj9|{|xޓG9p6ǟ c.K)#=,PLl<3B)W*F:/EJxwed7@ѰLuG2Ll$c6oGGNb<&Fb~tPˑsDԯi>~J%¡?B _I/8{"b]zn'9rz=3߱rIaBF* E}w =3ab^sfKJu%ÅNTF| ߜ&TDW_`߷녿T\ٴH%M }bB&Tx@%l7' QwW&l߷sx]D&BlbTX:R5=2oBLB};f;g$TgsFsi[f:Ti޿L ^x>3>kE7k2b=oz0R<ӪUئqaa>ߤz~8)0b0Y^G˞Cl;.l:{d۷&βXw8VM:GI:)4Mu)G=NMkl$C6LjYB9:ޣs"ͫXhSMqft%mB`ۉu#6R#9P:ǚ&FT2?n6BY\:OWaf!UR:@HtBuu0]e+6gn_*Z-81w\u(4+zUɚ9~OubIiկ?Wz"kxaԋn?,yzCr9]VB۹L,=H6>:ֶ{atطWf㖑mCefݼTbfӑ~ܱ̼lSm׷~ϣi"xQ#q68_.LGm~߃J6^yO#'UgbKz5MDk,,i">wNB HDZp q$o uި: ThH휅7L>~YT2=[.Ľ Rq[fi>p*xe֢﫨`m|P+X Ѿݕյf]{{ y_:_aTb󮝽߮UuB ,= Z!DαwI{?8Ug"Ӳjשּׁq,`e};w[@!b]LrdMw|X4WW"XfníG]JYP5c̚GuhBÃ;NWBp߱}㮏z*f#D]Tae3YKnS!'~K'X)_W=kMw|ѕ[~Y!yzoOTXu(ճ߾w< \:K>h>}BJOUpedbíGWH2f/Y3Mm:Klcď/X|kՌ95 4MhwTܯ<站?:x]D6UJy{?N=2z$ت:9EUi o[oYx4W <>NY,~`=_ulFu+=ho%Y.TY|H;{A߉bET7ϹO[!{*r5}v|̴ֱS;o;g,|@Jgŀ&4]gc׃GeJ竬pw~d-wE7zּ&ߪxw߶7jϷ22ɷ (nXwݬE7S9fDZL=m[`߫?mhЦlp/y`=3SQU;5sm\6aFʦv.]`K*<ؔ 9#ȿg/Y @w{.5Zz&DBHiBBY84x18j$/P?JU?iTXtRaw profile type iptc IPTC profile 52 3249636f6e206d616465206279204672656570696b20706572666563742066726f6d2077 77772e666c617469636f6e2e636f6d00  iTXtXML:com.adobe.xmp Icon made by Freepik perfect from www.flaticon.com 0<5IENDB`AntiMicroX-antimicrox-2888bf6/src/images/axis.png000066400000000000000000000037041377703515000217750ustar00rootroot00000000000000PNG  IHDRVgsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<AIDATHŖyVWm301 NmāƨAb1"в4t!REN֪CI5iHD)˴4Yl#;6 1}-o'9~sy>woZ!WiZ^RrRbACK9sdQ=W/lwLٚ˅^>- ˓3EGq˩?Y?<윻8UuHC` 8&x]Y%mi˵y┲K9OO//5KGyY.k?5H 1 &a;Wi $xu۴%-|9卵ECscvnٔsW4$5z(ؚnK!a!a)'|%CÅ'Mh W2-D Ͷ'1LFǓ׿@ !!( +ݓ賦!n#G`ƢDÐj`IHJbeC6Sa#m'bHxR78ai<6jJGW[7.JwP8 tg~pr)A@!p&m(4u+7F#=#F#3^IT]0+^!%B`)|!>>`9L*1x\f s$l|&@R2Lg'%QP@dAN֠@+ h#;i+Dԭ^)`[Z_y!HW=g󫧍n~ŘXq\O|@vji?yr7I]q~f4ʐ ?ך;w`ܐ PKɲ =P~>7>aCD| xJZ|/uk{`7_]1ٓyaΧX#`F"Lܴ1zA)j JkbͯpUsW[ٙ74\0a&nڎpU=bB1l|v=uyz #{G퉙NZIyGRVkbsɸG~W9=(U6xʧl6gm~x9{KMaKW 6KVRmV'Vp <4x 'CtZd⦒l ͞qt5|iTU׫z)|˥C!g3 πQyl{ /&SZ/\ՊlxT̳KF~~k=Йu:w0![t?Os=Ci4F~n冪{W]hn g QS7is^K$56O19A(@y=զ:2F#֦a)EkWkIlOsХ>\Is1rap@ixj/Mr3mk+k7X~Zn֐t<&CMJbAN<0<$ᬯ5DM;D{O?Lv\r=W-1;up3G(-*?j|E+9,XWܑѼpG8" SX3LIENDB`AntiMicroX-antimicrox-2888bf6/src/images/battery-low-level.png000066400000000000000000001102771377703515000244130ustar00rootroot00000000000000PNG  IHDR&#uzTXtRaw profile type exifxڭg:vcZYlv; Sk^L& ^s jTjn9[R}}Rgx,=z5uSw|}O9aЕ=u{_rPo=Lϗ6_(ą;` 0B绻ߣ^#t{~OA>-_/}=9Q.97. /Fz~LD[Q|s,~CVYIʗv5]s[9do_VCϛ/w|!+T276!mzUzWo/sToq;Gw޼כ~~(U2n+7xN1Q[9p\BΔq`hlv!l8G+  b>)z]wg&Be$+DXB)J&s1s^B%\J^C5\K| ``jV[k{ӹP\; ?ˆ#<ʨ>)gyYg}0*vf;.N8O9ӿ޶dͽY7S:|eWM)S8IRȘeʙ.F)gy"y2F v>fR]R9C~sfBw.R'^ܽK;`PXT?9gRڣgb?s=sԉ>MWc#Zn5Zi~1ɳEOh#SgIޠ2ʹCpZ޻5s#af89y `I|N$@ݲyL[+3ieJ5 >O_-ϜK; |R $8"?͞Z>Sػ_}-Ŵi!n!ؑ d6G+e"I>> T? xvϣ]ga"7`Z# t3J|L];N2r\,΄fvc|,q' 7Ѕz>\J?zg?Ŷj^IcSorJIާ(m{hvwʮ5|#+(? eW$\^UdѪ·Jeq㋻l{OOP0uB1Jatp;K0d.Q.am"(9Rakt *@V*IkZ j至PP+o뜍Kitj=yFU;Dڋ\ 2-pd;Q}уUH 68 e0 ҊP8wFl:wr me ĖY@FHxUcq5Bian[T'lÙAJ!"tvܜgqjT=}+eO*1''zfQKHD7(GNuF^uzӜz\Wnn@ 5ŸTׅCnz A8a#Go rOEIJ콺tSb\Pp\xC5i%* B2 I |Fٛj;5g{ `XQHc(6Ka5̜;mEZ?0~ӗ6yL+%w]KלP `Qp. Y£CʅY>]m!5ճ 1׏05"66ό*'?YshPw!:EAIN.f8Bl R9Y"tE7n!n!QηKK&H҈p6Ư&3ZS&Yj4FSEiJ0WVEAmX@*hS>sYfpa\dN \*sP}WMi!lbuT 3 j`x 5uG(8{BJ̦E5z798DUVJpzXكY$!W|pc74X۩;BHq=L "" F+&=mi =1j>R1[ xL"@DAچ t vI T1pdp6$^yq ֬|t1Bmҋ # dӄD!BͲu6w׍_hq#Bq ,}T%!nb|`XЫaz8seSҡr}BW#'.$B$5ӵ=>G#dԅ8p7U$@+"h@ ](6vLQ( WԽhJ5 MnCC1vGE ҫ jYF ,X4yh Hރ kVv8+`+k(G<ܟTpbJݯZd֛!U0H9 ݍD:S$[)1[:sxJ#}"N!T- d]rtLr"Ч vjުzQ[@0hq9)__'anXRS׆;S?ߓ[ N<sHzjX@&XΠA\S‹ڢ[4#etk, /!#d>9sB \$cش6d sD`4mYOc"ob%j귟oՑ$8/>l_E7Q*EY+M/)b5#prflFuSP|Xz|M{1TSWn@ңrkMc#j& @ z++G`|@tM(9H'Ut+7&R$]P*m{QWZToBJ]\wC]Q{b1v]~ |{Ӓ8&DH,+q=xZ=:" {d]g|oM}|4 q#X9>`>EWW859y}rf^BWjʑP-;A(adE^39FrMH wfP46~ @]W+wJFɂQDYAע*%bNuX:vo\%2{hx}5ӂ,OZS8+koHTlFƫ uOW~> br.N5# A q#$__OȱMҝy@rpҴַ|ڗјUi 4I< KbWQ=L )E3{UBΤJ .O-sl0-yǝaRw2#DD*x3G3ԃׇr 9CSHLSE紴QM/IT"ٕUJ{_Io0ye{E90{r;ˢH*Gz;jX15,W :>-yv?ꔏt=\tz;M^0A5Xi]Gjr AHd`- T"J-HD08i'܃4z@:CuEY|>lS24Dz/Mpb &}w{@FSSb$IӀ|1ch%h;pVP'[@]8PFp\4KNUF²bT &M"y`€ ~W&( ڑ!ıi*E~ Od?cfmD\K=1P 6 ۍOkNSë>Ƃ9q[MKsэqS Fa[<$! FU$W J=?4/Qی8xV _BɱjfR]F\7Uj@gq56$50jY;eK>*Bki4R /5"^dF\r}'c3. TTլ){@Jm?߽rwZ!N4u( 8sr4fΑ+ ý8ēdB1P& aȒ$_=(B4 u$"uH}n- _Wl\Vs  u Xm]Pȑ2X``MA|LV2((Iy55Hl[[U{sd;Z'nmwF{h)(u4*#U}Sv'؇?z(Z45DrMߣћ`0$@LP@K%XqMnTDNRY5 6[@p!"Ae4 "&jY冒 _@V`Q=w>"vmEOKZO_,1 aeiUQБuZ ӭ7ڭBKܣA2Aik+eѮv,7%l:mB\z8Yw˦\psXoCw{m 5I'jM1i#VMK 80-zm;Vi M`loGUzkZRe١w靶XC?7]$$C̿sl`'frfhqMa>pZT4n8ǃI/*λ M1sckf0UOͬvEk@JFh*#׳iݲ)l@gXQ/Wj}_ݑ-.Ni= PZCXmnPZE!mݚA;pl-;nI} = eh Nt +fbDDZ@*~~w*Q HNkS{D8D%+ ELLԷr"90.Gr.l5B; mֽܷ:dtcP^:uQݓ\Frc\SZaRT8tUpP{MAk P9i^D Ilq*X4htmt=8Ǧ23˾. !txGtmU^IgJzr=4H=h]Ȉ !, O΀q׿Dp:^ Kl N)]il,.7:j#=E8Tp5g|VX5f]#!?K]Z|dVH>~\ZOz 5Ę>m}`Gi%C`1ءN=`?`P aU^CI2?[('Jv^xrFs2̍*svjyvo~J4E)Nxy<ho]F˻Lӌf-e+})=bnL|S`j{ XN Ū'hCݹO0P[N2^Z]q3cor8<0Y#r O= E}FҿFɉ!>oۧZ\ \[~/?N+D˝\_0xwDM>Ht;UavB#e x{tQmo#JN׈=PBKAHIT+=7!LY_E=S柵^hi=8\cCzK= @gٌ9KkJv\ qz\)TZ!}qC%JXܯL Y;5 #8n6ƖdfkfY;o(Rh-SވzT+28k7 QISn@)7`g2j}$V>nH&O/5 vJzH2hvs8WX**5mUFqZ<}-O3YHFd(afn4mKaPOfv9 Ekuf * Zԓzj'Ķ{9\ko8tQ{K|16!*lQ[? RT\W$7x:],!qCl WܴGmYÊZ㖶෮G 겐:J 4RZƏks(*44 \w42;D. xFY3 nY+!GHGUBRҦ Ͷ TZlJh3C !dqէӔ=' (=ڄK"v2m,j5rXU;ۻ;5qi{q x6Fc1z7i q,.e+) .hz\$^z&МZ'72=\] ]D2v/MdE3ϛt&O@4t&v'^DLм}.d%!-B ,<=rbQ)tYuΣHxר'D%oB(;znߴs1ZkwS!羂f0}@ݲ)6rϿ).@jb;,'VS6,}h~_qAԎ䉏p\pk`OVNvU<:Mtz& . w;qcV8\==n 5㛭_YЕShakV+Q[c j/A9*܁.ܵz4P_=<iCCPICC profilex}=H@_SEVvqP,8jP :\MGbYWWAqquRtZxp܏ww^f1e11]^ы>ĀL}.Ls|׻(>*9>xEATH@tuUߏTݨT((J(" bV _}#+ m :h6h6Qc6IqZBf"Ѻ/-[[W`u;›&lۺ }}(DP̑ R/#.JEPJw JȔ++֭[1z9fkϫ o.Weͺ5x'VEsd>&oqiR o{۱f͚@՛c j8f| 18*aGsF˴3pᄹED,>V#oI_`fҝoPR`x:˃py<^b)eJ hfRoC0La4LX۶a[aYAJ@k;vS'QAӌl_v]+¿mͪ7 *u4M4M4uZM_Õ\!zP`@i9ZAq67y0BJ0-T*]TP.QtA@l}i8YV |armVΡ63 fJ JWy/y1 "arjPJB)֭;@;32KWl/Sp8J/igJJJjV|cD_W ZIs&Ru}?曇Hk˕mI I2 T3"gt#G_2>86mĿfCb" 8ۂs&&'077=ׅ\u8Oߺ = O `8%!D2 %Ȁi0 C{?ހi 0`LLVˉ&y~ ۿ~RwHVoe7,\p HѹwҕRPҏ3~Qm۰ 6 ˴`,˂7 $|gwSTm+$o\Ejjq#pgB$<^Nph`"L?"._&Oo5;vly?yo "%?neK%EE X ;v 'r)f+X'._Az3ku< hl^Vf1;;Zmf%| VDѷ0hoU~ofO|nsƘ7OKţh/: 5DoOPTP.Q*z*\\!Kq 9^"oT9!|`)x q}Cmv33pNs/$螱JXp? !?͗786l؀/+gF>'wk؎0 ׋^tw4#mx'ROEE/ւ~Zg&4f 0118~8Nffpsts0L_=^o|]oC?yޟ*dyiDuߏ߉kbժUm$|AMl򿆖tUM55Wfsɂ(y."}Bf< E+KMX0 M/OJ4u_˜>Çgv67C8K ?zٗ%8a5n*YMR mo͛ftD5WԊ8" R~.\^<DӂQo;is% "p)ǜcLG ,3 m,+A_4U e4hAn֐R Ĺs /{Oa`:g }?_>'?3N/2f+ƍp` 0-3VoNV zzfsss\q ␠`9 BfqzA(I>XѬ#xuHѨ1S?7ffh41mR0Mۛ8vNC< &.rvNsPUJA].TVtUUBogiص)z#>B|sz~?c68~>t]t Ww}/LUׂΞ= ` XMJ)-||Ҭ&qQ+E=)?j @sNY0'nE6`}*`CjpzU튴L695/≧v#* lz 7C- woe8yNTB{w}u]8qOGPvbՉ{hwq M}۽ =p\n)_zoxY|ٳgFu8Mg5Ks^OTڥ]bmpRݓ,vӾ@j%',1&Hwy4< utCJSNarj #WmNg* HB|;n?Wj;j?>&h=~꽨v' A":v葉1>nA]?k^ΐW{R׭߿67Es~wENjø)Պ9𸮋ukfED?@I$%K=hao)Nu1d#a/٨!+3L$)f:#92M_ $}wO2-O]q9L޳,]=@lWL֏n'Z^&tNچO-lgYs32%ܼHr$LBIt ij;(F[-}ZN V/-DW|Eb- pDDZ6)C6qV8Phmd5MbdYTt}R9> qtHazg?&RXdVе Ѡiq+/m{HQ&=uy_2 ?ar?sN?9sNl0{rN\b y7-ŅXM 8r(V2Ps*5슖Zy睶rW|s&Tn"v`~ήD6Q]nG#'$%MȜ87 ۲P,()->  6a&pҍyFLӀi0Lb"VJGfM[Ӯ([D@^ܯ5D0!#zzLWPzL=wemO#JW@\x(Mfi|WZ'İ80Db0 !`~7IͰm?Os)A#ʂ8՜8A0 BE i6OjMZ\b_@/rw Zͽ^n).T|)y/H.JX hŗY jMS^eh8 #DCO DJQx)N-u?*kPt(Qa=*J ;'BTkcB^eb$n!eAOA(b`M^K-Gtj1j'cf/ l\1Xrq7xH<:0ɷJ;8[H"pZcDr9Κ895z3ylސ3&c6)41ʍi䓩iʥ<͑rm x*l9$ 83J)LUqC6(j%Iz~uUCaz슟&kLgb <4G)rIgcA *hV gG/#׼ҜX9i3..̙Uj߮%BjuՖȤb:>!wF mL/T6.tB`X-͑r{I )}@Q./l+9BL72 r:%0Ygߩbf#ߔ8k0ugNBϭHJvn*v~U[[qyqjS}Byfaf9ԜZEJgY'e^h/67s.8a<(jZb~T6W|9 jK*<ϊx+t&!yg^r# x>f)+6ÜäQ>|͑9>qT8Չٴg񫔕KՄS@m"IŹR)ה+Qly+ÐEUN9OQZQCͤfvj6 דQ]ڌϱ9T/[$ܬ1dKe6nh)c %u*\Ȩʮ)Ag08ה[w>9d=σzV:Ċ12Tn^|)t)ɿc{art 8qfL@^h6[)bR0.XY)]8 XBg^*]yddR ;'y.6emZ#tࢳ`i7o2]1!/t{TnN|Y&Q'dvHjZ/MfLVJ ̞MÈ8ۓDF$aAڃyocn/KpDYQ(?QߞDkIQ*gV䌩v66Nq<lFQ&­Zr n{_#e!bT*nL9q̀NM26Ov**wm/ŎeLOʩC@D=]i1=ۋo_^#TnfJk/fR*N!izo}g06ҭ;9 f '8^$XRq/JP26}lf,Q ;9vH]S܄bݒn~l|]7yy#ݻ(!8囈P)͡"iQmBAmN9XWp@5;?gϣ6[Oslh4}'O 4HZydg|mo}\(jȍg:lBxu9r%%4GNN9{?ٹFB$ +I^Rw^8usp/3Gܪc*RT.s]t !וΜM[%PkVS{cclb-N:H8D<4\* ;Z(](eB L? "/cfFtmr[6?|nxr/Q\ IDATe9¹\ 1yRZ &혣]=[O±hJ) vnmׇR02@N^gm8"Ir a(rDk R$Pl\48k0q^x~gBJ9̯{sǃ#=9mq9Y/7\ 2e? 8$Clݴo~}vJe(P\~Z~*=6\*a1 ^M6 @+]k6W< ~'g5|{w7/uY9*sKI_@rs|kI_f(x߻߉; ePAs+ފJ6m>lA/@ؗ~/mشy6mކwfg%O/͜;kxۏ~SAG ed5&*<mWJx<HcxU?~#uA2?qZɩI຋a#kNi^/‡i;,#*e.bOfS$ \O1ch֭Hٶu ~{`.I)] uDoR9x+:an._ypF93pS.cmOx""yxt][7VCb߾ ]۱>)C<7/_J_' wNU44JYTZ#NÇUfb`jz5b! J35<ԓל0ݸk.œؿիqˍ;u0pW* $'^д9Q'IevX"_cX`ٳFRݏ{l쏘C"}ܭk{Ʈ28(* ru@aL8ChM#-Bofh4px[o B \SO)+%mJ88~x$;7o ůrt?"%I)-&)&V_ebm8:ZEيεefH闠;w6FVbㆍPJ0 s=ל/f/JnhV,o!+ A͔Fև=DJVzu"p7|0cff{//>InFGF8=5ɉ(1txxHK;`hNoV)}oC/j' R*+Rzh6h4Aۚ?[,=Fٸap`0;`([T*3c* ؅ mz{mn|>Zu]uZMluJ 'A85#0i;41a-@Z4+.̵yWXs Oɣm R:ZN tZ|vmw`"Pw4*MRL\y$* %(7i6Rl5. ptuUc!bIJ,\kzb88-9=Y*yx<'fb>KPvZr+-{9J!lڸ rGm6)J'Z-϶{[3k"_&>VD^GίM 9(1LK6l5'$hgqPoe3y5o03 +x$?qO!AjUX f^/u*-+<]VyJ)8-ve9v^v%11}li(nA)q UK: Q t*058&<]Pf&vxc@*H%[? _btš50yᇀ P\U*]XvlYkL1_zr j+M!&Zּϰ-oq~@$K0VAW(?y:RظacNGZNdB3*Db#ϓh6p'r#[݃͛$J)Q*a0J%5 J5|+ C8pp"]$RK1Wk ?ߩV_m:Uk~G䯅8{ML|ë w*tWx,#MKm.w 8Tj%VQ0u]4<]QrkF`dd4AѲRMGQR b%`hXs#h^Xs35^/z.a.e$"v퉘ߤo00P$$*02S8X>~t,C*^ at 84xqyr9;mmסZ&}JILN|@, /Am1=Xo@ɠcI{nز$csht8quHOf2j;e ˴󆝚Y`π@eT%lSƳ<7IQ)+9 !}BeuPp9jE_rw2!rv뭷A0>ϢT~6e}@?b|zkZ_aLL^L|p]㿦gf`&(J_p0d(uon[9̀ 3yݽ Wgf,$;?ˌ5㘨} 0X`Q8}TG|f)eI튷M[+qhJa׉&ݮ5 @T +8`S`OfXsf1#tU ~^୉hOw.Lq\tͰPvMC=ֱjcm֮C@ vmvFJ07 UO~Q(UL䙭S/^!Rdw8!UgKZԲ4:Dᆝѽ*aêvŮ .=80}=wBRF3^`͡uCܾNar9Vmv]UxRS ns(U{,Pv@8,0 Μ ^KX;j8/Usp'j2JJ%nvV(uVx²d(H(QA'96gmt֍O>Vf$paUEmVj53~y,mV)़@G$ɚw0U1\ԛάR*d2֎>ÇvS%rsv=Eҕ|`NgsUPB\Ӄuk%3!eF WNe" ugpq[JԜWʕ\KAk-W*ʝn''viM)סEnP /V1"5L 4&v`nnk텙QzjrWukAp H dm|\4۝v`X!P$ 402==*'mp̋W\Z*SgxU̪hhrHQ2):Z#"\Xc9`̥9_ gU]g[ٶR < \EpI OJX$@4Yڅo^5k1<;4z`EI:*^"w勝rG;gJ[HEPuLP@D݆i@Yaf_8{_d4A|s` Ilܼ 1(f_H|)5F-ꕶ*W؉X%t׏ zO`E`xpZ{v,CX(= Ƞ [m`s0 :wP(us:AAQwU;Ns,%~p廏0kP61^ۣ1%2VS(UC vbAfRB7הkfЂi -u?"9&m9ޞN>sewLvCͪ,; B>:2PP܄šC*S?G%HR.raMk :6cxĖT3r#,TWZ -۴F ~ޗw0-?` s(2 c6K_A4`5?NU Be%q)]e$K3,84ݬ|:7{/eㆍm[[-#3t H90Y(ȩ% T0L@\ึ vl f21:H*]V(ah} %`dAd)/iDnY`m(D)F(y$x\VXnۯ?FB0ZYtY4;Zm٦R܄YG u`H C3M2ǡT+aV,A.4Fwh ` ={ƿ>MC W!B<܁fg̪N–* ŪUCZ;O@*@z{1 &L) J b\*%!&,ہȘiSJU A(nyltҞάR J^F̌V[ef!/X=h(Fz Y(v&cIh²9(-`0l?c'ڌ0EjjVܹA@ KqW uݕhh60j5*J$\J)H4A8֯;rF@FOU0Jba[arA*&"MRÃ.n(,k:1yu+x#A:G5OX*\pgFbk400-K{ȗ8<{"2|D UB L|CL)a@R6l 7~V+ g )X31iV1t 8~TKP.W#, koij&E~kלCZC+EBZI`+XTÜ[`FԀiH HòoyDbtP,sTXB& -<Y)G6]]UlX1Z3_=,V~= &?2! dXl0V9X& gͦ>f2cd|㻮^縔$+}AM]Y?ϰF[nDt̡ZF=J Ь"kư-ijK~GvPl4r[ؾ'4^bӫpa?%"4MXyźK9KYo)6F[J%e cxx8Bڧ5([м:`nF>RхiDQ%x R X5}ce,FR5P*_Ý!GyrZW-O_K\yMQd7$ 08]ZX6gVܴMgRO1X7P(0i#5:(Ax Fo-gqÍ=x򉵑PaZR(+8wxPjajjP/MOOOO'Oy %Pva#(W=q/m/dTf"$/HThAGՄ;k~H;˒Ts(_pG;9^U͑QP+Ϫ c܂]k=~:uO=```y=x?Eo4ϼ (<(قȬJV؂ 78E/LJQbm`bb"x]==9r|NwCUwggg1>>ZmΞ='Oi5qX=zr@ݦ!0K# 7uǶ=XEI B1?2,{fq-3HWhQ!:1BK _]֟0\4.\G>wI{OM)ҼtiR~_(fr2Y:PB@"aIm(V޷w#N:sg]ENF]|J觞܍׿Ek&U|8B骃Z0;"z=fG>փ-['UUQ N'<:WAڏ xka*VAEtr=FSj C#.":aj:ivv/;-[6_VW`A\VLۑG~ duV Lc!ݙ_` ,FobWq-vyab&eN U%\uh߻{/e=Z.v>G9Vq8 (p7͢\F9 ~ZcFocYsz\2f TƜK< ۖ*ƫ_ |H R× 9b:|v!/*33XзJ°USF2nZ`C-#lPo&vw7 M_jWd,"r~G#<눮pk;i@G-%4/=sOIg[| a|#L8ـa3M)  Ki\vJj\I3plgnFҺ~H' _ !%`H r=Å\6ҮbO&lxʸ&ݽC?If =nۅih@`tu݇Bmmo£ߞ38s,F׌\ZՁ\ѥ(x!Kq`.ՂlA˜5-p\! CIӪzvd\t)ch4Oop[~@M‹&̴gY{J4ƶ=AC xw]5ÄPQ:> s 1)'1ma#~Y UmP1 ẰZVFހQQ 6L-ř]s|i17WSOɼ_b˖uk^3F }ap yiiU\|ۄ'}&;[\B'ggV?$:9ؓΜh6 yd\2"\pR0{`vWQTB >|6lw6^A!RȈ_2B70$$0d*e >.O*%=_$:HU :JSS(;a>y#"@)Tfеu+720JBbB](.` 00p||W"{^|ۅ 8z}_̠X ﲁb]Uq{/Ml W)ӷl4 IDATJ-$pm䢨hA'Fȉ|AN ʧϠ|px5MpNA43 Qf-֢~T]TP*Q*`JBĨx:Q u L$ K`Y(}oq oͩZK:#Pbhó׳5?:@߲\a΀~z $gK~Ss>$PFx}V+ R ]TQTPeB50W/qy}W UoQX&HJDV #Xm+W Ů.3XzDFdPFO$S@)|{й`S{`Ytw 6B_3k&?a*_xxVBJ&RV ?yir?-#2HqI@ 18Cp C*0l˯Q+cczCm_(+<ѨE~m@[b_ŸY-~j`HD]Ey2LZjatvۼJE倃Htx/k Mx9ș4l2 @s(RqZm{v?v_ŦuT+> 5$N4qrGKxX:eC6ΠwP0aRY`O]'!" Hbئ VLzH&_'A(Ԧ h"Y8xE <QN&-68n~}g0<G.N~n"ۙ=?>>l4r9h\-NmI(ʖݙ2'{F "w/LtA\@ $ /I/qljq.3w]׿ش1d/=6gy)>F{p5=w8pdB_(Yu4d JrCp ! Sue0jf2OMu^izC{MSݖخ*`)SG2lSeՙ*B9|ID .3x`l3cfffOr^OU#vzRzzD !jbV" fSx.k2 Q0-AڽG gKϟ;ND<<;Qƚ5J2THMjht|[U׿Ύ-d"dJZ"KmƩ,Fo=p&(,R:K]'hϊن@UZu(UKT`[4 S6 ',O(3g^E3,q TGw_h FP.YhSB$AO ٰJë_ u&Kq4LS${NyhNԑ%JejсNΝ_YiӋ4~7 …q:rs{ԅjR"`$la2 SB C0|f&BJX-FsIs߹7^.4<vm/Eؾe7z&+ r/ wE"gFOL:^lnvЊ)xmo{4x \wȔZt {x`ŘlyBpф oZï}ϗp/>n;38y!8$vuN#w(b"-#6wgpm2Ұw?f/m=8|Ю4\nXE@Q`UqG+H R*BC@{}<"mϗš#GpOt#h>_ͱ6 ?JUb& ^?z'm=16Y&Ե%=vz'(2>Kw-n%FPUqD%`cg4׷E5[ؕB&z҅Al_;Sg-"cnvo"tx*NJz\{ KK? lAɺ)/8j]4RY~zcɍ$|6ů2a Ю1>qz*`l5w:4$gcw)kHm x 7*>}a: x Ď۳a)%%qأo` hM5*#SKO7uS3o76p`}s+k^YAke%wJ߱(r$-'ږj{ Y,GZso}W9T [ݪ}H|hf23@ٶ8$Sr',`-꠵ (! ('f(tR$ɂV\^[k>dRwed6?`*s  02`bC*N!]}}]|"< ~Wlw.1\]աCx9 7PߣN D+TSNJjEfEWNӔ Db-E"IE~Ǐ=ݻg]$")K#7Gnt ha4@٪޺pB{8Dg0@{0@kbG !n޶ewjDlI^Yzq/}{7g?}(&ΪaTDᮺJsyfO=pHPYASzJ@=Q̃ZᘪjL׎Ѯk-wZ!zȴiտ;8|VWWY7/:(C fJuݡEC )ZMj%U&`E/`r0$S("!rf3Ϟ_^yG_o$_~T)=AʉV3e5m5`Xg&-?r%c?jTǎ>SjI~հTUH1Pv[NhPRa(=d&8B0!RD )a(@vK}ۙݻwV /'x=9]ӱ>hI@ێmÝNn{΂c3bd_#}ī_J66䋋X]Mv-8k" AujC@-@ GQ|~U}M?Ӌb{mOw*:`f"l8bPG`,0Dj.J%:-L&7 k KRfC[Y=vny)}U bvLOwiZWU6rf05=@2sC CfQוu uS [u]u^omWuiNuKK 9Lm+d9{.:ZEAp'3w2 Cn 0ɨD0Ad#M"d$a$ "DR4P4*^@fb- ,EYt˲kE$ =f^ B$AJ$ G4AD*U혙, H>lʺ,1r$ĩ'1lhŹO?я^8`yj 8zj- :IuTJj EHB VdD(9eI E*^η0eengle;3Y>`(7q `/ITU=caf?!W3k)⹉Lew1Z{/7tޠw5K诜Z{SJ:bKj(*J R* *0 [A%1RR!BOH0#<2sɖ#hcG`Y0,6jΥuwih7|Qw 70&ݩO=Hwvu.I.ܥ[^sLuk+ZYpV*?0PY"!TTB$&,B)lId(;)6r[T` K@i9L#KY2@ 4.QyR рcGGv;$x1+2]fvA'bem3¢cq/_z+nZw@ymOmjTEp"$LJIdBHh,圫EkI; 2YCLR49,P9؊hTÏxF Ks`!A ftG??4|ke~Dw-/z6GytQ?n7B66♳CݙՀX(Ȣ)s3FK2 g O`"h JI s;.)kx6pDQ渨I FUY$\h] MWb~:sv g&H?{8?\={ ?f+5Xmz`~a2",)XȔh%TmyA'&(Sq4k4v8[$tmܗۘϴƄ$~_a LU8u,V7r1VD\=3'wk3 %0; NkbgN'CpA^fDJ,צ:ѓ ZLEI"0 ـ"G+}l8A<> S*G )`EJ*qՁ=v\hRK˫8s~es TQ ]ޚr*K;/= c|qֹ'fK9a IDATeAYUլX2 4k]#i b2]$#C$- \PMi%1KӪ0"D3!J O9aDa?G?+ Ba 3]Luh%R.C{eVDk {X/P <$= 7,Zasyp#:*j&}biЌ#Mo¯>[|leHb$QC46:bjoc l*$Ordjwx%,ά]nwѤBNEN."Fe0i :AFPrܠ&lU p`#\T{Ї9~ks~}C^=,,cOȌaeP%ceׇQkZ$Z Tb6ՑLʓ-I%S3QIRa3 4 {RfЀBVHsd6@.&@X)=x)nQ< Cy3' ˠFiĀ)+nZdN"D A Zxbr0wD]˔$rp=j\na +wpDm2ه$$io5M]5 crxKj9FQe|U#!I HD8" K!),:i)!CЧXY=qnyO|o}^r~+^&|统Y|QgmU֪HVNU09 :aEHc 3tZ AX8!JmK6 0df K"*yyPꎭ8ZC $.L,iH.Ӏ"` YT3jJr>Zn;LCT{`u" |Sl+YXw/cx㭷raa'{=OM1_}yvԱ7!ͪ&ZB'C6Fb|bBh D!1 `!ZI ئ@LK`N؎yx}}unVI={~s9e`[%޵.Q/νq 5_w0v 7Wh孖&`< @ݕ$YM,˟IjKmQx@Rj igT:7X=twwT/a*LqҶn6EQz$pP JN( [ҳ+_^U `"NYݟz   l_/?Bɐ蠴rpǢV_ZBLd]k#3+v˕&.L&L4z; qҢ[vJN]x-L  `@@Qz |O$2ڮJ, ZeUzﬞ/KsG5M4nXQOT䟻ut貆 v<^,!15M*ȧDW g밉;Yٯ2sRr"%3VMϜ&X&yy7m?/O I9iUĒ$= 뭵[R&~&c쥪.)B.;o#}ҙ]Qвrj|o=R/(efXMYHh014399J:JmmmTxz1qto[fgg_`J&Bynic NްVϱf-4mI>9}W21=+`P7ZfmGcZ! d!(ra[JP#pj:::|+6 ^mvے_y]!}~^gEБ:ٰJ<`BypXZjAFU$0`WhҾt ~|q^ŪU)h(D?rBjrIb%QQLJhqJ-s(L|K(ro0%Izƿf+6:oy24M[栒LL==%୆r4M;`0Rzzp|:_枞ٝOA#X zw+_Zl~I,_M~=ikl,v:t2`*xJ}Tiga8EyX$\ Bkٹwм$ s}9;- Mk/XJ wT+;bᒱH8|[q}n&Sߑჩ8ZGfcl(;NeuX(fR䥢*3'"]X*1\[q&ifNhmKuЪl+]_hh-H_nu3NĸHye_蠴0sܾkEt]}\AA^^MkW J s}n/KRNoU.4o+"}fA('\/{BlIr+™`Eу5%xUu"~&zcua~%NDw{U5VAg+H5dm;D2sxe7, 3_\EEu Œ)@̣{/ΪϳaX+M U@IENDB`AntiMicroX-antimicrox-2888bf6/src/images/button.png000066400000000000000000000035031377703515000223410ustar00rootroot00000000000000PNG  IHDRVgsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATHŖI\GUo鞞 d,lJ2E HH #`6!!!q X6828~81'}z]oS𨻙uWqkřqkmfɬ07uşqK3>=EZLr! }˳}.tRnt|pc߱_?R7?꥗n0}D~R$<'74r+(@+M?3\KIlV K&+4=wkeOwG{(6\NQ*% >ZCo86 _x`SwmzWBْS q+Bv)Eܢ.<#47"zg/7S,d0'zP}Q~3~@i_hus~bנZ\(s#L7W0 Fo?ҭyS^tk&Naa!2ws#آ5TE%p`& @QhV7|hsXo|7 (c&;@5cx,$+`=]5L.e?.Fv h7|a6zE)U(]JJB 12枧ٶƦA9::pDĉ]rLƑd ̈́B}QVhhWVwVĦ%!ZC+F} 3j+hh"ҁiUdDAhYFS񋅖NjngTkXp-K9Ys U[ sa>x) "9w4F84E% tS \ZDp R`mJLqۃ!Vjh(/+`mV"x9܊ Zý%+B;^1t"t'øP܂)Ǧ&R0\̊aP঱ YOmxu2R;LyZ+R,v,#Eaܱ__찡l]7Sz3:+czF|n>c悱FV!/uq{-Zg^Jގr4K73Jl$`l4*#U15]^c{=moO 8w@Z3\72[Xl 1_Cjk]S{V3W=e_e37k>^dgPizz`5>!;osUkdن z휛vL݊yFb+٤^tPu_vuʩUoy/^Et׏%FI +ߔ矏pw^8IENDB`AntiMicroX-antimicrox-2888bf6/src/images/controllermap.png000066400000000000000000001303671377703515000237200ustar00rootroot00000000000000PNG  IHDR,5p%zTXtRaw profile type exifxڥirdns^ xS~RU*p?}h.J/'m?|z[_ Rg/j_uǁ#ϻh_+_oa~IsޟTY9O4;1DG,8wGz//,b_K#R?G(k[ \~C>/ۯgNoeڏKvw{F*,s[|}Sjd" 692Z#T77s%&;F-¥^HµJT7qyUq-᝶-gށZ`ܿyJ>|k/\2F}mZ?k$;v~1s:OqńH| Pf5S!6@6i)Bpj>/wgHXb%6J)?55rhSι[yXRɥZƚjZ[uR˭Zmt̽[} 98Ӄ71mƙfeV7s,gWYuض;vu8J'|ʩ~%nfw˭~Ǐ}/_"j+j"7QZ'Y1#bBB@Bb[H9w*qYA#7t #nD)t"rEQzcç}i9VRaأYX̵$6V 딸Cquqm~U*:N n-\g%b3@!'g[m'sƣ$A%Q=y+K]uֶ-r Jpa"&l^^mqkǻbE?( 'z= Z-8Rf{W3 32@&j0*0: Cj`XVNnu\wG ^h`VjBWtY!u`T L5%/"^;Ԕ64U7NB×ꆔS%P hysHC!Ao [$uJ &h!w BYN|> 2' @tFq&.Vs0&jƀQ\p\ApF#] %O2mH#jPޓjjXT&nk Z8)}`dR9FT1K֊C9qP2{ {^5XK-3蘚 O ~~^ZHT4 bV PY6pmΑ=NZRZV :ʂZr5Dҕ:rZû1 VY<(+al!*rty%Q[`>ʁg꽠ppuY3!?Vn45 9Msȡ\%ǃ{lƁi5)ClqC u*U ;I@ۉ$2If`\rCM07Q i8!9c} '&N@1 Cr'#A!<(t8:v̿5V᷷](k pp(h*_ Á_H uV+& 澱PXzF5EȖqwuxi&% y'ńb@UzJ6dA 6),AބtXO;#B ^wK|Q@҂& = Ylg``yƻXzwFl6)4tC[E\\С0dWE~4I"Sdd]mvagዠOM9[,8h<\R]C|9`\{ A+d9(gS_pG; BNy*5gccы PQPK>JHJh2iYT[$} 7<+uKRh+S} $$fu7 q56!TIY 2)3P p/<[O^BxpVfl3XyKpمv`ID"DE[>wjFȗ`cknR̘P#Ln]gX4sWZ ج a>)/Y~#<'Na@J#ɘOJFwd! @5ZP%`VǮ/XUR=4<jr kBAJEK}]nnYWф-x͋=cDn*\}J^J3b"X__Pʽb% 3H1/C#Y)H̦^2$ b8%Fî?ipIέ***U+o׽q"=s5(s (H3; [D +&D-{U- I'kI԰4P͒P& 蓓}dW$@ÈIkUc!%F$QIq`pUbhCImAxC@XtLZ({F ^[>.0)UJ,b09BAlPb::IkZ,V㖕Ι;}Wϣ>!Ia}Ao)H h.eC 93< npW2}Z,͜A\r<t)LD; zr\\)GqS}7H:ž FV1pLP_L6O4/ģچ@&i!9PK3RN,`rL*X kuenQ ߊf(|q&Uܚ'?ͨ҃CE欣vToւ$ۨ<7@dU i ]FlǶp{8͒t=  lGFYn ,Ր7!|p穆[)Gn,䛚ߡ՜qY`FyBozt9j3$bi"!2"quV{=y(W8)j8P4<:KYV%Ct}VmYYxqjwxHڰ w $DBZqj[p8j*F@.{.3br1XZ}spP8xYGGDsn6"A .!@375v#nw4JnAF!yaeIejFGh#tgaտ¡tqʎe9qE\c$Cd  E,-@D"NR:o;`]>xێ'.`2Py3v QĂ͵8^(#dycŤ|=var&mI4I4@Wl$Ldc@G_ oKSd f%햢R{) S` wd N]L/]bĎ Je\͊}(B}Q*Ҩ6rYzl5pi^R.0wY[C<%_nIBQUP%fy! s]`PC-V.9F]!/ !NXؤl-D>zA&'EYyŒA91q2}jF6M[]P&HPp*RZs4Pt'$v)@]8&8@Pm&|3GڥFMmk"JBT#|QWiO}ShEbrLX[%8ͫAy5)K5O8[@,j{x&̌o^ϒC pn1C>j.HAf X l|hˀ\Age8y:b&Jzz04Y)P~.\9? ,&]O`($_!}٪y(hr1fh=XnVHDL:INXI EUepxH H86 {BFppYk˒PΔ^vGFJA]3Bq\hZL]M3r2xTT 46J$E 8`\O܁#SsIDI Ec5&\ML].[+ܻKvښ n V\@KT1ҒlQQF6 0NXH?M xz3OގLEBj L.\ 2n#L͐XG@TZԽE\rmy5Qi%@Kd6N;h8/w;\I5s"EaA 8MP4_Q5 kLkkiKj Ja8?90Z\ND UT+Wc[ͤxߍKɐjYSJ&D3 Y@McjylFC6\nFJQ}b\M|f @jeY.E$Y/g  }ҋ4=o! g kW=U~}欽ԥq^ol?@#zvY+DJL#>W'7&Tے?}j->'G|6(!)(C`܀?!QM_7G V *r''XQ ]xDṔHQ*Bb~i"odP8E07R-h[l)#'>&Y󾚭KHԺT 2U"SkԈf/ԷO`қQ%ro:yYb#aF+f9@fYLºeUl< N JFs`Xv0Dx2 ARH@c=j hS^itm 86} X{[x HNbq@Rp 6mAGiV  .YP=Eb 'Sxñ&&vq p~nk%, zi5D[C\G$H.s0HDZa䩱`SQK.d1,š nUa!󩩡GjqobU/ś,|9TrpE4e:Y+T7o8!^]^ P\t-LXj0;2ILc7 _#{Yª.E%wX7-U[o9P#9@D%`F|2q@98mvc?{L%*Ym[(<܋j34 ^"9h5yVk[ָ,&ǿmM(Qxە=d ʎJ I0ՠv(oeAՄU} VN=S&=դYX&'F u ͗TGX.` But6v|,@:.蔦}6\2ET.e#=IPH 6`1~ȕv j}yk]2 #|Kv"_6w=J;R+6q"$FE{XM7-Zx; Od%V_…ϳ: Xhm]sű\Җ}ٯVSCG#&#h:+kx7&.E}$\(ʢFNvFk8)x,}bP \&E qwEC%g9&xSPe =[]=yòv W'*z'dB|0 <>0 ih# _UF癣 Df! f> %SY~allR5&uɇvdqH ~rFW&H[*Ӕ2=<쒣V=eBQ h@W jEOp'q90=?=#O \&Մ"WrZu$֤~ : -l E`o7&|ыؐӅϡ2r*j`AV{Ak+G?S p#4DBjl,4A@E[xt.z|.6kpmCP8-k 3Q`U Y; jQ&NgT^0P É0  NgAMA abKGD pHYs.#.#x?vtIME &%g IDATx}yXTg{k b)}}dU Q܍Y;Iv'3tg&ttvi,Ƙh\(DPQQA٥A}[}wy^x1K@ܫlllźl6ñb ;]jl޼xxcfO{b^s?$3331wA$I>}x嗽?skNRRV~z nΝ;HdffN hjjLq/;v Ñ=k8Nlڴ ]?'hoow{ɸ|wy ##cR`Xhmm%uA,$IO`Jsn1yÈl6cuŋIL6i*ջ$INHDxx8\#<<|!I'8^x1X_yb%l^º[p8ky OtSVpp0u@(6jDŤr`0<bٸr劗F|YX׮]#K΋ZFl6#bX0 ^º[1 K '2^L=aUT*݂.χd8/&MXr  11 ⮶²ͬV=qԂ v@ll,Zº3 YYY/&¢aJ{abr yikkCEET/qy1n\~jhnn6Պ!/aflݺ|7ozL&{t:Fii';::m6|,X:uuutzd-,/aF|Gd?R)8ǎIDgg':kע ϟoMd2Z !!!^BCPfaɒ% , 7nѣGQPPౠ{PPN>wy?>ᄏnu1jw%裏"<<ܣϟǹsb`0PPPGyغu+>Ӻeرcc=tDr!99vc단(X_rN8AVUU@tt4N=FXN6 A --lu\\֬YٳKZ ?Xd n"$$ PFPb1 ]CX| YWW˗pV+BBBd2=fal60L4٨KKKqu|^Һ;w.bbb$d@V{HDLL A$"""tR%J]1 ɞX&br:0L3v;V+ ŋ^Һi&2==[H l68VTT.]D.00˗/ǖ-[9';wzK,U*m;N&2 ,[ 555طob&#""?nmŊ £Saaa#~Eᣏ>lf5a}ǤhDqq-3f33Gxx{A^Çwdff&ܲΝ >nǣK"駟}Yb$#Z}] Vn0`0PVVGzz:;w},**BII7as`4z ͈D"$&&m$IgJ7Ax'W_ٳdAA%i͛@rID"l6; F^ F\( XVRB<P*`0PTh4 㮒Xd Z-;֭Crrf ׯJt00lE@@b1$ "##aZA$||| H  6t!..nTrXj;ϓjͺ__dNNǜ(Ab̙3EMM X,b1F#F#HblVjj* J:& cZzcÎ;˅{ ^⚡8s YYY}L pz"++N-[ӿ f;wZi/ f?/a/Ɗ+r܌Ƣ!!!mWvIB|cxسgÑ:[lA^^d2nBAL& ҥKFRRP}OZ w^455r$IHRHRxx:tׯxa4I].!Z DHRA"ӷzO\.J%v܉SNGœO>Ix ٳ|2ʐP8:44ׯt`0̙3Eaa!`Z! |hf1wܙo(=Z00LZE#T9FjzDH& . .eYL rpa?wΜ9X ٌddd 88gv/@tt4bcc{{3>>X,ɤkd\T1g( 444ԩSAII Q]]N2::g2 ٿ;wH$`ƆL&ë6h$.hZbA&!88>>>`2p80Lh4hnnFOOHD||DEEm!Cł!t:466B.C  %%b?Nh4ʢuz-l߾'|DDDM(pnۋAHIIAC@@|{3 t:\pXf "##=*9---Xt),L@}jR<b̛7dsk>O{{;Z[[A$KY/qWW_}E8q/Tzkk+___FDFFw$Io/Rػw/Ν;fD{{;N> ???zbݺu:b0ꫯjQRRii%W~- ^~q6RT*qittt@"!!!L4 KVUU3gZy13rذa]I1SU9N477|>wA8<.^^{$~\|9ߏ^{ VuLRDyy9.LZgϞrssuBɓ' (O=\N-[ 3gX,֘󴱱>YXjմpɴn߾r#F\. [$0z^G5@$b1/_=z2 EEE^ʕ+tVZ5&3en$d2$''ө;=JWl6#++ wFGG35-H8p> N'ߏ_|qhZ:t>Υrf 9L&r ]zCXXV\yW$ Srtww dgg#;;{DӧV~\t ?ϧOºx" uZFRiii mmy T`4aN'Qf=ʿDII RRRpI466w1V jkk!) kg fA X,X,vMT7(4IA,eb+b\%%%p:tX歷B^^"""& 5-V֔3\.'?c<#~P DKDEEuLINUz:nhhL& L&Oap:Zp:l6ݧP*ߟ1#2Njk׮C||MQ=9 l6j477 ٘;w,o.1+罘>( TVV-e[ .]B}}=K Nܥ F6#** III3gݓV3F}-ZP455`ٲeĬ$* 9998vBCCvj\.G__N< $Jw*݉Y,`@@>DDD. 8qϟ)sNVPXp!z˅N;v 0gDFFr/_F@@ 9J4 mۆz/NH._hii %uL)t:l߾}"==}$`ԩSDذaøHđ#Gֆ￟.rp8(**B||[\.Ν;A~Zd6d2ٳ0 `ذabMVWgg';lذG%K0gbVVgg'_Gŋ/8QM":::rPZZi6+ݡjajQVV6{F= .\dF_}j5V\It `0P*8y$|>,YٳP(AEE^}EXv"b1N:e˖2r^/dTټ Ӄ5k **jܟ'NU'"""iZ]]]8{,VX.]cǎwp#ICSS .]Jv|'Xp!\2e} z-R*"00EEEîD"Aff&\P iiiXhѸ))tuu 6 ?Bx. f0t-F9}P2i:jdXz5\., >dffcݺuĬ ӧOuuuP*xGׯ_!x{jѐ$Jh4?vK"'N`ppj7pu]X+WpB߳GPɓ(++C^^[$IZȀX,F\\ܴ3VewvvBFjj*L}7 yyyU5֘O={nr[#f4a) 7yjժ_~%|}}ճ IDATQXXx^ DFFbٲen+QR]]]~:hhoffi7Fl27cF'*sf/\^ 11ѷw9ڊyyyZÞMkk+/Bb׮]?? ɺ:봠Av>s,_!!!޸ phR"R(r _1L&j5t:t:V+܀C$]o2Thp8xWE 6 .1QPVX,Fhh(BBBr0$''#66vd?G?֬YUڸ]: 8}4mۆ۷/H$g,a-Y=XgΜ>:סjqbѢE^dYHLerqdEY?u*l )rN<<|.=r5l۶ HNNQVjEww7`0$I]T*E||9s̃$b2=)9.lXN'NdO<1㭭َNݻgāL_|> ұAա~~~h4 IqqqHJJłĩSrrJ&:w?S,^/9k֭dhh(R)n݊)!+*񯷷jV 0 vĥb& ?x<R)fDߏǏ#33yyyzᙹD5d0 (((@``Oݎݻw#$$YYY`0Bcc#$ `06 Ʉ={ 11#dÿ˿x$1g^_W!66֣p```555Exx85700>ZySEm6T*T*Յ~ߟIt:؈ddd`Dny] l6PYY $y'N-Z͆s΁dbҥc(NΝ;bŊI+gϜ9Ndeeg%faڵBMM JJJED ;ht̟?L&s'ei+**\???\dM^&/0Xt)Ҽl4gmXpQ466"88N3Z‡'zj}n 6oތ:GϰuVrݻwf?OF:ANN~ɓ'ǴPbrիW1tBь~BB /IV}}=-J?ſuVdeeaҥn $駟NiHDtt4-Gtt9%%eP(DEE[XDT$ga(++c=\|'0ޕǐfyW^Œ%Kg\.~ªP C(dֻRA`…_ rO.7[-xq1 EOOGgZV+s*~2!+e§}}}ngJ‰'Oyt˖-AӟZT555nA`2@BBi󪬬 I_(**%]K.šC& Ν;ɉ:u +W@ h|V Z ^L <B $'s?$IbtڵkvOA (//Ggg'-<<:Uܿ?\.$ JJJXzm HSO֮];@9'dhx|>VusLE6m"rwLTСCxW<j6ڊ69r VHɤ3l6|||PTT|DFFN$I|ᇈAvv] @{{;= .tޤ?>>p8h4hoofQCSIO>$"""fJLB[[C"vokkǑP  eJBOO W&C*:^0 lڴ *`0`Ϟ=Ϡji+((aaa@`` f0ZCOOr9}˅b HJJjhhz6mV۲\.L&d2ddd`ܹHLLáK%/^ĥKfAl6Z-|I,_u=A>|(..Ϩ$IBTرcX,Xt)]j5ЊJBMM .^.h4XVp8H$`޼y(,,tfj 7$'7B|ұSN>@WWB!I NOf3.\~fB3Ffw"8<`p@"駟T*wߏر \.NCCCÏcYOgV P\.ǑDaTTT nǽ:;;~\tJ ņ PXX) -- ĔV}}=y -[a՚ȃlغu+>SXV\."55uÏ5VGwա _׈vkt:K/4Tƃ:OX\.D"6n܈IYBTQMMOtFb<.jܪQ]]vzv0 |!77^ܷz/˅!rt:\.x<"$$mI$Ӊcǎa׮]lQG"0GǢ- -Zg}v.boo/L&zꩩ!otqkp].>wn2LxsNX,&`@Ph4p e%C&ݖDhEJGVV[/L&CJJʬZ|===x뭷(/{5mwѡV5kUnٳ/^)MVE||CTWWӖEXX pC-. ___bA@ 999.#I/۶m{ӣ@ZVd2 yyyп/ػw/]_`0Lr\|INNFdd$|>  tcHX#00* MMM0D#,/PP( ֭テlpk=:/O#vxh4Ф܌N;|8x \.7(A*ņRNz=jjjh};G):."`>0Lqu>.߿߳FHHȄ\_{q{EAٳ`0X`Ѐ~L&v"..HNNF\\R)8jT*ގAףv}#CDDjq5\r\Ih4h4`0`6rF幛f?M q]eZZ>L^@*쾝]%V >H |!`ڊsN{ᮮ.|th4"**C6 . NÁ%KkY,Q]]=.wnK KQQ._ Ӊ2 ԩS … 4[hMl$aXpU;v Xp!pI̛7 Bĉ㏏㣏>Bii*ԎsA!**l6:OZHOOtEE 1::yyy"pc?ÁP(7|T*477CTdE3u2' !ɞ֩T*P(bBrr2M:>EF`Ů]sM[܎ ڵ v\.z111ND`2X,t(L&rrrP]]M!k׮۷o͞`ZJ`8qĸ5kLgϞ֬Y3gΌ,wSX& ˅h\.[9{έ&g} :nBi088шI)0LDEE]̧˚ɄnXg*^O↫WNª%'[Q/jz_5XHOOGVVָd2 ?y#22W^dAʂjEKK uͰ /mppRtB$** eH]BjUOӡpBdA$={tB rMג'z~$ ٌIrr2jjj&OXΝCzz>Ţ(>//ׯ_GJJɗAAAܹs'U|rj$%%NP5p!PFM8ogx{,D6$ɺTfXHjP%)AxxUbGN!"bSJ ,\gBtvv"I $TVVaPq J;I("::)))bxº'K,AGGb1  ۯiq,OJݘ2A?tRQ2UG >*O,@ll,=8sBCC'u233#qY===p\HOOfCff&$|}}QRRBR*?0P(#Ƌ~Q+ BTUUMkjE[[|-O$߉_oo73Hp{P(6 . '^:N_~ׯL$|ADFFjNsz^999N}e˖[^䖦_MN*s#R)9Bjł$dѕ깹|P. ~-m{G}NG>l4jqy|m[@bf5}8vu8x<"g0Ŷm۠RB /a00L8}4+#&&f ,%%G{LƲe˦}Ns8塵W^7f8N 7oG 6 .T3#*O~2[b188JR$P+Wjf#--tE"Zɓ'qU,+!77 .muyp8.ڵ 6l2)\>3 (++m2#eq>PxAhWoo/h":z IDAT+`0nRsΜ9Xv~~~կ~ݻwĉhooGpp0|||FYP)&Lrr2֭[綸< dtt41.R*ᅬl/T\p\.ZoN$ L:* ,,x¤L&Chh-7h";v ~~~8qd2.\1u:Z| N'X,l6|||#Ep8 ţ>J+aT1==r_7oFww7BCCG(tX2Euj4w}XrĢXz)XgΜA{{;r9T*=^< 7orss>%>}㶰(2> lق77eSg7X* @!""III*N$֭[BFD"x<ٳ]]]Xz5'$I~)Au9z 0aƉfpp0^u\|ը hhD"ANN'mH|ղh4./ES9cccG2oKXʕ+4}aݺu7Uf*7gpp5Aov Ó;>A8<<>>>x饗hkkuO>K.aڵϟp6|kk+8(, ^yDEEͺ9Txjj*}0CQ ɤg%jRbJb)=]Dp'qLW"1YUUEΟ?4M{7햖,Y?gΜ nJ@KK ܌)4͆J"++kL&X,>>> Ql۶ ǎJ$MTO@ ٌN?~---p:td2d^s#L7AHRM=ۭGyy94 |>|||htpp]]]0L0L@YYbbbf]m$iɝZX&#n#>C@@ߋD"T;WZZ._i| 6 :BZRacS+;*;ى#_ !ر9233r@ˌPݷ].::: HTܹsOOzfww7>sF$&&"""RBaj|G3g{Y#<<|TOq)9jt7"::o6\_|uvvbӦMƍ0HII& }BBB\ko#RT*jfgggxzzBUF( \.3m :rUNjahZO"x D~~]b?яp12x/8m=_~m&>g}/^Z\.ȊV555(,,}jj ǎ#T[:V׮]@jj*bbbra68j)l CHHfff ɖѾkLWkCnjD8q\|{}@cc#fׇlڴiA޽{QTTZ Fjk '''˷9o΁>wڅ`JJJSO[> 7ߜ>JbcchcX`4QZZ ///}v9X,Ftt4 7Ԅ$$$ $$<  GhNw͆ntwwcjjK3 t0 DQoZ |R tعs]ܹs]7*H9,zAx7+aՆ+WN/xW(Bqq1.]DknW( 텇 !ңl< %%%%r Z-  ze0P[[j Ś0hS.\~rK8Ĭv)uRR(ܼyIIIin___R݂g^P] nՂ7~wx<ޒWjOQXX;vgΜAPP~1 ̠عs'H(>ߦ,`0Hp8pvvQ/]bvł)d2!""!!! prrݻe8;;JBK1nd"<#ߑ*~˘O`JBWWΟ?)[Bz@tdee nnnK~ECVV6nHMMM .\{ک 5N|'b6 |>'l6fccc&&D...k7sFZbjj #8~8W$څSNG``ຣFW\A?rssU7 (++C?233ԓE_ʴ 88Dmmm@tt?śoIBqX, h4r! "T\Dq_٩lFUUN>N5ld2DFFC?1cӦMszpE<\Vo9z(m۶,_>>HMM%j:L&###~:\^'''L&DGGCllh4|7ضm$;{ޗщ'GډUUUA.cZ(// fff}hD`` \\\ȇWWW#<<wᄉbӧHwJBEE^xp8jF\\c^ٳg_BbATTkvxx333DA探kYl6x`XZ!6극v155C~S颢"l޼($1 466B./³( eee [rR ݘ:::GםP dTm5P;NzI&B===r8p]D]rtry 001d2ӪհZp8CJJ I(4 z{{쌠 L9󅳋S*" >>>th4QWWG͘K 㴶lbi1 ( 477hD{{;p(Jh4Bм6 L&c׮]D"Y~tՊG"33sՔf gbU}׻G@@l6hT*~mfA, "DRhZ2*}A;*'''p\27bbb---ZpqqA^^[{T*ũS`0҂xWJޤ!;;'O'|dVW^O}DQQQTłn arrBff&^|ExyyB~~>\ݻw;@ ح TKKd_|`٨Cmm-qb o~^X,$&&'1880 L&ǏGFFq K1HFjRatt͐H$d^4 ;aBqMLL~FjWŤu-EJ .n޼ V#'v:;^J]pff}}}hooi'9pnc08}4֥ٽɓ'm۶; \ C  ** ###8y$p|ƢSSS40!!(в@2B[V ޽5 =?233es7^^^dH$PDee%|}}3 PRDFF>k \@,$Bff&oEvv668z(Ibccg899fMәfH Gр-[̈́(DEEk߳X,`͘@qq1T*SOA"f~!fffFGGchhCCC`0 dbbbM `Rt6to?^Gjj*v T w\RNNNΝ;ɻï~+8qeEYG F\.XyR@Qp5 ;;l OFMM ="V4bpڵ` ŠbDFF0P(`V***Bjj*X,$ ,mFVV֊{Ihoo v܉eu/yzzB&attDfIII˶zr)[ LMM9q`.]FOkkkNpJ%>sB|gp\\t Fw,Ϊjpl6nnnwyq===pssáCHT@HpqqM鉛7oBׯNOO122_/vu׃K-@&d/šߑ.LLLrXBб` 2 * "_p`4QXXXZX,DEEe0v+1zȇ(|dffpfd2믿&,E!-- 夝"++ JrM֗-)^{pwwGNN΢s5f3L&F#g8g̷Ɂl6>\tiEkF50==}a9Ү̙3j5N:& $''ccc^"VZp8wd2-8PYY Z,188HϏHS@@Wl6G/EEE(--fCaaF&&&PYYRcpp㘚8܌K.(+/,l6vtZv"[`t:zzz'իW֭[1>>7o"55uѵ( h4+4( 2 ---KbrGII \]] ή95!!555gg9rKU\q;66>6 -D#400TVV( ::prrj%<^^^D}&DB&D,[AӭY0 L\N-T~199 LOOח\f\rGFFQQQF 6 ]]]NJu ƍ:-Ze[$ ֦\ }}}`0DPTz\.wɱc`Z!ZP(} :!& LFԹcccqF#((ktD"LMMy -X*J ⟋b+5T*59(A@*BR瓰l6E!##cccZDsBwt]Ma\\N b!((p8c(Ѹ|2BBB^LLL`||鼾IDATJ$466dݝWs8;;1Bˤdm  X DH$;>fr( h4a||!] hkk#iekrg jzȣ חJ"*t=##z΂fZwf#!! M'b6AtALL :;;+8V fBB*jYD5h6P(HR2\%q4** 6l`@UUZ-$ NmH%%%O~F@\BhtNI^hh4mhh d{|2|h4BPh4B*<oUZE `0 HraX099Atuuaǎ0xhnn&T5kyIL&555prr]:IOBc׮]suW :E޼y3ussCww7& ///fHKK[wX,f2q^ՂML90^!.0Lx(JL}x{{cv$IMҚhD||R X&m/eҋE;͆pLrV& aaa]Vf6I睜ڵ uuu0ɄH$H$"iHKK[te fff6.|>*pssCkk+Q]ۢGWۑ>,zRkQ!Á/|}}d2Q[[PLNNӓ+M:h`W...KnU(P*0ͤnddPa 00pY900\.%E, D}}=!CCCNFԴg~T`q80"`24Y{l$&Qb8/[M%}F4DthD~~n\ !J\N(-fCcc#rrrƶX,0jap\D"899AӑhjZnN@XVhZXVR=0 k(BHHz{{b?]V<<>~_^???p\>|x޵ח-ߛp;`.={ {np\L&ƎnZyFFFCCQQQFtwwczz[n/iATT{O#'''ٳvL48ݑR^OjKz_5^[[NlݺuU  &7-CO駟fCAAJKKRTd2AՒCzcX,B|7n`jj 0L$O*B(bfի`28x yVn$$$&|xꩧpq###cHvDjdggӚ$~5cbb;vp 122[+-- j*sHs??qM/2~_fI4!yWUmm-"""'?lFee%&&&^xDW96lrOTÇǎ;\.a\KgEQJKK^O.hf+J|#i#ZW(`@RRҺ*/۷EEE$툌ēO> pҥ[yiY,4-NNNĦMƻ( 򂏏1`AޞB~~>Iߏbfgg#&&GE[[vo\&ZH$P*vt)墱_~%HY L&0[WƱ2KpHNNw}wc~@P… P(\T\NCqq1[L&''qe2 BBBc~!"""h$!!d ;pr9<8'et`jDpj hh4hjj"L/k׮lɔAAAhkk[d2a2ܝ/ƛo wwwgA;({n?x("22֭[#76 ]v`iNСChiiAcc# \\\ӟCEEV!+R]O122,[D`0࣏>lF^^ԅ?|0^~e?0f6ЀCϣ X,#)w`ibcnM+سgqԩENi0R) k a֭xW`'|!ٳixff&F#nܸq3\8ښL&3Vzz:JJJ+ gAEEܚWkA EA*.js봲ϱc`4/^#i {=r+dD"ۇo^ /8Vz###۳TRR#5\ p9xbx{{^Css3N<3g#I<oEB t*˅N\.G}}=j5ꫯ"!!8PR"..(//j%W򳻷~=X,`2s:NnO+b5Z bd"%%B/"_nnnHNN^m=R 6 eeepwwjA?&/amٲ%d"-- ROv&$$$%%%! x{{Օ(!/t_W `bb͛N( ѣ BRRbbbm6ឞرcFTT^u`XHJJZ6{MM m۶hkTYY7qthVo/~Aݻ>lajE[[{$&&"55D96 z8{,FFF XDDsGٜOlF`` CMh'*QWW)cbbvBzza9qގTjm۶$-E&K.!88زe˒Nٳgb?pC ::: JXa:uT*u]:R6l 5)M Z\-J; NNND8uz{{EUkZ- H谬V+:::PVV8pְrI;;FXԙ3gH W MMMP*hooG~~>ΣofO+ tvv. @Xlg\3 o`Z!퍞"''AAAmgpUUuu׃̙3c=@@rTS((--d?G> O?}gfre0܌Z DEEA,#00b...<_oݲ055Q BTBV$KNNƮ]>BYY 0bB2ަ#ZɄB@nn.FFF=ճ!..nqBa۶m[ŗhB& >Itvv%! wwwx,7oބ^ݱyfl6btth5b!""V x7{*##1uNd2arrGxx8 ŋMP(P(0::JL&8] T 0L#**1 ^$mt͐HJJT*H$jD"AZZY^ׯ_E||<\\\]HHHX:s 555E͛hkkCtt4 e KCSSUZZ R,xzz:f8{,zymSK(Bss3ݻw;#|!!!ǵ ikkCpp0nݺ|u d2!,,̱,^GOO;v8#n"ª;ZFϟomgQN߿QZ6 Avv6opT Rx" OOOU}-hC?z*z[D R{cpF@@T}}=qFӚG?hIF[oQFR*  O,eee]`>( uuuHNNFff;kN.&ݣse"&&G]> GɾL&o.jSK6~yL&'|Gᆪ*++!H9.p+KjY) O>Abb"Յ pT) dDaFKK B!:$ZQ'N͛)u:4@SSd26mLpTS|TSSF#thæ&899-Zh_â#ؾ};E={zz8ŋӃyFֱSƆ 0G|>\ML&J===P(ػw/^z%rAdd$ُ2jmmP(ƍ ***`7FX?xY7jnܸ<$%%9<:4552lA=555GNNΊl >@v5GII  68~-uM 4;F#Kv=wXPZZJ"##ciN&''FL]_B6lx蚚011k[5qW_! aaa+j:f{qpE9Pc||DCCDBWfVQWWea_BrdffSi]<ɄzDGG#%%1wShjjBzz:b1\tb2ӃݻwUkkb7oޤΝ;# l6{U%i~sZ2khhr9pIF7nDPPFASSZ-ca?*))ADDz=X,d2b1]NnEpvvB>pr;̙3Tee%R)fffe ɄlFoo/ヾ>x<\S;F^SSCBբ:""naEX,!H$شiI92q J.cppr"DuvELMMARb 00pssL&g![w# IENDB`AntiMicroX-antimicrox-2888bf6/src/inputdaemon.cpp000066400000000000000000001320601377703515000221030ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "inputdaemon.h" #include "antimicrosettings.h" #include "common.h" #include "globalvariables.h" #include "inputdevicebitarraystatus.h" #include "joydpad.h" #include "joystick.h" #include "logger.h" #include "messagehandler.h" #include "sdleventreader.h" #include #include #include #include #include #include #define USE_NEW_REFRESH InputDaemon::InputDaemon(QMap *joysticks, AntiMicroSettings *settings, bool graphical, QObject *parent) : QObject(parent) , pollResetTimer(this) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_joysticks = joysticks; // Xbox360Wireless* xbox360class = new Xbox360Wireless(); // xbox360 = xbox360class->getResult(); this->stopped = false; m_graphical = graphical; m_settings = settings; eventWorker = new SDLEventReader(joysticks, settings); refreshJoysticks(); sdlWorkerThread = nullptr; if (m_graphical) { sdlWorkerThread = new QThread; eventWorker->moveToThread(sdlWorkerThread); connect(sdlWorkerThread, &QThread::started, eventWorker, &SDLEventReader::performWork); connect(eventWorker, &SDLEventReader::eventRaised, this, &InputDaemon::run); connect(JoyButton::getMouseHelper(), &JoyButtonMouseHelper::gamepadRefreshRateUpdated, eventWorker, &SDLEventReader::updatePollRate); connect(JoyButton::getMouseHelper(), &JoyButtonMouseHelper::gamepadRefreshRateUpdated, this, &InputDaemon::updatePollResetRate); connect(JoyButton::getMouseHelper(), &JoyButtonMouseHelper::mouseRefreshRateUpdated, this, &InputDaemon::updatePollResetRate); // Timer in case SDL does not produce an axis event during a joystick // poll. pollResetTimer.setSingleShot(true); pollResetTimer.setInterval( qMax(GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::gamepadRefreshRate) + 1); connect(&pollResetTimer, &QTimer::timeout, this, &InputDaemon::resetActiveButtonMouseDistances); } } InputDaemon::~InputDaemon() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (eventWorker != nullptr) quit(); if (sdlWorkerThread != nullptr) { sdlWorkerThread->quit(); sdlWorkerThread->wait(); delete sdlWorkerThread; sdlWorkerThread = nullptr; } } void InputDaemon::startWorker() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!sdlWorkerThread->isRunning()) sdlWorkerThread->start(QThread::HighPriority); } void InputDaemon::run() { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); // SDL has found events. The timeout is not necessary. pollResetTimer.stop(); if (!stopped) { JoyButton::resetActiveButtonMouseDistances(JoyButton::getMouseHelper()); QQueue sdlEventQueue; firstInputPass(&sdlEventQueue); modifyUnplugEvents(&sdlEventQueue); secondInputPass(&sdlEventQueue); clearBitArrayStatusInstances(); } if (stopped) { if (m_joysticks->size() > 0) emit complete(m_joysticks->value(0)); emit complete(); stopped = false; } else { QTimer::singleShot(0, eventWorker, SLOT(performWork())); pollResetTimer.start(); } PadderCommon::inputDaemonMutex.unlock(); } QString InputDaemon::getJoyInfo(SDL_JoystickGUID sdlvalue) { char buffer[65] = {'0'}; SDL_JoystickGetGUIDString(sdlvalue, buffer, sizeof(buffer)); return QString(buffer); } QString InputDaemon::getJoyInfo(Uint16 sdlvalue) { char buffer[50] = {'0'}; sprintf(buffer, "%u", sdlvalue); return QString(buffer); } void InputDaemon::refreshJoysticks() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMapIterator iter(*m_joysticks); while (iter.hasNext()) { InputDevice *joystick = iter.next().value(); if (joystick != nullptr) { m_joysticks->remove(iter.key()); delete joystick; } } m_joysticks->clear(); getTrackjoysticksLocal().clear(); trackcontrollers.clear(); m_settings->getLock()->lock(); m_settings->beginGroup("Mappings"); QMap uniques = QMap(); int counterUniques = 1; bool duplicatedGamepad = false; for (int i = 0; i < SDL_NumJoysticks(); i++) { #ifdef USE_NEW_REFRESH int index = i; // Check if device is considered a Game Controller at the start. if (SDL_IsGameController(index)) { SDL_GameController *controller = SDL_GameControllerOpen(index); if (controller != nullptr) { SDL_Joystick *sdlStick = SDL_GameControllerGetJoystick(controller); SDL_JoystickID tempJoystickID = SDL_JoystickInstanceID(sdlStick); // Check if device has already been grabbed. if (!m_joysticks->contains(tempJoystickID)) { QString guidText = getJoyInfo(SDL_JoystickGetGUID(sdlStick)); QString vendor = getJoyInfo(SDL_GameControllerGetVendor(controller)); QString productID = getJoyInfo(SDL_GameControllerGetProduct(controller)); if (uniques.contains(guidText)) { productID = getJoyInfo(SDL_GameControllerGetProduct(controller) + ++uniques[guidText]); duplicatedGamepad = true; // previous value will be erased in map anyway uniques.insert(guidText, uniques[guidText]); } else { uniques.insert(guidText, counterUniques); } convertMappingsToUnique(m_settings, guidText, guidText + vendor + productID); bool disableGameController = m_settings->value(QString("%1Disable").arg(guidText + vendor + productID), false).toBool(); // Check if user has designated device Joystick mode. if (!disableGameController) { int resultDuplicated = 0; if (duplicatedGamepad) resultDuplicated = uniques.value(guidText); GameController *damncontroller = new GameController(controller, index, m_settings, resultDuplicated, this); duplicatedGamepad = false; connect(damncontroller, &GameController::requestWait, eventWorker, &SDLEventReader::haltServices); m_joysticks->insert(tempJoystickID, damncontroller); trackcontrollers.insert(tempJoystickID, damncontroller); emit deviceAdded(damncontroller); } else { Joystick *joystick = openJoystickDevice(index); if (joystick != nullptr) emit deviceAdded(joystick); } } else { SDL_GameControllerClose(controller); // Make sure to decrement reference count } } } else { Joystick *joystick = openJoystickDevice(index); if (joystick != nullptr) emit deviceAdded(joystick); } #else SDL_Joystick *joystick = SDL_JoystickOpen(i); if (joystick != nullptr) { QString temp = QString(); SDL_JoystickGUID tempGUID = SDL_JoystickGetGUID(joystick); char guidString[65] = {'0'}; SDL_JoystickGetGUIDString(tempGUID, guidString, sizeof(guidString)); temp = QString(guidString); bool disableGameController = m_settings->value(QString("%1Disable").arg(temp), false).toBool(); if (SDL_IsGameController(i) && !disableGameController) { SDL_GameController *controller = SDL_GameControllerOpen(i); GameController *damncontroller = new GameController(controller, i, m_settings, this); connect(damncontroller, &GameController::requestWait, eventWorker, &SDLEventReader::haltServices); SDL_Joystick *sdlStick = SDL_GameControllerGetJoystick(controller); SDL_JoystickID joystickID = SDL_JoystickInstanceID(sdlStick); m_joysticks->insert(joystickID, damncontroller); trackcontrollers.insert(joystickID, damncontroller); } else { Joystick *curJoystick = new Joystick(joystick, i, m_settings, this); connect(curJoystick, &Joystick::requestWait, eventWorker, &SDLEventReader::haltServices); SDL_JoystickID joystickID = SDL_JoystickInstanceID(joystick); m_joysticks->insert(joystickID, curJoystick); trackjoysticks.insert(joystickID, curJoystick); } } #endif } m_settings->endGroup(); m_settings->getLock()->unlock(); emit joysticksRefreshed(m_joysticks); } void InputDaemon::deleteJoysticks() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMapIterator iter(*m_joysticks); while (iter.hasNext()) { InputDevice *joystick = iter.next().value(); for (auto el : joystick->getJoystick_sets().values()) { } if (joystick != nullptr) { delete joystick; joystick = nullptr; } } m_joysticks->clear(); getTrackjoysticksLocal().clear(); trackcontrollers.clear(); } void InputDaemon::stop() { qInstallMessageHandler(MessageHandler::myMessageOutput); stopped = true; pollResetTimer.stop(); } void InputDaemon::refresh() { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "REFRESH"; stop(); Logger::LogInfo("Refreshing joystick list"); QEventLoop q; connect(eventWorker, &SDLEventReader::sdlStarted, &q, &QEventLoop::quit); QTimer::singleShot(0, eventWorker, SLOT(refresh())); // QMetaObject::invokeMethod(eventWorker, "refresh", Qt::BlockingQueuedConnection); if (eventWorker->isSDLOpen()) q.exec(); disconnect(eventWorker, &SDLEventReader::sdlStarted, &q, &QEventLoop::quit); pollResetTimer.stop(); // Put in an extra delay before refreshing the joysticks QTimer temp; connect(&temp, &QTimer::timeout, &q, &QEventLoop::quit); temp.start(100); q.exec(); refreshJoysticks(); QTimer::singleShot(100, eventWorker, SLOT(performWork())); stopped = false; } void InputDaemon::refreshJoystick(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); joystick->reset(); emit joystickRefreshed(joystick); } void InputDaemon::quit() { qInstallMessageHandler(MessageHandler::myMessageOutput); stopped = true; pollResetTimer.stop(); disconnect(eventWorker, &SDLEventReader::eventRaised, this, nullptr); // Wait for SDL to finish. Let worker destructor close SDL. // Let InputDaemon destructor close thread instance. if (m_graphical) { QMetaObject::invokeMethod(eventWorker, "stop"); QMetaObject::invokeMethod(eventWorker, "quit"); QMetaObject::invokeMethod(eventWorker, "deleteLater", Qt::BlockingQueuedConnection); } else { eventWorker->stop(); eventWorker->quit(); delete eventWorker; } eventWorker = nullptr; } void InputDaemon::refreshMapping(QString mapping, InputDevice *device) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; QMap uniques = QMap(); int counterUniques = 1; bool duplicatedGamepad = false; for (int i = 0; (i < SDL_NumJoysticks()) && !found; i++) // for (int i = 0; (i < 1) && !found; i++) { SDL_Joystick *joystick = SDL_JoystickOpen(i); // SDL_Joystick *joystick = xbox360; SDL_JoystickID joystickID = SDL_JoystickInstanceID(joystick); if (device->getSDLJoystickID() == joystickID) { found = true; if (SDL_IsGameController(i)) { // Mapping string updated. Perform basic refresh QByteArray tempbarray = mapping.toUtf8(); SDL_GameControllerAddMapping(tempbarray.data()); } else { // Previously registered as a plain joystick. Add // mapping and check for validity. If SDL accepts it, // close current device and re-open as // a game controller. SDL_GameControllerAddMapping(mapping.toUtf8().constData()); if (SDL_IsGameController(i)) { device->closeSDLDevice(); getTrackjoysticksLocal().remove(joystickID); m_joysticks->remove(joystickID); SDL_GameController *controller = SDL_GameControllerOpen(i); QString guidText = getJoyInfo(SDL_JoystickGetGUID(SDL_GameControllerGetJoystick(controller))); if (uniques.contains(guidText)) { ++uniques[guidText]; duplicatedGamepad = true; // previous value will be erased in map anyway uniques.insert(guidText, uniques[guidText]); } else { uniques.insert(guidText, counterUniques); } int resultDuplicated = 0; if (duplicatedGamepad) resultDuplicated = counterUniques; GameController *damncontroller = new GameController(controller, i, m_settings, resultDuplicated, this); duplicatedGamepad = false; connect(damncontroller, &GameController::requestWait, eventWorker, &SDLEventReader::haltServices); SDL_Joystick *sdlStick = SDL_GameControllerGetJoystick(controller); joystickID = SDL_JoystickInstanceID(sdlStick); m_joysticks->insert(joystickID, damncontroller); trackcontrollers.insert(joystickID, damncontroller); emit deviceUpdated(i, damncontroller); } } } // Make sure to decrement reference count SDL_JoystickClose(joystick); } } void InputDaemon::removeDevice(InputDevice *device) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (device != nullptr) { SDL_JoystickID deviceID = device->getSDLJoystickID(); m_joysticks->remove(deviceID); getTrackjoysticksLocal().remove(deviceID); trackcontrollers.remove(deviceID); refreshIndexes(); emit deviceRemoved(deviceID); } } void InputDaemon::refreshIndexes() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < SDL_NumJoysticks(); i++) // for (int i = 0; i < 1; i++) { SDL_Joystick *joystick = SDL_JoystickOpen(i); // SDL_Joystick *joystick = xbox360; SDL_JoystickID joystickID = SDL_JoystickInstanceID(joystick); SDL_JoystickClose(joystick); // Make sure to decrement reference count InputDevice *tempdevice = m_joysticks->value(joystickID); if (tempdevice != nullptr) tempdevice->setIndex(i); } } void InputDaemon::addInputDevice(int index, QMap &uniques, int &counterUniques, bool &duplicatedGamepad) { qInstallMessageHandler(MessageHandler::myMessageOutput); #ifdef USE_NEW_ADD // Check if device is considered a Game Controller at the start. if (SDL_IsGameController(index)) { SDL_GameController *controller = SDL_GameControllerOpen(index); if (controller != nullptr) { SDL_Joystick *sdlStick = SDL_GameControllerGetJoystick(controller); SDL_JoystickID tempJoystickID = SDL_JoystickInstanceID(sdlStick); // Check if device has already been grabbed. if (!m_joysticks->contains(tempJoystickID)) { m_settings->getLock()->lock(); m_settings->beginGroup("Mappings"); QString temp = QString(); SDL_JoystickGUID tempGUID = SDL_JoystickGetGUID(sdlStick); char guidString[65] = {'0'}; SDL_JoystickGetGUIDString(tempGUID, guidString, sizeof(guidString)); temp = QString(guidString); bool disableGameController = m_settings->value(QString("%1Disable").arg(temp), false).toBool(); m_settings->endGroup(); m_settings->getLock()->unlock(); // Check if user has designated device Joystick mode. if (!disableGameController) { GameController *damncontroller = new GameController(controller, index, m_settings, this); connect(damncontroller, &GameController::requestWait, eventWorker, &SDLEventReader::haltServices); m_joysticks->insert(tempJoystickID, damncontroller); trackcontrollers.insert(tempJoystickID, damncontroller); Logger::LogInfo(QString("New game controller found - #%1 [%2]") .arg(index + 1) .arg(QTime::currentTime().toString("hh:mm:ss.zzz"))); emit deviceAdded(damncontroller); } else { // Check if joystick is considered connected. Joystick *joystick = openJoystickDevice(index); if (joystick != nullptr) { Logger::LogInfo(QString("New joystick found - #%1 [%2]") .arg(index + 1) .arg(QTime::currentTime().toString("hh:mm:ss.zzz"))); emit deviceAdded(joystick); } } } else { // Make sure to decrement reference count SDL_GameControllerClose(controller); } } } else { Joystick *joystick = openJoystickDevice(index); if (joystick != nullptr) { Logger::LogInfo( QString("New joystick found - #%1 [%2]").arg(index + 1).arg(QTime::currentTime().toString("hh:mm:ss.zzz"))); emit deviceAdded(joystick); } } #else SDL_GameController *controller = SDL_GameControllerOpen(index); SDL_Joystick *joystick = SDL_JoystickOpen(index); // SDL_Joystick *joystick = xbox360; // SDL_GameController *controller = SDL_GameControllerFromInstanceID(xbox360->instance_id); if (joystick != nullptr) { SDL_JoystickID tempJoystickID_local = SDL_JoystickInstanceID(joystick); if (!m_joysticks->contains(tempJoystickID_local)) { m_settings->getLock()->lock(); m_settings->beginGroup("Mappings"); // QString temp = QString(); // SDL_JoystickGUID tempGUID = SDL_JoystickGetGUID(joystick); // char guidString[65] = {'0'}; // SDL_JoystickGetGUIDString(tempGUID, guidString, sizeof(guidString)); // temp = QString(guidString); // bool disableGameController = m_settings->value(QString("%1Disable").arg(temp), false).toBool(); QString guidText = QString(); SDL_JoystickGUID tempGUID = SDL_JoystickGetGUID(joystick); char guidString[65] = {'0'}; SDL_JoystickGetGUIDString(tempGUID, guidString, sizeof(guidString)); guidText = QString(guidString); QString vendor = QString(); if (controller != nullptr) { Uint16 tempVendor = SDL_GameControllerGetVendor(controller); char buffer[50]; sprintf(buffer, "%u", tempVendor); vendor = QString(buffer); } QString productID = QString(); if (controller != nullptr) { Uint16 tempProduct = SDL_GameControllerGetProduct(controller); char buffer[50]; sprintf(buffer, "%u", tempProduct); productID = QString(buffer); } if (uniques.contains(guidText)) { productID = getJoyInfo(SDL_GameControllerGetProduct(controller) + ++uniques[guidText]); duplicatedGamepad = true; uniques.insert(guidText, uniques[guidText]); } else { uniques.insert(guidText, counterUniques); } convertMappingsToUnique(m_settings, guidText, guidText + vendor + productID); int resultDuplicated = 0; if (duplicatedGamepad) resultDuplicated = uniques[guidText]; bool disableGameController = m_settings->value(QString("%1Disable").arg(guidText + vendor + productID), false).toBool(); if (SDL_IsGameController(index) && !disableGameController) { // Make sure to decrement reference count SDL_JoystickClose(joystick); SDL_GameController *controller = SDL_GameControllerOpen(index); if (controller != nullptr) { SDL_Joystick *sdlStick = SDL_GameControllerGetJoystick(controller); SDL_JoystickID tempJoystickID_local_2 = SDL_JoystickInstanceID(sdlStick); if (!m_joysticks->contains(tempJoystickID_local_2)) { GameController *damncontroller = new GameController(controller, index, m_settings, resultDuplicated, this); connect(damncontroller, &GameController::requestWait, eventWorker, &SDLEventReader::haltServices); m_joysticks->insert(tempJoystickID_local_2, damncontroller); trackcontrollers.insert(tempJoystickID_local_2, damncontroller); m_settings->endGroup(); m_settings->getLock()->unlock(); emit deviceAdded(damncontroller); } duplicatedGamepad = false; } else { m_settings->endGroup(); m_settings->getLock()->unlock(); } } else { Joystick *curJoystick = new Joystick(joystick, index, m_settings, this); m_joysticks->insert(tempJoystickID_local, curJoystick); getTrackjoysticksLocal().insert(tempJoystickID_local, curJoystick); m_settings->endGroup(); m_settings->getLock()->unlock(); emit deviceAdded(curJoystick); } } else { // Make sure to decrement reference count SDL_JoystickClose(joystick); } } #endif } Joystick *InputDaemon::openJoystickDevice(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Check if joystick is considered connected. SDL_Joystick *joystick = SDL_JoystickOpen(index); // SDL_Joystick* joystick = xbox360; Joystick *curJoystick = nullptr; if (joystick != nullptr) { SDL_JoystickID tempJoystickID = SDL_JoystickInstanceID(joystick); curJoystick = new Joystick(joystick, index, m_settings, this); m_joysticks->insert(tempJoystickID, curJoystick); getTrackjoysticksLocal().insert(tempJoystickID, curJoystick); } return curJoystick; } InputDeviceBitArrayStatus * InputDaemon::createOrGrabBitStatusEntry(QHash *statusHash, InputDevice *device, bool readCurrent) { qInstallMessageHandler(MessageHandler::myMessageOutput); InputDeviceBitArrayStatus *bitArrayStatus = nullptr; if (!statusHash->contains(device)) { bitArrayStatus = new InputDeviceBitArrayStatus(device, readCurrent); statusHash->insert(device, bitArrayStatus); } else { bitArrayStatus = statusHash->value(device); } return bitArrayStatus; } void InputDaemon::firstInputPass(QQueue *sdlEventQueue) { qInstallMessageHandler(MessageHandler::myMessageOutput); SDL_Event event; while (SDL_PollEvent(&event) > 0) { switch (event.type) { case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: { InputDevice *joy = getTrackjoysticksLocal().value(event.jbutton.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyButton *button = set->getJoyButton(event.jbutton.button); if (button != nullptr) { InputDeviceBitArrayStatus *pending = createOrGrabBitStatusEntry(&pendingEventValues, joy); pending->changeButtonStatus(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN ? true : false); sdlEventQueue->append(event); } } else { sdlEventQueue->append(event); } break; } case SDL_JOYAXISMOTION: { InputDevice *joy = getTrackjoysticksLocal().value(event.jaxis.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyAxis *axis = set->getJoyAxis(event.jaxis.axis); if (axis != nullptr) { InputDeviceBitArrayStatus *temp = createOrGrabBitStatusEntry(&releaseEventsGenerated, joy, false); temp->changeAxesStatus(event.jaxis.axis, event.jaxis.axis == 0); InputDeviceBitArrayStatus *pending = createOrGrabBitStatusEntry(&pendingEventValues, joy); pending->changeAxesStatus(event.jaxis.axis, !axis->inDeadZone(event.jaxis.value)); sdlEventQueue->append(event); } } else { sdlEventQueue->append(event); } break; } case SDL_JOYHATMOTION: { InputDevice *joy = getTrackjoysticksLocal().value(event.jhat.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyDPad *dpad = set->getJoyDPad(event.jhat.hat); if (dpad != nullptr) { InputDeviceBitArrayStatus *pending = createOrGrabBitStatusEntry(&pendingEventValues, joy); pending->changeHatStatus(event.jhat.hat, (event.jhat.value != 0) ? true : false); sdlEventQueue->append(event); } } else { sdlEventQueue->append(event); } break; } case SDL_CONTROLLERAXISMOTION: { InputDevice *joy = trackcontrollers.value(event.caxis.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyAxis *axis = set->getJoyAxis(event.caxis.axis); if (axis != nullptr) { InputDeviceBitArrayStatus *temp = createOrGrabBitStatusEntry(&releaseEventsGenerated, joy, false); if ((event.caxis.axis != SDL_CONTROLLER_AXIS_TRIGGERLEFT) && (event.caxis.axis != SDL_CONTROLLER_AXIS_TRIGGERRIGHT)) { temp->changeAxesStatus(event.caxis.axis, event.caxis.value == 0); } else { temp->changeAxesStatus(event.caxis.axis, event.caxis.value == GlobalVariables::InputDaemon::GAMECONTROLLERTRIGGERRELEASE); } InputDeviceBitArrayStatus *pending = createOrGrabBitStatusEntry(&pendingEventValues, joy); pending->changeAxesStatus(event.caxis.axis, !axis->inDeadZone(event.caxis.value)); sdlEventQueue->append(event); } } break; } case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: { InputDevice *joy = trackcontrollers.value(event.cbutton.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyButton *button = set->getJoyButton(event.cbutton.button); if (button != nullptr) { InputDeviceBitArrayStatus *pending = createOrGrabBitStatusEntry(&pendingEventValues, joy); pending->changeButtonStatus(event.cbutton.button, event.type == SDL_CONTROLLERBUTTONDOWN ? true : false); sdlEventQueue->append(event); } } break; } case SDL_JOYDEVICEREMOVED: case SDL_JOYDEVICEADDED: case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: { sdlEventQueue->append(event); break; } case SDL_QUIT: { sdlEventQueue->append(event); break; } default: { break; } } } } void InputDaemon::modifyUnplugEvents(QQueue *sdlEventQueue) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator genIter(getReleaseEventsGeneratedLocal()); while (genIter.hasNext()) { genIter.next(); InputDevice *device = genIter.key(); InputDeviceBitArrayStatus *generatedTemp = genIter.value(); QBitArray tempBitArray = generatedTemp->generateFinalBitArray(); qDebug() << "ARRAY: " << tempBitArray; int bitArraySize = tempBitArray.size(); qDebug() << "ARRAY SIZE: " << bitArraySize; if ((bitArraySize > 0) && (tempBitArray.count(true) == device->getNumberAxes())) { if (getPendingEventValuesLocal().contains(device)) { InputDeviceBitArrayStatus *pendingTemp = getPendingEventValuesLocal().value(device); QBitArray pendingBitArray = pendingTemp->generateFinalBitArray(); QBitArray unplugBitArray = createUnplugEventBitArray(device); int pendingBitArraySize = pendingBitArray.size(); if ((bitArraySize == pendingBitArraySize) && (pendingBitArray == unplugBitArray)) { QQueue tempQueue; while (!sdlEventQueue->isEmpty()) { SDL_Event event = sdlEventQueue->dequeue(); switch (event.type) { case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: { tempQueue.enqueue(event); break; } case SDL_JOYAXISMOTION: { if (event.jaxis.which != device->getSDLJoystickID()) { tempQueue.enqueue(event); } else { InputDevice *joy = getTrackjoysticksLocal().value(event.jaxis.which); if (joy != nullptr) { JoyAxis *axis = joy->getActiveSetJoystick()->getJoyAxis(event.jaxis.axis); if (axis != nullptr) { if (axis->getThrottle() != static_cast(JoyAxis::NormalThrottle)) { event.jaxis.value = axis->getProperReleaseValue(); } } } tempQueue.enqueue(event); } break; } case SDL_JOYHATMOTION: { tempQueue.enqueue(event); break; } case SDL_CONTROLLERAXISMOTION: { if (event.caxis.which != device->getSDLJoystickID()) { tempQueue.enqueue(event); } else { InputDevice *joy = trackcontrollers.value(event.caxis.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyAxis *axis = set->getJoyAxis(event.caxis.axis); if (axis != nullptr) { if ((event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) || (event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)) { event.caxis.value = axis->getProperReleaseValue(); } } } tempQueue.enqueue(event); } break; } case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: { tempQueue.enqueue(event); break; } case SDL_JOYDEVICEREMOVED: case SDL_JOYDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: case SDL_CONTROLLERDEVICEADDED: { tempQueue.enqueue(event); break; } default: { tempQueue.enqueue(event); } } } sdlEventQueue->swap(tempQueue); } } } } } QBitArray InputDaemon::createUnplugEventBitArray(InputDevice *device) { qInstallMessageHandler(MessageHandler::myMessageOutput); InputDeviceBitArrayStatus tempStatus(device, false); for (int i = 0; i < device->getNumberRawAxes(); i++) { JoyAxis *axis = device->getActiveSetJoystick()->getJoyAxis(i); if ((axis != nullptr) && (axis->getThrottle() != static_cast(JoyAxis::NormalThrottle))) tempStatus.changeAxesStatus(i, true); } QBitArray unplugBitArray = tempStatus.generateFinalBitArray(); return unplugBitArray; } void InputDaemon::secondInputPass(QQueue *sdlEventQueue) { qInstallMessageHandler(MessageHandler::myMessageOutput); QMap uniques = QMap(); int counterUniques = 1; bool duplicatedGamepad = false; QHash activeDevices; while (!sdlEventQueue->isEmpty()) { SDL_Event event = sdlEventQueue->dequeue(); switch (event.type) { case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: { InputDevice *joy = getTrackjoysticksLocal().value(event.jbutton.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyButton *button = set->getJoyButton(event.jbutton.button); if (button != nullptr) { button->queuePendingEvent(event.type == SDL_JOYBUTTONDOWN ? true : false); if (!activeDevices.contains(event.jbutton.which)) activeDevices.insert(event.jbutton.which, joy); } } else if (trackcontrollers.contains(event.jbutton.which)) { GameController *gamepad = trackcontrollers.value(event.jbutton.which); gamepad->rawButtonEvent(event.jbutton.button, event.type == SDL_JOYBUTTONDOWN ? true : false); } break; } case SDL_JOYAXISMOTION: { InputDevice *joy = getTrackjoysticksLocal().value(event.jaxis.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyAxis *axis = set->getJoyAxis(event.jaxis.axis); if (axis != nullptr) { axis->queuePendingEvent(event.jaxis.value); if (!activeDevices.contains(event.jaxis.which)) activeDevices.insert(event.jaxis.which, joy); } joy->rawAxisEvent(event.jaxis.which, event.jaxis.value); } else if (trackcontrollers.contains(event.jaxis.which)) { GameController *gamepad = trackcontrollers.value(event.jaxis.which); gamepad->rawAxisEvent(event.jaxis.axis, event.jaxis.value); } break; } case SDL_JOYHATMOTION: { InputDevice *joy = getTrackjoysticksLocal().value(event.jhat.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyDPad *dpad = set->getJoyDPad(event.jhat.hat); if (dpad != nullptr) { dpad->joyEvent(event.jhat.value); if (!activeDevices.contains(event.jhat.which)) activeDevices.insert(event.jhat.which, joy); } } else if (trackcontrollers.contains(event.jhat.which)) { GameController *gamepad = trackcontrollers.value(event.jaxis.which); gamepad->rawDPadEvent(event.jhat.hat, event.jhat.value); } break; } case SDL_CONTROLLERAXISMOTION: { InputDevice *joy = trackcontrollers.value(event.caxis.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyAxis *axis = set->getJoyAxis(event.caxis.axis); if (axis != nullptr) { axis->queuePendingEvent(event.caxis.value); if (!activeDevices.contains(event.caxis.which)) activeDevices.insert(event.caxis.which, joy); } } break; } case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: { InputDevice *joy = trackcontrollers.value(event.cbutton.which); if (joy != nullptr) { SetJoystick *set = joy->getActiveSetJoystick(); JoyButton *button = set->getJoyButton(event.cbutton.button); if (button != nullptr) { button->queuePendingEvent(event.type == SDL_CONTROLLERBUTTONDOWN ? true : false); if (!activeDevices.contains(event.cbutton.which)) activeDevices.insert(event.cbutton.which, joy); } } break; } case SDL_JOYDEVICEREMOVED: case SDL_CONTROLLERDEVICEREMOVED: { InputDevice *device = m_joysticks->value(event.jdevice.which); if (device != nullptr) { Logger::LogInfo(QString("Removing joystick #%1 [%2]") .arg(device->getRealJoyNumber()) .arg(QTime::currentTime().toString("hh:mm:ss.zzz"))); removeDevice(device); } break; } case SDL_JOYDEVICEADDED: case SDL_CONTROLLERDEVICEADDED: { addInputDevice(event.jdevice.which, uniques, counterUniques, duplicatedGamepad); break; } case SDL_QUIT: { stopped = true; break; } default: break; } // Active possible queued events. QHashIterator activeDevIter(activeDevices); while (activeDevIter.hasNext()) { InputDevice *tempDevice = activeDevIter.next().value(); tempDevice->activatePossibleControlStickEvents(); tempDevice->activatePossibleAxisEvents(); tempDevice->activatePossibleDPadEvents(); tempDevice->activatePossibleVDPadEvents(); tempDevice->activatePossibleButtonEvents(); } if (JoyButton::shouldInvokeMouseEvents(JoyButton::getPendingMouseButtons(), JoyButton::getStaticMouseEventTimer(), JoyButton::getTestOldMouseTime())) JoyButton::invokeMouseEvents( JoyButton::getMouseHelper()); // Do not wait for next event loop run. Execute immediately. } } void InputDaemon::clearBitArrayStatusInstances() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator genIter(getReleaseEventsGeneratedLocal()); while (genIter.hasNext()) { InputDeviceBitArrayStatus *temp = genIter.next().value(); if (temp != nullptr) { delete temp; temp = nullptr; } } getReleaseEventsGeneratedLocal().clear(); QHashIterator pendIter(getPendingEventValuesLocal()); while (pendIter.hasNext()) { InputDeviceBitArrayStatus *temp = pendIter.next().value(); if (temp != nullptr) { delete temp; temp = nullptr; } } getPendingEventValuesLocal().clear(); } void InputDaemon::resetActiveButtonMouseDistances() { qInstallMessageHandler(MessageHandler::myMessageOutput); pollResetTimer.stop(); JoyButton::resetActiveButtonMouseDistances(JoyButton::getMouseHelper()); } void InputDaemon::updatePollResetRate(int tempPollRate) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(tempPollRate); bool wasActive = pollResetTimer.isActive(); pollResetTimer.stop(); pollResetTimer.setInterval( qMax(GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::gamepadRefreshRate) + 1); if (wasActive) pollResetTimer.start(); } void InputDaemon::convertMappingsToUnique(QSettings *sett, QString guidString, QString uniqueIdString) { if (sett->contains(QString("%1Disable").arg(guidString))) { sett->setValue(QString("%1Disable").arg(uniqueIdString), sett->value(QString("%1Disable").arg(guidString))); sett->remove(QString("%1Disable").arg(guidString)); } if (sett->contains(guidString)) { QStringList gg = sett->value(guidString).toString().split(","); qDebug() << "Convert guidString to uniqueString 1): " << gg << endl; gg.removeFirst(); qDebug() << "Convert guidString to uniqueString 2): " << gg << endl; gg.prepend(uniqueIdString); qDebug() << "Convert guidString to uniqueString 3): " << gg << endl; qDebug() << "Joined uniqueMapping: " << gg.join(",") << endl; sett->setValue(uniqueIdString, gg.join(",")); sett->remove(guidString); } } QHash &InputDaemon::getTrackjoysticksLocal() { return trackjoysticks; } QHash &InputDaemon::getReleaseEventsGeneratedLocal() { return releaseEventsGenerated; } QHash &InputDaemon::getPendingEventValuesLocal() { return pendingEventValues; } AntiMicroX-antimicrox-2888bf6/src/inputdaemon.h000066400000000000000000000074611377703515000215560ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef INPUTDAEMONTHREAD_H #define INPUTDAEMONTHREAD_H #include "gamecontroller/gamecontroller.h" //#include "fakeclasses/xbox360wireless.h" #include class InputDevice; class AntiMicroSettings; class InputDeviceBitArrayStatus; class Joystick; class GameController; class SDLEventReader; class QThread; class InputDaemon : public QObject { Q_OBJECT public: explicit InputDaemon(QMap *joysticks, AntiMicroSettings *settings, bool graphical = true, QObject *parent = 0); ~InputDaemon(); protected: InputDeviceBitArrayStatus *createOrGrabBitStatusEntry(QHash *statusHash, InputDevice *device, bool readCurrent = true); QString getJoyInfo(SDL_JoystickGUID sdlvalue); QString getJoyInfo(Uint16 sdlvalue); void firstInputPass(QQueue *sdlEventQueue); void secondInputPass(QQueue *sdlEventQueue); void modifyUnplugEvents(QQueue *sdlEventQueue); QBitArray createUnplugEventBitArray(InputDevice *device); Joystick *openJoystickDevice(int index); void clearBitArrayStatusInstances(); void convertMappingsToUnique(QSettings *sett, QString guidString, QString uniqueIdString); signals: void joystickRefreshed(InputDevice *joystick); void joysticksRefreshed(QMap *joysticks); void complete(InputDevice *joystick); void complete(); void deviceUpdated(int index, InputDevice *device); void deviceRemoved(SDL_JoystickID deviceID); void deviceAdded(InputDevice *device); public slots: void run(); void quit(); void refresh(); void refreshJoystick(InputDevice *joystick); void refreshJoysticks(); void deleteJoysticks(); void startWorker(); void refreshMapping(QString mapping, InputDevice *device); void removeDevice(InputDevice *device); void addInputDevice(int index, QMap &uniques, int &counterUniques, bool &duplicatedGamepad); void refreshIndexes(); private slots: void stop(); void resetActiveButtonMouseDistances(); void updatePollResetRate(int tempPollRate); private: QHash &getTrackjoysticksLocal(); QHash &getReleaseEventsGeneratedLocal(); QHash &getPendingEventValuesLocal(); QMap *m_joysticks; QHash trackjoysticks; QHash trackcontrollers; QHash releaseEventsGenerated; QHash pendingEventValues; bool stopped; bool m_graphical; SDLEventReader *eventWorker; QThread *sdlWorkerThread; AntiMicroSettings *m_settings; QTimer pollResetTimer; // SDL_Joystick* xbox360; }; #endif // INPUTDAEMONTHREAD_H AntiMicroX-antimicrox-2888bf6/src/inputdevice.cpp000066400000000000000000001731161377703515000221060ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "inputdevice.h" #include "antimicrosettings.h" #include "common.h" #include "globalvariables.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joybuttontypes/joydpadbutton.h" #include "joycontrolstick.h" #include "joydpad.h" #include "messagehandler.h" #include "vdpad.h" #include #include #include #include InputDevice::InputDevice(SDL_Joystick *joystick, int deviceIndex, AntiMicroSettings *settings, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); buttonDownCount = 0; joyNumber = deviceIndex; active_set = 0; joystickID = 0; keyPressTime = 0; m_joyhandle = joystick; deviceEdited = false; keyRepeatEnabled = false; keyRepeatDelay = 0; keyRepeatRate = 0; rawAxisDeadZone = GlobalVariables::InputDevice::RAISEDDEADZONE; m_settings = settings; } InputDevice::~InputDevice() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *setjoystick = iter.next().value(); if (setjoystick != nullptr) { getJoystick_sets().remove(iter.key()); delete setjoystick; } } getJoystick_sets().clear(); } int InputDevice::getJoyNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return joyNumber; } int InputDevice::getRealJoyNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); int joynumber = getJoyNumber(); return joynumber + 1; } void InputDevice::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); resetButtonDownCount(); deviceEdited = false; profileName = ""; for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { SetJoystick *set = getJoystick_sets().value(i); set->reset(); } } /** * @brief Obtain current joystick element values, create new SetJoystick objects, * and then transfer most recent joystick element values to new * current set. */ void InputDevice::transferReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); // Grab current states for all elements in old set SetJoystick *current_set = getJoystick_sets().value(active_set); for (int i = 0; i < current_set->getNumberButtons(); i++) { JoyButton *button = current_set->getJoyButton(i); getButtonstatesLocal().append(button->getButtonState()); } for (int i = 0; i < current_set->getNumberAxes(); i++) { JoyAxis *axis = current_set->getJoyAxis(i); getAxesstatesLocal().append(axis->getCurrentRawValue()); } for (int i = 0; i < current_set->getNumberHats(); i++) { JoyDPad *dpad = current_set->getJoyDPad(i); getDpadstatesLocal().append(dpad->getCurrentDirection()); } reset(); } void InputDevice::reInitButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *current_set = getJoystick_sets().value(active_set); for (int i = 0; i < current_set->getNumberButtons(); i++) { bool value = getButtonstatesLocal().at(i); JoyButton *button = current_set->getJoyButton(i); button->queuePendingEvent(value); } for (int i = 0; i < current_set->getNumberAxes(); i++) { int value = getAxesstatesLocal().at(i); JoyAxis *axis = current_set->getJoyAxis(i); axis->queuePendingEvent(value); } for (int i = 0; i < current_set->getNumberHats(); i++) { int value = getDpadstatesLocal().at(i); JoyDPad *dpad = current_set->getJoyDPad(i); dpad->queuePendingEvent(value); } activatePossibleControlStickEvents(); activatePossibleAxisEvents(); activatePossibleDPadEvents(); activatePossibleVDPadEvents(); activatePossibleButtonEvents(); buttonstates.clear(); axesstates.clear(); dpadstates.clear(); } void InputDevice::setActiveSetNumber(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (((index >= 0) && (index < GlobalVariables::InputDevice::NUMBER_JOYSETS)) && (index != active_set)) { QList buttonstates; QList axesstates; QList dpadstates; QList stickstates; QList vdpadstates; // Grab current states for all elements in old set SetJoystick *current_set = getJoystick_sets().value(active_set); SetJoystick *old_set = current_set; SetJoystick *tempSet = getJoystick_sets().value(index); for (int i = 0; i < current_set->getNumberButtons(); i++) { JoyButton *button = current_set->getJoyButton(i); buttonstates.append(button->getButtonState()); tempSet->getJoyButton(i)->copyLastMouseDistanceFromDeadZone(button); tempSet->getJoyButton(i)->copyLastAccelerationDistance(button); tempSet->getJoyButton(i)->setUpdateInitAccel(false); } for (int i = 0; i < current_set->getNumberAxes(); i++) { JoyAxis *axis = current_set->getJoyAxis(i); axesstates.append(axis->getCurrentRawValue()); tempSet->getJoyAxis(i)->copyRawValues(axis); tempSet->getJoyAxis(i)->copyThrottledValues(axis); JoyAxisButton *button = tempSet->getJoyAxis(i)->getAxisButtonByValue(axis->getCurrentRawValue()); if (button != nullptr) { button->setUpdateInitAccel(false); } } for (int i = 0; i < current_set->getNumberHats(); i++) { JoyDPad *dpad = current_set->getJoyDPad(i); dpadstates.append(dpad->getCurrentDirection()); JoyDPadButton::JoyDPadDirections tempDir = static_cast(dpad->getCurrentDirection()); tempSet->getJoyDPad(i)->setDirButtonsUpdateInitAccel(tempDir, false); tempSet->getJoyDPad(i)->copyLastDistanceValues(dpad); } for (int i = 0; i < current_set->getNumberSticks(); i++) { // Last distances for elements are taken from associated axes. // Copying is not required here. JoyControlStick *stick = current_set->getJoyStick(i); stickstates.append(stick->getCurrentDirection()); tempSet->getJoyStick(i)->setDirButtonsUpdateInitAccel(stick->getCurrentDirection(), false); } for (int i = 0; i < current_set->getNumberVDPads(); i++) { JoyDPad *dpad = current_set->getVDPad(i); vdpadstates.append(dpad->getCurrentDirection()); JoyDPadButton::JoyDPadDirections tempDir = static_cast(dpad->getCurrentDirection()); tempSet->getVDPad(i)->setDirButtonsUpdateInitAccel(tempDir, false); tempSet->getVDPad(i)->copyLastDistanceValues(dpad); } // Release all current pressed elements and change set number getJoystick_sets().value(active_set)->release(); active_set = index; // Activate all buttons in the switched set current_set = getJoystick_sets().value(active_set); for (int i = 0; i < current_set->getNumberSticks(); i++) { JoyControlStick::JoyStickDirections value = stickstates.at(i); QList buttonList; QList oldButtonList; JoyControlStick *stick = current_set->getJoyStick(i); JoyControlStick *oldStick = old_set->getJoyStick(i); if ((stick->getJoyMode() == JoyControlStick::StandardMode) && value) { switch (value) { case JoyControlStick::StickRightUp: { buttonList.append(stick->getDirectionButton(JoyControlStick::StickUp)); buttonList.append(stick->getDirectionButton(JoyControlStick::StickRight)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickUp)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickRight)); break; } case JoyControlStick::StickRightDown: { buttonList.append(stick->getDirectionButton(JoyControlStick::StickRight)); buttonList.append(stick->getDirectionButton(JoyControlStick::StickDown)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickRight)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickDown)); break; } case JoyControlStick::StickLeftDown: { buttonList.append(stick->getDirectionButton(JoyControlStick::StickDown)); buttonList.append(stick->getDirectionButton(JoyControlStick::StickLeft)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickDown)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickLeft)); break; } case JoyControlStick::StickLeftUp: { buttonList.append(stick->getDirectionButton(JoyControlStick::StickLeft)); buttonList.append(stick->getDirectionButton(JoyControlStick::StickUp)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickLeft)); oldButtonList.append(oldStick->getDirectionButton(JoyControlStick::StickUp)); break; } default: { buttonList.append(stick->getDirectionButton(value)); oldButtonList.append(oldStick->getDirectionButton(value)); } } } else if (value) { buttonList.append(stick->getDirectionButton(value)); oldButtonList.append(oldStick->getDirectionButton(value)); } QHashIterator iter(*stick->getButtons()); while (iter.hasNext()) { JoyControlStickButton *tempButton = iter.next().value(); if (!buttonList.contains(tempButton)) { tempButton->setWhileHeldStatus(false); } } for (int j = 0; j < buttonList.size(); j++) { JoyControlStickButton *button = buttonList.at(j); JoyControlStickButton *oldButton = oldButtonList.at(j); if ((button != nullptr) && (oldButton != nullptr)) { if (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) { if ((oldButton->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && oldButton->getWhileHeldStatus()) { // Button from old set involved in a while held set // change. Carry over to new set button to ensure // set changes are done in the proper order. button->setWhileHeldStatus(true); } else if (!button->getWhileHeldStatus()) { // Ensure that set change events are performed if needed. // tempignore = false; } } } } } // Activate all dpad buttons in the switched set for (int i = 0; i < current_set->getNumberVDPads(); i++) { int value = vdpadstates.at(i); JoyDPad *dpad = current_set->getVDPad(i); QList buttonList; QList oldButtonList; bool valueTrue = (value != 0); if ((dpad->getJoyMode() == JoyDPad::StandardMode) && valueTrue) { switch (value) { case JoyDPadButton::DpadRightUp: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadUp)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadRight)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadUp)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadRight)); break; } case JoyDPadButton::DpadRightDown: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadRight)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadDown)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadRight)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadDown)); break; } case JoyDPadButton::DpadLeftDown: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadDown)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadLeft)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadDown)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadLeft)); break; } case JoyDPadButton::DpadLeftUp: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadLeft)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadUp)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadLeft)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(JoyDPadButton::DpadUp)); break; } default: { buttonList.append(dpad->getJoyButton(value)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(value)); } } } else if (valueTrue) { buttonList.append(dpad->getJoyButton(value)); oldButtonList.append(old_set->getVDPad(i)->getJoyButton(value)); } QHashIterator iter(*dpad->getJoyButtons()); while (iter.hasNext()) { // Ensure that set change events are performed if needed. JoyDPadButton *button = iter.next().value(); if (!buttonList.contains(button)) { button->setWhileHeldStatus(false); } } for (int j = 0; j < buttonList.size(); j++) { JoyDPadButton *button = buttonList.at(j); JoyDPadButton *oldButton = oldButtonList.at(j); if ((button != nullptr) && (oldButton != nullptr) && (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && valueTrue && (oldButton->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && oldButton->getWhileHeldStatus()) { // Button from old set involved in a while held set // change. Carry over to new set button to ensure // set changes are done in the proper order. button->setWhileHeldStatus(true); } else if ((button != nullptr) && (oldButton != nullptr) && (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && !valueTrue) { button->setWhileHeldStatus(false); } } } for (int i = 0; i < current_set->getNumberButtons(); i++) { bool value = buttonstates.at(i); bool tempignore = false; JoyButton *button = current_set->getJoyButton(i); JoyButton *oldButton = old_set->getJoyButton(i); if (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld && value && (oldButton->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && oldButton->getWhileHeldStatus()) { // Button from old set involved in a while held set // change. Carry over to new set button to ensure // set changes are done in the proper order. button->setWhileHeldStatus(true); } else if (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld && value && !button->getWhileHeldStatus()) { // Ensure that set change events are performed if needed. tempignore = false; } else if (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld && !value) { // Ensure that set change events are performed if needed. button->setWhileHeldStatus(false); } button->queuePendingEvent(value, tempignore); } // Activate all axis buttons in the switched set for (int i = 0; i < current_set->getNumberAxes(); i++) { int value = axesstates.at(i); bool tempignore = false; JoyAxis *axis = current_set->getJoyAxis(i); JoyAxisButton *oldButton = old_set->getJoyAxis(i)->getAxisButtonByValue(value); JoyAxisButton *button = axis->getAxisButtonByValue(value); if ((button != nullptr) && (oldButton != nullptr) && (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && (oldButton->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && oldButton->getWhileHeldStatus()) { // Button from old set involved in a while held set // change. Carry over to new set button to ensure // set changes are done in the proper order. button->setWhileHeldStatus(true); } else if ((button != nullptr) && (oldButton != nullptr) && (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && !button->getWhileHeldStatus()) { // Ensure that set change events are performed if needed. tempignore = false; } else if (button == nullptr) { // Ensure that set change events are performed if needed. axis->getPAxisButton()->setWhileHeldStatus(false); axis->getNAxisButton()->setWhileHeldStatus(false); } axis->queuePendingEvent(value, tempignore, false); } // Activate all dpad buttons in the switched set for (int i = 0; i < current_set->getNumberHats(); i++) { int value = dpadstates.at(i); bool tempignore = false; JoyDPad *dpad = current_set->getJoyDPad(i); QList buttonList; QList oldButtonList; bool valueTrue = (value != 0); if ((dpad->getJoyMode() == JoyDPad::StandardMode) && valueTrue) { switch (value) { case JoyDPadButton::DpadRightUp: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadUp)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadRight)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadUp)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadRight)); break; } case JoyDPadButton::DpadRightDown: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadRight)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadDown)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadRight)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadDown)); break; } case JoyDPadButton::DpadLeftDown: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadDown)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadLeft)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadDown)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadLeft)); break; } case JoyDPadButton::DpadLeftUp: { buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadLeft)); buttonList.append(dpad->getJoyButton(JoyDPadButton::DpadUp)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadLeft)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(JoyDPadButton::DpadUp)); break; } default: { buttonList.append(dpad->getJoyButton(value)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(value)); } } } else if (valueTrue) { buttonList.append(dpad->getJoyButton(value)); oldButtonList.append(old_set->getJoyDPad(i)->getJoyButton(value)); } QHashIterator iter(*dpad->getJoyButtons()); while (iter.hasNext()) { // Ensure that set change events are performed if needed. JoyDPadButton *button = iter.next().value(); if (!buttonList.contains(button)) button->setWhileHeldStatus(false); } for (int j = 0; j < buttonList.size(); j++) { JoyDPadButton *button = buttonList.at(j); JoyDPadButton *oldButton = oldButtonList.at(j); if ((button != nullptr) && (oldButton != nullptr) && (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && valueTrue && (oldButton->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && oldButton->getWhileHeldStatus()) { // Button from old set involved in a while held set // change. Carry over to new set button to ensure // set changes are done in the proper order. button->setWhileHeldStatus(true); } else if ((button != nullptr) && (oldButton != nullptr) && (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && valueTrue && !button->getWhileHeldStatus()) { // Ensure that set change events are performed if needed. tempignore = false; } else if ((button != nullptr) && (oldButton != nullptr) && (button->getChangeSetCondition() == JoyButton::SetChangeWhileHeld) && !valueTrue) { button->setWhileHeldStatus(false); } } dpad->queuePendingEvent(value, tempignore); } activatePossibleControlStickEvents(); activatePossibleAxisEvents(); activatePossibleDPadEvents(); activatePossibleVDPadEvents(); activatePossibleButtonEvents(); } } int InputDevice::getActiveSetNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return active_set; } SetJoystick *InputDevice::getActiveSetJoystick() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getJoystick_sets().value(active_set); } int InputDevice::getNumberButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getActiveSetJoystick()->getNumberButtons(); } int InputDevice::getNumberAxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getActiveSetJoystick()->getNumberAxes(); } int InputDevice::getNumberHats() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getActiveSetJoystick()->getNumberHats(); } int InputDevice::getNumberSticks() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getActiveSetJoystick()->getNumberSticks(); } int InputDevice::getNumberVDPads() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getActiveSetJoystick()->getNumberVDPads(); } SetJoystick *InputDevice::getSetJoystick(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); return getJoystick_sets().value(index); } void InputDevice::propogateSetChange(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit setChangeActivated(index); } void InputDevice::changeSetButtonAssociation(int button_index, int originset, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = getJoystick_sets().value(newset)->getJoyButton(button_index); JoyButton::SetChangeCondition tempmode = static_cast(mode); button->setChangeSetSelection(originset); button->setChangeSetCondition(tempmode, true); } void InputDevice::changeSetAxisButtonAssociation(int button_index, int axis_index, int originset, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *button = nullptr; if (button_index == 0) { button = getJoystick_sets().value(newset)->getJoyAxis(axis_index)->getNAxisButton(); } else if (button_index == 1) { button = getJoystick_sets().value(newset)->getJoyAxis(axis_index)->getPAxisButton(); } JoyButton::SetChangeCondition tempmode = static_cast(mode); button->setChangeSetSelection(originset); button->setChangeSetCondition(tempmode, true); } void InputDevice::changeSetStickButtonAssociation(int button_index, int stick_index, int originset, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *button = getJoystick_sets() .value(newset) ->getJoyStick(stick_index) ->getDirectionButton(static_cast(button_index)); JoyButton::SetChangeCondition tempmode = static_cast(mode); button->setChangeSetSelection(originset); button->setChangeSetCondition(tempmode, true); } void InputDevice::changeSetDPadButtonAssociation(int button_index, int dpad_index, int originset, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *button = getJoystick_sets().value(newset)->getJoyDPad(dpad_index)->getJoyButton(button_index); JoyButton::SetChangeCondition tempmode = static_cast(mode); button->setChangeSetSelection(originset); button->setChangeSetCondition(tempmode, true); } void InputDevice::changeSetVDPadButtonAssociation(int button_index, int dpad_index, int originset, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *button = getJoystick_sets().value(newset)->getVDPad(dpad_index)->getJoyButton(button_index); JoyButton::SetChangeCondition tempmode = static_cast(mode); button->setChangeSetSelection(originset); button->setChangeSetCondition(tempmode, true); } void InputDevice::propogateSetAxisThrottleChange(int index, int originset) { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentSet = getJoystick_sets().value(originset); if (currentSet != nullptr) { JoyAxis *axis = currentSet->getJoyAxis(index); if (axis != nullptr) { int throttleSetting = axis->getThrottle(); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { iter.next(); SetJoystick *temp = iter.value(); // Ignore change for set axis that initiated the change if (temp != currentSet) temp->getJoyAxis(index)->setThrottle(throttleSetting); } } } } void InputDevice::removeControlStick(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { SetJoystick *currentset = getSetJoystick(i); if (currentset->getJoyStick(index)) currentset->removeControlStick(index); } } bool InputDevice::isActive() { qInstallMessageHandler(MessageHandler::myMessageOutput); return buttonDownCount > 0; } void InputDevice::buttonDownEvent(int setindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(setindex); Q_UNUSED(buttonindex); bool old = isActive(); buttonDownCount += 1; if (isActive() != old) emit clicked(joyNumber); } void InputDevice::buttonUpEvent(int setindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(setindex); Q_UNUSED(buttonindex); bool old = isActive(); buttonDownCount -= 1; if (buttonDownCount < 0) buttonDownCount = 0; if (isActive() != old) emit released(joyNumber); } void InputDevice::buttonClickEvent(int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit rawButtonClick(buttonindex); } void InputDevice::buttonReleaseEvent(int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit rawButtonRelease(buttonindex); } void InputDevice::axisButtonDownEvent(int setindex, int axisindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(axisindex); buttonDownEvent(setindex, buttonindex); } void InputDevice::axisButtonUpEvent(int setindex, int axisindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(axisindex); buttonUpEvent(setindex, buttonindex); } void InputDevice::dpadButtonClickEvent(int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *dpadbutton = qobject_cast(sender()); if (dpadbutton != nullptr) emit rawDPadButtonClick(dpadbutton->getDPad()->getIndex(), buttonindex); } void InputDevice::dpadButtonReleaseEvent(int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *dpadbutton = qobject_cast(sender()); if (dpadbutton != nullptr) emit rawDPadButtonRelease(dpadbutton->getDPad()->getIndex(), buttonindex); } void InputDevice::dpadButtonDownEvent(int setindex, int dpadindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(dpadindex); buttonDownEvent(setindex, buttonindex); } void InputDevice::dpadButtonUpEvent(int setindex, int dpadindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(dpadindex); buttonUpEvent(setindex, buttonindex); } void InputDevice::stickButtonDownEvent(int setindex, int stickindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(stickindex); buttonDownEvent(setindex, buttonindex); } void InputDevice::stickButtonUpEvent(int setindex, int stickindex, int buttonindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(stickindex); buttonUpEvent(setindex, buttonindex); } void InputDevice::setButtonName(int index, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setButtonNameChange, this, &InputDevice::updateSetButtonNames); JoyButton *button = tempSet->getJoyButton(index); if (button != nullptr) button->setButtonName(tempName); connect(tempSet, &SetJoystick::setButtonNameChange, this, &InputDevice::updateSetButtonNames); } } void InputDevice::setAxisButtonName(int axisIndex, int buttonIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setAxisButtonNameChange, this, &InputDevice::updateSetAxisButtonNames); JoyAxis *axis = tempSet->getJoyAxis(axisIndex); if (axis != nullptr) { JoyAxisButton *button = nullptr; if (buttonIndex == 0) button = axis->getNAxisButton(); else if (buttonIndex == 1) button = axis->getPAxisButton(); if (button != nullptr) button->setButtonName(tempName); } connect(tempSet, &SetJoystick::setAxisButtonNameChange, this, &InputDevice::updateSetAxisButtonNames); } } void InputDevice::setStickButtonName(int stickIndex, int buttonIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setStickButtonNameChange, this, &InputDevice::updateSetStickButtonNames); JoyControlStick *stick = tempSet->getJoyStick(stickIndex); if (stick != nullptr) { JoyControlStickButton *button = stick->getDirectionButton(JoyControlStick::JoyStickDirections(buttonIndex)); if (button != nullptr) button->setButtonName(tempName); } connect(tempSet, &SetJoystick::setStickButtonNameChange, this, &InputDevice::updateSetStickButtonNames); } } void InputDevice::setDPadButtonName(int dpadIndex, int buttonIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setDPadButtonNameChange, this, &InputDevice::updateSetDPadButtonNames); JoyDPad *dpad = tempSet->getJoyDPad(dpadIndex); if (dpad != nullptr) { JoyDPadButton *button = dpad->getJoyButton(buttonIndex); if (button != nullptr) button->setButtonName(tempName); } connect(tempSet, &SetJoystick::setDPadButtonNameChange, this, &InputDevice::updateSetDPadButtonNames); } } void InputDevice::setVDPadButtonName(int vdpadIndex, int buttonIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setVDPadButtonNameChange, this, &InputDevice::updateSetVDPadButtonNames); VDPad *vdpad = tempSet->getVDPad(vdpadIndex); if (vdpad != nullptr) { JoyDPadButton *button = vdpad->getJoyButton(buttonIndex); if (button != nullptr) button->setButtonName(tempName); } connect(tempSet, &SetJoystick::setVDPadButtonNameChange, this, &InputDevice::updateSetVDPadButtonNames); } } void InputDevice::setAxisName(int axisIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setAxisNameChange, this, &InputDevice::updateSetAxisNames); JoyAxis *axis = tempSet->getJoyAxis(axisIndex); if (axis != nullptr) axis->setAxisName(tempName); connect(tempSet, &SetJoystick::setAxisNameChange, this, &InputDevice::updateSetAxisNames); } } void InputDevice::setStickName(int stickIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setStickNameChange, this, &InputDevice::updateSetStickNames); JoyControlStick *stick = tempSet->getJoyStick(stickIndex); if (stick != nullptr) stick->setStickName(tempName); connect(tempSet, &SetJoystick::setStickNameChange, this, &InputDevice::updateSetStickNames); } } void InputDevice::setDPadName(int dpadIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setDPadNameChange, this, &InputDevice::updateSetDPadNames); JoyDPad *dpad = tempSet->getJoyDPad(dpadIndex); if (dpad != nullptr) dpad->setDPadName(tempName); connect(tempSet, &SetJoystick::setDPadNameChange, this, &InputDevice::updateSetDPadNames); } } void InputDevice::setVDPadName(int vdpadIndex, QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getJoystick_sets()); while (iter.hasNext()) { SetJoystick *tempSet = iter.next().value(); disconnect(tempSet, &SetJoystick::setVDPadNameChange, this, &InputDevice::updateSetVDPadNames); VDPad *vdpad = tempSet->getVDPad(vdpadIndex); if (vdpad != nullptr) vdpad->setDPadName(tempName); connect(tempSet, &SetJoystick::setVDPadNameChange, this, &InputDevice::updateSetVDPadNames); } } void InputDevice::updateSetButtonNames(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = getActiveSetJoystick()->getJoyButton(index); if (button != nullptr) setButtonName(index, button->getButtonName()); } void InputDevice::updateSetAxisButtonNames(int axisIndex, int buttonIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxis *axis = getActiveSetJoystick()->getJoyAxis(axisIndex); if (axis != nullptr) { JoyAxisButton *button = nullptr; if (buttonIndex == 0) button = axis->getNAxisButton(); else if (buttonIndex == 1) button = axis->getPAxisButton(); if (button != nullptr) setAxisButtonName(axisIndex, buttonIndex, button->getButtonName()); } } void InputDevice::updateSetStickButtonNames(int stickIndex, int buttonIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStick *stick = getActiveSetJoystick()->getJoyStick(stickIndex); if (stick != nullptr) { JoyControlStickButton *button = stick->getDirectionButton(JoyControlStick::JoyStickDirections(buttonIndex)); if (button != nullptr) setStickButtonName(stickIndex, buttonIndex, button->getButtonName()); } } void InputDevice::updateSetDPadButtonNames(int dpadIndex, int buttonIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPad *dpad = getActiveSetJoystick()->getJoyDPad(dpadIndex); if (dpad != nullptr) { JoyDPadButton *button = dpad->getJoyButton(buttonIndex); if (button != nullptr) setDPadButtonName(dpadIndex, buttonIndex, button->getButtonName()); } } void InputDevice::updateSetVDPadButtonNames(int vdpadIndex, int buttonIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); VDPad *vdpad = getActiveSetJoystick()->getVDPad(vdpadIndex); if (vdpad != nullptr) { JoyDPadButton *button = vdpad->getJoyButton(buttonIndex); if (button != nullptr) setVDPadButtonName(vdpadIndex, buttonIndex, button->getButtonName()); } } void InputDevice::updateSetAxisNames(int axisIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxis *axis = getActiveSetJoystick()->getJoyAxis(axisIndex); if (axis != nullptr) setAxisName(axisIndex, axis->getAxisName()); } void InputDevice::updateSetStickNames(int stickIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStick *stick = getActiveSetJoystick()->getJoyStick(stickIndex); if (stick != nullptr) setStickName(stickIndex, stick->getStickName()); } void InputDevice::updateSetDPadNames(int dpadIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPad *dpad = getActiveSetJoystick()->getJoyDPad(dpadIndex); if (dpad != nullptr) setDPadName(dpadIndex, dpad->getDpadName()); } void InputDevice::updateSetVDPadNames(int vdpadIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); VDPad *vdpad = getActiveSetJoystick()->getVDPad(vdpadIndex); if (vdpad != nullptr) setVDPadName(vdpadIndex, vdpad->getDpadName()); } void InputDevice::resetButtonDownCount() { qInstallMessageHandler(MessageHandler::myMessageOutput); buttonDownCount = 0; emit released(joyNumber); } void InputDevice::enableSetConnections(SetJoystick *setstick) { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(setstick, &SetJoystick::setChangeActivated, this, &InputDevice::resetButtonDownCount); connect(setstick, &SetJoystick::setChangeActivated, this, &InputDevice::setActiveSetNumber); connect(setstick, &SetJoystick::setChangeActivated, this, &InputDevice::propogateSetChange); connect(setstick, &SetJoystick::setAssignmentButtonChanged, this, &InputDevice::changeSetButtonAssociation); connect(setstick, &SetJoystick::setAssignmentAxisChanged, this, &InputDevice::changeSetAxisButtonAssociation); connect(setstick, &SetJoystick::setAssignmentDPadChanged, this, &InputDevice::changeSetDPadButtonAssociation); connect(setstick, &SetJoystick::setAssignmentVDPadChanged, this, &InputDevice::changeSetVDPadButtonAssociation); connect(setstick, &SetJoystick::setAssignmentStickChanged, this, &InputDevice::changeSetStickButtonAssociation); connect(setstick, &SetJoystick::setAssignmentAxisThrottleChanged, this, &InputDevice::propogateSetAxisThrottleChange); connect(setstick, &SetJoystick::setButtonClick, this, &InputDevice::buttonDownEvent); connect(setstick, &SetJoystick::setButtonRelease, this, &InputDevice::buttonUpEvent); connect(setstick, &SetJoystick::setAxisButtonClick, this, &InputDevice::axisButtonDownEvent); connect(setstick, &SetJoystick::setAxisButtonRelease, this, &InputDevice::axisButtonUpEvent); connect(setstick, &SetJoystick::setAxisActivated, this, &InputDevice::axisActivatedEvent); connect(setstick, &SetJoystick::setAxisReleased, this, &InputDevice::axisReleasedEvent); connect(setstick, &SetJoystick::setDPadButtonClick, this, &InputDevice::dpadButtonDownEvent); connect(setstick, &SetJoystick::setDPadButtonRelease, this, &InputDevice::dpadButtonUpEvent); connect(setstick, &SetJoystick::setStickButtonClick, this, &InputDevice::stickButtonDownEvent); connect(setstick, &SetJoystick::setStickButtonRelease, this, &InputDevice::stickButtonUpEvent); connect(setstick, &SetJoystick::setButtonNameChange, this, &InputDevice::updateSetButtonNames); connect(setstick, &SetJoystick::setAxisButtonNameChange, this, &InputDevice::updateSetAxisButtonNames); connect(setstick, &SetJoystick::setStickButtonNameChange, this, &InputDevice::updateSetStickButtonNames); connect(setstick, &SetJoystick::setDPadButtonNameChange, this, &InputDevice::updateSetDPadButtonNames); connect(setstick, &SetJoystick::setVDPadButtonNameChange, this, &InputDevice::updateSetVDPadButtonNames); connect(setstick, &SetJoystick::setAxisNameChange, this, &InputDevice::updateSetAxisNames); connect(setstick, &SetJoystick::setStickNameChange, this, &InputDevice::updateSetStickNames); connect(setstick, &SetJoystick::setDPadNameChange, this, &InputDevice::updateSetDPadNames); connect(setstick, &SetJoystick::setVDPadNameChange, this, &InputDevice::updateSetVDPadNames); } void InputDevice::axisActivatedEvent(int setindex, int axisindex, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(setindex); emit rawAxisActivated(axisindex, value); } void InputDevice::axisReleasedEvent(int setindex, int axisindex, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(setindex); emit rawAxisReleased(axisindex, value); } void InputDevice::setIndex(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index >= 0) joyNumber = index; else joyNumber = 0; } void InputDevice::setDeviceKeyPressTime(int newPressTime) { qInstallMessageHandler(MessageHandler::myMessageOutput); keyPressTime = newPressTime; emit propertyUpdated(); } int InputDevice::getDeviceKeyPressTime() { qInstallMessageHandler(MessageHandler::myMessageOutput); return keyPressTime; } void InputDevice::profileEdited() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!deviceEdited) { deviceEdited = true; emit profileUpdated(); } } bool InputDevice::isDeviceEdited() { qInstallMessageHandler(MessageHandler::myMessageOutput); return deviceEdited; } void InputDevice::revertProfileEdited() { qInstallMessageHandler(MessageHandler::myMessageOutput); deviceEdited = false; } QString InputDevice::getStringIdentifier() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString identifier = QString(); // QString tempGUID = getGUIDString(); QString tempUniqueID = getUniqueIDString(); QString tempName = getSDLName(); if (!tempUniqueID.isEmpty()) identifier = tempUniqueID; // else if (!tempGUID.isEmpty()) identifier = tempGUID; else if (!tempName.isEmpty()) identifier = tempName; return identifier; } void InputDevice::establishPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(this, &InputDevice::propertyUpdated, this, &InputDevice::profileEdited); } void InputDevice::disconnectPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(this, &InputDevice::propertyUpdated, this, &InputDevice::profileEdited); } void InputDevice::setKeyRepeatStatus(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); keyRepeatEnabled = enabled; } void InputDevice::setKeyRepeatDelay(int delay) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((delay >= 250) && (delay <= 1000)) { keyRepeatDelay = delay; } } void InputDevice::setKeyRepeatRate(int rate) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((rate >= 20) && (rate <= 200)) { keyRepeatRate = rate; } } bool InputDevice::isKeyRepeatEnabled() { qInstallMessageHandler(MessageHandler::myMessageOutput); return keyRepeatEnabled; } int InputDevice::getKeyRepeatDelay() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempKeyRepeatDelay = GlobalVariables::InputDevice::DEFAULTKEYREPEATDELAY; if (keyRepeatDelay != 0) { tempKeyRepeatDelay = keyRepeatDelay; } return tempKeyRepeatDelay; } int InputDevice::getKeyRepeatRate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempKeyRepeatRate = GlobalVariables::InputDevice::DEFAULTKEYREPEATRATE; if (keyRepeatRate != 0) { tempKeyRepeatRate = keyRepeatRate; } return tempKeyRepeatRate; } void InputDevice::setProfileName(QString value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (profileName != value) { if (value.size() > 50) { value.truncate(47); value.append("..."); } profileName = value; emit propertyUpdated(); emit profileNameEdited(value); } } QString InputDevice::getProfileName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return profileName; } int InputDevice::getButtonDownCount() { qInstallMessageHandler(MessageHandler::myMessageOutput); return buttonDownCount; } QString InputDevice::getSDLPlatform() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = SDL_GetPlatform(); return temp; } /** * @brief Check if device is using the SDL Game Controller API * @return Status showing if device is using the Game Controller API */ bool InputDevice::isGameController() { qInstallMessageHandler(MessageHandler::myMessageOutput); return false; } bool InputDevice::hasCalibrationThrottle(int axisNum) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; if (getCali().contains(axisNum)) result = true; return result; } JoyAxis::ThrottleTypes InputDevice::getCalibrationThrottle(int axisNum) { qInstallMessageHandler(MessageHandler::myMessageOutput); return getCali().value(axisNum); } void InputDevice::setCalibrationThrottle(int axisNum, JoyAxis::ThrottleTypes throttle) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getCali().contains(axisNum)) { for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { getJoystick_sets().value(i)->setAxisThrottle(axisNum, throttle); } getCali().insert(axisNum, throttle); } } void InputDevice::setCalibrationStatus(int axisNum, JoyAxis::ThrottleTypes throttle) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getCali().contains(axisNum)) getCali().insert(axisNum, throttle); } void InputDevice::removeCalibrationStatus(int axisNum) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (getCali().contains(axisNum)) getCali().remove(axisNum); } void InputDevice::sendLoadProfileRequest(QString location) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!location.isEmpty()) emit requestProfileLoad(location); } AntiMicroSettings *InputDevice::getSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_settings; } bool InputDevice::isKnownController() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; if (isGameController()) { result = true; } else { m_settings->beginGroup("Mappings"); // if (m_settings->contains(getGUIDString())) result = true; // else if (m_settings->contains(QString("%1%2").arg(getGUIDString()).arg("Disabled"))) result = true; convertToUniqueMappSett(m_settings, getGUIDString(), getUniqueIDString()); convertToUniqueMappSett(m_settings, (QString("%1%2").arg(getGUIDString()).arg("Disabled")), (QString("%1%2").arg(getUniqueIDString()).arg("Disabled"))); if (m_settings->contains(getUniqueIDString())) result = true; else if (m_settings->contains(QString("%1%2").arg(getUniqueIDString()).arg("Disabled"))) result = true; m_settings->endGroup(); } return result; } void InputDevice::activatePossiblePendingEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); activatePossibleControlStickEvents(); activatePossibleAxisEvents(); activatePossibleDPadEvents(); activatePossibleVDPadEvents(); activatePossibleButtonEvents(); } void InputDevice::activatePossibleControlStickEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentSet = getActiveSetJoystick(); for (int i = 0; i < currentSet->getNumberSticks(); i++) { JoyControlStick *tempStick = currentSet->getJoyStick(i); if ((tempStick != nullptr) && tempStick->hasPendingEvent()) { tempStick->activatePendingEvent(); } } } void InputDevice::activatePossibleAxisEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentSet = getActiveSetJoystick(); for (int i = 0; i < currentSet->getNumberAxes(); i++) { JoyAxis *tempAxis = currentSet->getJoyAxis(i); if ((tempAxis != nullptr) && tempAxis->hasPendingEvent()) { tempAxis->activatePendingEvent(); } } } void InputDevice::activatePossibleDPadEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentSet = getActiveSetJoystick(); for (int i = 0; i < currentSet->getNumberHats(); i++) { JoyDPad *tempDPad = currentSet->getJoyDPad(i); if ((tempDPad != nullptr) && tempDPad->hasPendingEvent()) tempDPad->activatePendingEvent(); } } void InputDevice::activatePossibleVDPadEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentSet = getActiveSetJoystick(); for (int i = 0; i < currentSet->getNumberVDPads(); i++) { VDPad *tempVDPad = currentSet->getVDPad(i); if ((tempVDPad != nullptr) && tempVDPad->hasPendingEvent()) tempVDPad->activatePendingEvent(); } } void InputDevice::activatePossibleButtonEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentSet = getActiveSetJoystick(); for (int i = 0; i < currentSet->getNumberButtons(); i++) { JoyButton *tempButton = currentSet->getJoyButton(i); if ((tempButton != nullptr) && tempButton->hasPendingEvent()) tempButton->activatePendingEvent(); } } bool InputDevice::elementsHaveNames() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; SetJoystick *tempSet = getActiveSetJoystick(); for (int i = 0; i < getNumberButtons() && !result; i++) { JoyButton *button = tempSet->getJoyButton(i); if ((button != nullptr) && !button->getButtonName().isEmpty()) result = true; } for (int i = 0; (i < getNumberAxes()) && !result; i++) { JoyAxis *axis = tempSet->getJoyAxis(i); if (axis != nullptr) { if (!axis->getAxisName().isEmpty()) result = true; JoyAxisButton *naxisbutton = axis->getNAxisButton(); if (!naxisbutton->getButtonName().isEmpty()) result = true; JoyAxisButton *paxisbutton = axis->getPAxisButton(); if (!paxisbutton->getButtonName().isEmpty()) result = true; } } for (int i = 0; (i < getNumberSticks()) && !result; i++) { JoyControlStick *stick = tempSet->getJoyStick(i); if (stick != nullptr) { if (!stick->getStickName().isEmpty()) result = true; QHash *buttons = stick->getButtons(); QHashIterator iter(*buttons); while (iter.hasNext() && !result) { JoyControlStickButton *button = iter.next().value(); if (button && !button->getButtonName().isEmpty()) result = true; } } } for (int i = 0; (i < getNumberHats()) && !result; i++) { JoyDPad *dpad = tempSet->getJoyDPad(i); if (dpad != nullptr) { if (!dpad->getDpadName().isEmpty()) result = true; QHash *temp = dpad->getButtons(); QHashIterator iter(*temp); while (iter.hasNext() && !result) { JoyDPadButton *button = iter.next().value(); if (button && !button->getButtonName().isEmpty()) result = true; } } } for (int i = 0; (i < getNumberVDPads()) && !result; i++) { VDPad *vdpad = getActiveSetJoystick()->getVDPad(i); if (vdpad != nullptr) { if (!vdpad->getDpadName().isEmpty()) result = true; QHash *temp = vdpad->getButtons(); QHashIterator iter(*temp); while (iter.hasNext() && !result) { JoyDPadButton *button = iter.next().value(); if ((button != nullptr) && !button->getButtonName().isEmpty()) result = true; } } } return result; } /** * @brief Check if the GUID passed is considered empty. * @param GUID string * @return if GUID is considered empty. */ // bool InputDevice::isEmptyGUID(QString tempGUID) //{ // qInstallMessageHandler(MessageHandler::myMessageOutput); // bool result = false; // if (tempGUID.contains(GlobalVariables::InputDevice::emptyGUID)) result = true; // return result; //} bool InputDevice::isEmptyUniqueID(QString tempUniqueID) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; if (tempUniqueID.contains(GlobalVariables::InputDevice::emptyUniqueID)) result = true; return result; } /** * @brief Check if GUID passed matches the expected GUID for a device. * Needed for xinput GUID abstraction. * @param GUID string * @return if GUID is considered a match. */ // bool InputDevice::isRelevantGUID(QString tempGUID) //{ // qInstallMessageHandler(MessageHandler::myMessageOutput); // bool result = false; // if (tempGUID == getGUIDString()) result = true; // return result; //} bool InputDevice::isRelevantUniqueID(QString tempUniqueID) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; if (tempUniqueID == getUniqueIDString()) result = true; return result; } QString InputDevice::getRawGUIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getGUIDString(); } QString InputDevice::getRawVendorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getVendorString(); } QString InputDevice::getRawProductIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getProductIDString(); } QString InputDevice::getRawProductVersion() { return getProductVersion(); } QString InputDevice::getRawUniqueIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getUniqueIDString(); } void InputDevice::haltServices() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit requestWait(); } void InputDevice::finalRemoval() { qInstallMessageHandler(MessageHandler::myMessageOutput); this->closeSDLDevice(); this->deleteLater(); } void InputDevice::setRawAxisDeadZone(int deadZone) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((deadZone > 0) && (deadZone <= GlobalVariables::JoyAxis::AXISMAX)) { this->rawAxisDeadZone = deadZone; } else { this->rawAxisDeadZone = GlobalVariables::InputDevice::RAISEDDEADZONE; } } int InputDevice::getRawAxisDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return rawAxisDeadZone; } void InputDevice::rawAxisEvent(int index, int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit rawAxisMoved(index, value); } void InputDevice::convertToUniqueMappSett(QSettings *sett, QString gUIDmappGroupSett, QString uniqueIDGroupSett) { if (sett->contains(gUIDmappGroupSett)) { if (sett->contains(gUIDmappGroupSett) && (sett->value(gUIDmappGroupSett).toString().split(",").first() == getGUIDString())) { QStringList gg = sett->value(gUIDmappGroupSett).toString().split(","); gg.removeFirst(); gg.prepend(uniqueIDGroupSett); sett->setValue(uniqueIDGroupSett, sett->value(gg.join(","))); sett->remove(gUIDmappGroupSett); } else { sett->setValue(uniqueIDGroupSett, sett->value(gUIDmappGroupSett)); sett->remove(gUIDmappGroupSett); } } } QHash &InputDevice::getJoystick_sets() { return joystick_sets; } QHash &InputDevice::getCali() { return cali; } SDL_JoystickID *InputDevice::getJoystickID() { return &joystickID; } QList &InputDevice::getButtonstatesLocal() { return buttonstates; } QList &InputDevice::getAxesstatesLocal() { return axesstates; } QList &InputDevice::getDpadstatesLocal() { return dpadstates; } SDL_Joystick *InputDevice::getJoyHandle() const { return m_joyhandle; } AntiMicroX-antimicrox-2888bf6/src/inputdevice.h000066400000000000000000000253311377703515000215460ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef INPUTDEVICE_H #define INPUTDEVICE_H #include "setjoystick.h" #include class AntiMicroSettings; class SetJoystick; class QXmlStreamReader; class QXmlStreamWriter; class QSettings; class InputDevice : public QObject { Q_OBJECT public: explicit InputDevice(SDL_Joystick *joystick, int deviceIndex, AntiMicroSettings *settings, QObject *parent = nullptr); virtual ~InputDevice(); virtual int getNumberButtons(); virtual int getNumberAxes(); virtual int getNumberHats(); virtual int getNumberSticks(); virtual int getNumberVDPads(); int getJoyNumber(); int getRealJoyNumber(); int getActiveSetNumber(); SetJoystick *getActiveSetJoystick(); SetJoystick *getSetJoystick(int index); void removeControlStick(int index); bool isActive(); int getButtonDownCount(); virtual QString getXmlName() = 0; virtual QString getName() = 0; virtual QString getSDLName() = 0; // GUID only available on SDL 2. virtual QString getGUIDString() = 0; virtual QString getUniqueIDString() = 0; virtual QString getVendorString() = 0; virtual QString getProductIDString() = 0; virtual QString getProductVersion() = 0; virtual QString getRawGUIDString(); virtual QString getRawVendorString(); virtual QString getRawProductIDString(); virtual QString getRawProductVersion(); virtual QString getRawUniqueIDString(); virtual void setCounterUniques(int counter) = 0; virtual QString getStringIdentifier(); virtual void closeSDLDevice() = 0; virtual SDL_JoystickID getSDLJoystickID() = 0; QString getSDLPlatform(); virtual bool isGameController(); virtual bool isKnownController(); void setButtonName(int index, QString tempName); // InputDeviceXml class void setAxisButtonName(int axisIndex, int buttonIndex, QString tempName); // InputDeviceXml class void setStickButtonName(int stickIndex, int buttonIndex, QString tempName); // InputDeviceXml class void setDPadButtonName(int dpadIndex, int buttonIndex, QString tempName); // InputDeviceXml class void setVDPadButtonName(int vdpadIndex, int buttonIndex, QString tempName); // InputDeviceXml class void setAxisName(int axisIndex, QString tempName); // InputDeviceAxis class void setStickName(int stickIndex, QString tempName); // InputDeviceStick class void setDPadName(int dpadIndex, QString tempName); // InputDeviceHat class void setVDPadName(int vdpadIndex, QString tempName); // InputDeviceVDPad class virtual int getNumberRawButtons() = 0; virtual int getNumberRawAxes() = 0; virtual int getNumberRawHats() = 0; int getDeviceKeyPressTime(); // unsigned void setIndex(int index); bool isDeviceEdited(); void revertProfileEdited(); void setKeyRepeatStatus(bool enabled); void setKeyRepeatDelay(int delay); void setKeyRepeatRate(int rate); bool isKeyRepeatEnabled(); int getKeyRepeatDelay(); int getKeyRepeatRate(); QString getProfileName(); bool hasCalibrationThrottle(int axisNum); JoyAxis::ThrottleTypes getCalibrationThrottle(int axisNum); void setCalibrationThrottle(int axisNum, JoyAxis::ThrottleTypes throttle); void setCalibrationStatus(int axisNum, JoyAxis::ThrottleTypes throttle); void removeCalibrationStatus(int axisNum); void sendLoadProfileRequest(QString location); AntiMicroSettings *getSettings(); void activatePossiblePendingEvents(); void activatePossibleControlStickEvents(); // InputDeviceStick class void activatePossibleAxisEvents(); // InputDeviceAxis class void activatePossibleDPadEvents(); // InputDeviceHat class void activatePossibleVDPadEvents(); // InputDeviceVDPad class void activatePossibleButtonEvents(); // InputDeviceButton class void convertToUniqueMappSett(QSettings *sett, QString gUIDmappGroupSett, QString uniqueIDGroupSett); // bool isEmptyGUID(QString tempGUID); bool isEmptyUniqueID(QString tempUniqueID); // bool isRelevantGUID(QString tempGUID); bool isRelevantUniqueID(QString tempUniqueID); void setRawAxisDeadZone(int deadZone); // InputDeviceAxis class int getRawAxisDeadZone(); // InputDeviceAxis class void rawAxisEvent(int index, int value); // InputDeviceAxis class bool elementsHaveNames(); QHash &getJoystick_sets(); SDL_Joystick *getJoyHandle() const; protected: void enableSetConnections(SetJoystick *setstick); QHash &getCali(); SDL_JoystickID *getJoystickID(); int rawAxisDeadZone; int keyPressTime; // unsigned QString profileName; signals: void setChangeActivated(int index); void setAxisThrottleActivated(int index); // InputDeviceAxis class void clicked(int index); void released(int index); void rawButtonClick(int index); // InputDeviceButton class void rawButtonRelease(int index); // InputDeviceButton class void rawAxisButtonClick(int axis, int buttonindex); // InputDeviceAxisBtn class void rawAxisButtonRelease(int axis, int buttonindex); // InputDeviceAxisBtn class void rawDPadButtonClick(int dpad, int buttonindex); // InputDeviceHat class void rawDPadButtonRelease(int dpad, int buttonindex); // InputDeviceHat class void rawAxisActivated(int axis, int value); // InputDeviceAxis class void rawAxisReleased(int axis, int value); // InputDeviceAxis class void rawAxisMoved(int axis, int value); // InputDeviceAxis class void profileUpdated(); void propertyUpdated(); void profileNameEdited(QString text); void requestProfileLoad(QString location); void requestWait(); public slots: void reset(); void transferReset(); void reInitButtons(); void resetButtonDownCount(); void setActiveSetNumber(int index); void changeSetButtonAssociation(int button_index, int originset, int newset, int mode); // InputDeviceButton class void changeSetAxisButtonAssociation(int button_index, int axis_index, int originset, int newset, int mode); // InputDeviceAxisBtn class void changeSetStickButtonAssociation(int button_index, int stick_index, int originset, int newset, int mode); // InputDeviceStick class void changeSetDPadButtonAssociation(int button_index, int dpad_index, int originset, int newset, int mode); // InputDeviceHat class void changeSetVDPadButtonAssociation(int button_index, int dpad_index, int originset, int newset, int mode); // InputDeviceVDPad class void setDeviceKeyPressTime(int newPressTime); // .., unsigned void profileEdited(); void setProfileName(QString value); void haltServices(); void finalRemoval(); virtual void buttonClickEvent(int buttonindex); // InputDeviceButton class virtual void buttonReleaseEvent(int buttonindex); // InputDeviceButton class virtual void dpadButtonClickEvent(int buttonindex); // InputDeviceHat class virtual void dpadButtonReleaseEvent(int buttonindex); // InputDeviceHat class void establishPropertyUpdatedConnection(); void disconnectPropertyUpdatedConnection(); protected slots: void propogateSetChange(int index); void propogateSetAxisThrottleChange(int index, int originset); void buttonDownEvent(int setindex, int buttonindex); // InputDeviceButton class void buttonUpEvent(int setindex, int buttonindex); // InputDeviceButton class virtual void axisActivatedEvent(int setindex, int axisindex, int value); // InputDeviceAxis class virtual void axisReleasedEvent(int setindex, int axisindex, int value); // InputDeviceAxis class virtual void axisButtonDownEvent(int setindex, int axisindex, int buttonindex); // InputDeviceAxisBtn class virtual void axisButtonUpEvent(int setindex, int axisindex, int buttonindex); // InputDeviceAxisBtn class virtual void dpadButtonDownEvent(int setindex, int dpadindex, int buttonindex); // InputDeviceHat class virtual void dpadButtonUpEvent(int setindex, int dpadindex, int buttonindex); // InputDeviceHat class virtual void stickButtonDownEvent(int setindex, int stickindex, int buttonindex); // InputDeviceStick class virtual void stickButtonUpEvent(int setindex, int stickindex, int buttonindex); // InputDeviceStick class void updateSetButtonNames(int index); // InputDeviceButton class void updateSetAxisButtonNames(int axisIndex, int buttonIndex); // InputDeviceAxis class void updateSetStickButtonNames(int stickIndex, int buttonIndex); // InputDeviceStick class void updateSetDPadButtonNames(int dpadIndex, int buttonIndex); // InputDeviceHat class void updateSetVDPadButtonNames(int vdpadIndex, int buttonIndex); // InputDeviceVDPad class void updateSetAxisNames(int axisIndex); // InputDeviceAxis class void updateSetStickNames(int stickIndex); // InputDeviceStick class void updateSetDPadNames(int dpadIndex); // InputDeviceHat class void updateSetVDPadNames(int vdpadIndex); // InputDeviceVDPad class private: QList &getButtonstatesLocal(); QList &getAxesstatesLocal(); QList &getDpadstatesLocal(); SDL_Joystick *m_joyhandle; QHash joystick_sets; QHash cali; AntiMicroSettings *m_settings; int active_set; int joyNumber; int buttonDownCount; SDL_JoystickID joystickID; bool deviceEdited; bool keyRepeatEnabled; int keyRepeatDelay; int keyRepeatRate; QList buttonstates; QList axesstates; QList dpadstates; }; Q_DECLARE_METATYPE(InputDevice *) Q_DECLARE_METATYPE(SDL_JoystickID) #endif // INPUTDEVICE_H AntiMicroX-antimicrox-2888bf6/src/inputdevicebitarraystatus.cpp000066400000000000000000000107671377703515000251120ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "inputdevicebitarraystatus.h" #include "inputdevice.h" #include "joybutton.h" #include "joydpad.h" #include "joystick.h" #include "messagehandler.h" #include "setjoystick.h" #include InputDeviceBitArrayStatus::InputDeviceBitArrayStatus(InputDevice *device, bool readCurrent, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < device->getNumberRawAxes(); i++) { SetJoystick *currentSet = device->getActiveSetJoystick(); JoyAxis *axis = currentSet->getJoyAxis(i); if ((axis != nullptr) && readCurrent) { axesStatus.append(!axis->inDeadZone(axis->getCurrentRawValue()) ? true : false); } else { axesStatus.append(false); } } for (int i = 0; i < device->getNumberRawHats(); i++) { SetJoystick *currentSet = device->getActiveSetJoystick(); JoyDPad *dpad = currentSet->getJoyDPad(i); if ((dpad != nullptr) && readCurrent) { hatButtonStatus.append(dpad->getCurrentDirection() != JoyDPadButton::DpadCentered ? true : false); } else { hatButtonStatus.append(false); } } getButtonStatusLocal().resize(device->getNumberRawButtons()); getButtonStatusLocal().fill(0); for (int i = 0; i < device->getNumberRawButtons(); i++) { SetJoystick *currentSet = device->getActiveSetJoystick(); JoyButton *button = currentSet->getJoyButton(i); if ((button != nullptr) && readCurrent) { getButtonStatusLocal().setBit(i, button->getButtonState()); } } } void InputDeviceBitArrayStatus::changeAxesStatus(int axisIndex, bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((axisIndex >= 0) && (axisIndex <= axesStatus.size())) { axesStatus.replace(axisIndex, value); } } void InputDeviceBitArrayStatus::changeButtonStatus(int buttonIndex, bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((buttonIndex >= 0) && (buttonIndex <= getButtonStatusLocal().size())) { getButtonStatusLocal().setBit(buttonIndex, value); } } void InputDeviceBitArrayStatus::changeHatStatus(int hatIndex, bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((hatIndex >= 0) && (hatIndex <= hatButtonStatus.size())) { hatButtonStatus.replace(hatIndex, value); } } QBitArray InputDeviceBitArrayStatus::generateFinalBitArray() { qInstallMessageHandler(MessageHandler::myMessageOutput); int totalArraySize = 0; totalArraySize = axesStatus.size() + hatButtonStatus.size() + getButtonStatusLocal().size(); QBitArray aggregateBitArray(totalArraySize, false); int currentBit = 0; for (int i = 0; i < axesStatus.size(); i++) { aggregateBitArray.setBit(currentBit, axesStatus.at(i)); currentBit++; } for (int i = 0; i < hatButtonStatus.size(); i++) { aggregateBitArray.setBit(currentBit, hatButtonStatus.at(i)); currentBit++; } for (int i = 0; i < getButtonStatusLocal().size(); i++) { aggregateBitArray.setBit(currentBit, getButtonStatusLocal().at(i)); currentBit++; } return aggregateBitArray; } void InputDeviceBitArrayStatus::clearStatusValues() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < axesStatus.size(); i++) axesStatus.replace(i, false); for (int i = 0; i < hatButtonStatus.size(); i++) hatButtonStatus.replace(i, false); getButtonStatusLocal().fill(false); } QBitArray &InputDeviceBitArrayStatus::getButtonStatusLocal() { return buttonStatus; } AntiMicroX-antimicrox-2888bf6/src/inputdevicebitarraystatus.h000066400000000000000000000030401377703515000245410ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef INPUTDEVICESTATUSEVENT_H #define INPUTDEVICESTATUSEVENT_H #include #include #include class InputDevice; class InputDeviceBitArrayStatus : public QObject { Q_OBJECT public: explicit InputDeviceBitArrayStatus(InputDevice *device, bool readCurrent = true, QObject *parent = nullptr); void changeAxesStatus(int axisIndex, bool value); void changeButtonStatus(int buttonIndex, bool value); void changeHatStatus(int hatIndex, bool value); QBitArray generateFinalBitArray(); void clearStatusValues(); private: QBitArray &getButtonStatusLocal(); QList axesStatus; QList hatButtonStatus; QBitArray buttonStatus; }; #endif // INPUTDEVICESTATUSEVENT_H AntiMicroX-antimicrox-2888bf6/src/joyaxis.cpp000066400000000000000000000730641377703515000212560ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joyaxis.h" #include "event.h" #include "globalvariables.h" #include "inputdevice.h" #include "joyaxis.h" #include "joycontrolstick.h" #include "messagehandler.h" #include "setjoystick.h" #include #include #include #include #include const JoyAxis::ThrottleTypes JoyAxis::DEFAULTTHROTTLE = JoyAxis::NormalThrottle; JoyAxis::JoyAxis(int index, int originset, SetJoystick *parentSet, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_stick = nullptr; lastKnownThottledValue = 0; lastKnownRawValue = 0; axis_max_cal = -1; axis_min_cal = -1; axis_center_cal = -1; currentRawValue = 0; m_originset = originset; m_parentSet = parentSet; naxisbutton = new JoyAxisButton(this, 0, originset, parentSet, this); paxisbutton = new JoyAxisButton(this, 1, originset, parentSet, this); resetPrivateVars(); m_index = index; } JoyAxis::~JoyAxis() { qInstallMessageHandler(MessageHandler::myMessageOutput); resetPrivateVars(); } void JoyAxis::queuePendingEvent(int value, bool ignoresets, bool updateLastValues) { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingEvent = false; pendingValue = 0; pendingIgnoreSets = false; if (m_stick != nullptr) { stickPassEvent(value, ignoresets, updateLastValues); } else { pendingEvent = true; pendingValue = value; pendingIgnoreSets = ignoresets; } } void JoyAxis::activatePendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (pendingEvent) { joyEvent(pendingValue, pendingIgnoreSets); pendingEvent = false; pendingValue = false; pendingIgnoreSets = false; } } bool JoyAxis::hasPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); return pendingEvent; } void JoyAxis::clearPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingEvent = false; pendingValue = false; pendingIgnoreSets = false; } void JoyAxis::stickPassEvent(int value, bool ignoresets, bool updateLastValues) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_stick != nullptr) { if (updateLastValues) { lastKnownThottledValue = currentThrottledValue; lastKnownRawValue = currentRawValue; } setCurrentRawValue(value); bool safezone = !inDeadZone(currentRawValue); currentThrottledValue = calculateThrottledValue(value); if (safezone && !isActive) { isActive = eventActive = true; emit active(value); } else if (!safezone && isActive) { isActive = eventActive = false; emit released(value); } if (!ignoresets) m_stick->queueJoyEvent(ignoresets); else m_stick->joyEvent(ignoresets); emit moved(currentRawValue); } } void JoyAxis::joyEvent(int value, bool ignoresets, bool updateLastValues) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((m_stick != nullptr) && !pendingEvent) { stickPassEvent(value, ignoresets, updateLastValues); } else { if (updateLastValues) { lastKnownThottledValue = currentThrottledValue; lastKnownRawValue = currentRawValue; } setCurrentRawValue(value); bool safezone = !inDeadZone(currentRawValue); currentThrottledValue = calculateThrottledValue(value); // If in joystick mode and this is the first detected event, // use the current value as the axis center point. If the value // is below -30,000 then consider it a trigger. InputDevice *device = m_parentSet->getInputDevice(); if (!device->isGameController() && !device->hasCalibrationThrottle(m_index)) { performCalibration(currentRawValue); safezone = !inDeadZone(currentRawValue); currentThrottledValue = calculateThrottledValue(value); } if (safezone && !isActive) { isActive = eventActive = true; emit active(value); createDeskEvent(ignoresets); } else if (!safezone && isActive) { isActive = eventActive = false; emit released(value); createDeskEvent(ignoresets); } else if (isActive) { createDeskEvent(ignoresets); } } emit moved(currentRawValue); } bool JoyAxis::inDeadZone(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; int temp = calculateThrottledValue(value); if (abs(temp) <= deadZone) { qDebug() << "Value of throttle is in (less than) dead zone: " << abs(temp) << " <= " << deadZone; result = true; } else { qDebug() << "Value of throttle is not in (greater than) dead zone: " << abs(temp) << " > " << deadZone; } return result; } QString JoyAxis::getName(bool forceFullFormat, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = getPartialName(forceFullFormat, displayNames); label.append(": "); if (throttle == static_cast(NormalThrottle)) { label.append("-"); if (!naxisbutton->getActionName().isEmpty() && displayNames) { label.append(naxisbutton->getActionName()); } else { label.append(naxisbutton->getCalculatedActiveZoneSummary()); } label.append(" | +"); if (!paxisbutton->getActionName().isEmpty() && displayNames) { label.append(paxisbutton->getActionName()); } else { label.append(paxisbutton->getCalculatedActiveZoneSummary()); } } else if ((throttle == static_cast(PositiveThrottle)) || (throttle == static_cast(PositiveHalfThrottle))) { label.append("+"); if (!paxisbutton->getActionName().isEmpty() && displayNames) { label.append(paxisbutton->getActionName()); } else { label.append(paxisbutton->getCalculatedActiveZoneSummary()); } } else if ((throttle == static_cast(NegativeThrottle)) || (throttle == static_cast(NegativeHalfThrottle))) { label.append("-"); if (!naxisbutton->getActionName().isEmpty() && displayNames) { label.append(naxisbutton->getActionName()); } else { label.append(naxisbutton->getCalculatedActiveZoneSummary()); } } return label; } int JoyAxis::getRealJoyIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index + 1; } int JoyAxis::getCurrentThrottledValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentThrottledValue; } void JoyAxis::updateCurrentThrottledValue(int newValue) { currentThrottledValue = newValue; } int JoyAxis::calculateThrottledValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "Throtted value at start of function is: " << value; int temp = value; switch (throttle) { case -2: qDebug() << "It's a negative half throttle"; value = (value <= 0) ? value : -value; temp = value; break; case -1: qDebug() << "It's a negative throttle"; temp = (value + getAxisMinCal()) / 2; break; case 1: qDebug() << "It's a positive throttle"; temp = (value + getAxisMaxCal()) / 2; break; case 2: qDebug() << "It's a positive half throttle"; value = (value >= 0) ? value : -value; temp = value; break; } qDebug() << "Calculated value of throttle is: " << temp; return temp; } void JoyAxis::setIndex(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_index = index; } int JoyAxis::getIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index; } void JoyAxis::createDeskEvent(bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *eventbutton = nullptr; if (currentThrottledValue > deadZone) eventbutton = paxisbutton; else if (currentThrottledValue < -deadZone) eventbutton = naxisbutton; if ((eventbutton != nullptr) && !activeButton) { // There is no active button. Call joyEvent and set current // button as active button eventbutton->joyEvent(eventActive, ignoresets); activeButton = eventbutton; } else if ((eventbutton == nullptr) && (activeButton != nullptr)) { // Currently in deadzone. Disable currently active button. activeButton->joyEvent(eventActive, ignoresets); activeButton = nullptr; } else if ((eventbutton != nullptr) && (activeButton != nullptr) && (eventbutton == activeButton)) { // Button is currently active. Just pass current value eventbutton->joyEvent(eventActive, ignoresets); } else if ((eventbutton != nullptr) && (activeButton != nullptr) && (eventbutton != activeButton)) { // Deadzone skipped. Button for new event is not the currently // active button. Disable the active button before enabling // the new button activeButton->joyEvent(!eventActive, ignoresets); eventbutton->joyEvent(eventActive, ignoresets); activeButton = eventbutton; } } void JoyAxis::setDeadZone(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); deadZone = abs(value); emit propertyUpdated(); } int JoyAxis::getDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return deadZone; } void JoyAxis::setMaxZoneValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); value = abs(value); if (value >= getAxisMaxCal()) { maxZoneValue = getAxisMaxCal(); emit propertyUpdated(); } else { maxZoneValue = value; emit propertyUpdated(); } } int JoyAxis::getMaxZoneValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return maxZoneValue; } /** * @brief Set throttle value for axis. * @param Current value for axis. */ void JoyAxis::setThrottle(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "Value of throttle for axis in setThrottle is: " << value; if ((value >= static_cast(JoyAxis::NegativeHalfThrottle)) && (value <= static_cast(JoyAxis::PositiveHalfThrottle))) { if (value != throttle) { qDebug() << "Throttle value for variable \"throttle\" has been set: " << value; throttle = value; adjustRange(); emit throttleChanged(); emit propertyUpdated(); } } } /** * @brief Set the initial calibrated throttle based on the first event * passed by SDL. * @param Current value for axis. */ void JoyAxis::setInitialThrottle(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= static_cast(JoyAxis::NegativeHalfThrottle)) && (value <= static_cast(JoyAxis::PositiveHalfThrottle)) && (value != throttle)) { throttle = value; adjustRange(); emit throttleChanged(); } } int JoyAxis::getThrottle() { qInstallMessageHandler(MessageHandler::myMessageOutput); return throttle; } void JoyAxis::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); resetPrivateVars(); } void JoyAxis::resetPrivateVars() { deadZone = GlobalVariables::JoyAxis::AXISDEADZONE; isActive = false; eventActive = false; maxZoneValue = GlobalVariables::JoyAxis::AXISMAXZONE; throttle = this->DEFAULTTHROTTLE; paxisbutton->reset(); naxisbutton->reset(); activeButton = nullptr; lastKnownThottledValue = 0; lastKnownRawValue = 0; adjustRange(); setCurrentRawValue(currentThrottledDeadValue); currentThrottledValue = calculateThrottledValue(currentRawValue); axisName.clear(); pendingEvent = false; pendingValue = currentRawValue; pendingIgnoreSets = false; } void JoyAxis::reset(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); reset(); m_index = index; } JoyAxisButton *JoyAxis::getPAxisButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); return paxisbutton; } JoyAxisButton *JoyAxis::getNAxisButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); return naxisbutton; } int JoyAxis::getCurrentRawValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentRawValue; } void JoyAxis::adjustRange() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (throttle == static_cast(JoyAxis::NegativeThrottle)) { currentThrottledDeadValue = getAxisMaxCal(); } else if ((throttle == static_cast(JoyAxis::NormalThrottle)) || (throttle == static_cast(JoyAxis::PositiveHalfThrottle)) || (throttle == static_cast(JoyAxis::NegativeHalfThrottle))) { currentThrottledDeadValue = 0; } else if (throttle == static_cast(JoyAxis::PositiveThrottle)) { currentThrottledDeadValue = getAxisMinCal(); } currentThrottledValue = calculateThrottledValue(currentRawValue); } int JoyAxis::getCurrentThrottledDeadValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentThrottledDeadValue; } double JoyAxis::getDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getDistanceFromDeadZone(currentThrottledValue); } double JoyAxis::getDistanceFromDeadZone(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); double distance = 0.0; if (value >= deadZone) { distance = static_cast(value - deadZone) / (maxZoneValue - deadZone); } else if (value <= -deadZone) { distance = static_cast(value + deadZone) / ((-maxZoneValue) + deadZone); } return qBound(0.0, distance, 1.0); } /** * @brief Get the current value for an axis in either direction converted to * the range of -1.0 to 1.0. * @param Current interger value of the axis * @return Axis value in the range of -1.0 to 1.0 */ double JoyAxis::getRawDistance(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); return qBound(-1.0, static_cast(value) / maxZoneValue, 1.0); } void JoyAxis::propogateThrottleChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit throttleChangePropogated(m_index); } int JoyAxis::getCurrentlyAssignedSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_originset; } void JoyAxis::setControlStick(JoyControlStick *stick) { qInstallMessageHandler(MessageHandler::myMessageOutput); removeVDPads(); removeControlStick(); m_stick = stick; emit propertyUpdated(); } bool JoyAxis::isPartControlStick() { qInstallMessageHandler(MessageHandler::myMessageOutput); return (m_stick != nullptr); } JoyControlStick *JoyAxis::getControlStick() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_stick; } void JoyAxis::removeControlStick(bool performRelease) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_stick != nullptr) { if (performRelease) m_stick->releaseButtonEvents(); m_stick = nullptr; // emit propertyUpdated(); } } bool JoyAxis::hasControlOfButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool value = true; if (paxisbutton->isPartVDPad() || naxisbutton->isPartVDPad()) { value = false; } return value; } void JoyAxis::removeVDPads() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (paxisbutton->isPartVDPad()) { paxisbutton->joyEvent(false, true); paxisbutton->removeVDPad(); } if (naxisbutton->isPartVDPad()) { naxisbutton->joyEvent(false, true); naxisbutton->removeVDPad(); } } bool JoyAxis::isDefault() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool value = true; value = value && (deadZone == getDefaultDeadZone()); value = value && (maxZoneValue == getDefaultMaxZone()); value = value && (paxisbutton->isDefault()); value = value && (naxisbutton->isDefault()); return value; } /* Use this method to keep currentRawValue in the expected range. * SDL has a minimum axis value of -32768 which should be ignored to * ensure that JoyControlStick will not encounter overflow problems * on a 32 bit machine. */ void JoyAxis::setCurrentRawValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= getAxisMinCal()) && (value <= getAxisMaxCal())) { qDebug() << "Raw value is less than " << getAxisMaxCal() << " and greather than " << getAxisMinCal(); currentRawValue = value; } else if (value > getAxisMaxCal()) { qDebug() << "Raw value is greather than " << getAxisMaxCal(); currentRawValue = getAxisMaxCal(); } else if (value < getAxisMinCal()) { qDebug() << "Raw value is less than " << getAxisMinCal(); currentRawValue = getAxisMinCal(); } qDebug() << "Raw value for axis is: " << currentRawValue; } void JoyAxis::setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setMouseMode(mode); naxisbutton->setMouseMode(mode); } bool JoyAxis::hasSameButtonsMouseMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; if (paxisbutton->getMouseMode() != naxisbutton->getMouseMode()) { result = false; } return result; } JoyButton::JoyMouseMovementMode JoyAxis::getButtonsPresetMouseMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseMovementMode resultMode = JoyButton::MouseCursor; if (paxisbutton->getMouseMode() == naxisbutton->getMouseMode()) resultMode = paxisbutton->getMouseMode(); return resultMode; } void JoyAxis::setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setMouseCurve(mouseCurve); naxisbutton->setMouseCurve(mouseCurve); } bool JoyAxis::hasSameButtonsMouseCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; if (paxisbutton->getMouseCurve() != naxisbutton->getMouseCurve()) { result = false; } return result; } JoyButton::JoyMouseCurve JoyAxis::getButtonsPresetMouseCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve resultCurve = JoyButton::LinearCurve; if (paxisbutton->getMouseCurve() == naxisbutton->getMouseCurve()) { resultCurve = paxisbutton->getMouseCurve(); } return resultCurve; } void JoyAxis::setButtonsSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setSpringWidth(value); naxisbutton->setSpringWidth(value); } void JoyAxis::setButtonsSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setSpringHeight(value); naxisbutton->setSpringHeight(value); } int JoyAxis::getButtonsPresetSpringWidth() { qInstallMessageHandler(MessageHandler::myMessageOutput); int presetSpringWidth = 0; if (paxisbutton->getSpringWidth() == naxisbutton->getSpringWidth()) presetSpringWidth = paxisbutton->getSpringWidth(); return presetSpringWidth; } int JoyAxis::getButtonsPresetSpringHeight() { qInstallMessageHandler(MessageHandler::myMessageOutput); int presetSpringHeight = 0; if (paxisbutton->getSpringHeight() == naxisbutton->getSpringHeight()) presetSpringHeight = paxisbutton->getSpringHeight(); return presetSpringHeight; } void JoyAxis::setButtonsSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setSensitivity(value); naxisbutton->setSensitivity(value); } double JoyAxis::getButtonsPresetSensitivity() { qInstallMessageHandler(MessageHandler::myMessageOutput); double presetSensitivity = 1.0; if (qFuzzyCompare(paxisbutton->getSensitivity(), naxisbutton->getSensitivity())) presetSensitivity = paxisbutton->getSensitivity(); return presetSensitivity; } JoyAxisButton *JoyAxis::getAxisButtonByValue(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *eventbutton = nullptr; int throttledValue = calculateThrottledValue(value); qDebug() << "throttledValue in getAxisButtonByValue is: " << throttledValue; if (throttledValue > deadZone) { qDebug() << "throtted value is positive"; eventbutton = paxisbutton; } else if (throttledValue < (-deadZone)) { qDebug() << "throtted value is negative"; eventbutton = naxisbutton; } return eventbutton; } void JoyAxis::setAxisName(QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((tempName.length() <= 20) && (tempName != axisName)) { axisName = tempName; emit axisNameChanged(); emit propertyUpdated(); } } QString JoyAxis::getAxisName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return axisName; } void JoyAxis::setButtonsWheelSpeedX(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setWheelSpeed(value, 'X'); naxisbutton->setWheelSpeed(value, 'X'); } void JoyAxis::setButtonsWheelSpeedY(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setWheelSpeed(value, 'Y'); naxisbutton->setWheelSpeed(value, 'Y'); } void JoyAxis::setDefaultAxisName(QString tempname) { qInstallMessageHandler(MessageHandler::myMessageOutput); defaultAxisName = tempname; } QString JoyAxis::getDefaultAxisName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return defaultAxisName; } QString JoyAxis::getPartialName(bool forceFullFormat, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); if (!axisName.isEmpty() && displayNames) { if (forceFullFormat) { label.append(tr("Axis")).append(" "); } label.append(axisName); } else if (!defaultAxisName.isEmpty()) { if (forceFullFormat) { label.append(tr("Axis")).append(" "); } label.append(defaultAxisName); } else { label.append(tr("Axis")).append(" "); label.append(QString::number(getRealJoyIndex())); } return label; } QString JoyAxis::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyAxis::xmlName; } int JoyAxis::getDefaultDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyAxis::AXISDEADZONE; } int JoyAxis::getDefaultMaxZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyAxis::AXISMAXZONE; } JoyAxis::ThrottleTypes JoyAxis::getDefaultThrottle() { qInstallMessageHandler(MessageHandler::myMessageOutput); return this->DEFAULTTHROTTLE; } SetJoystick *JoyAxis::getParentSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_parentSet; } void JoyAxis::establishPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(this, &JoyAxis::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); } void JoyAxis::disconnectPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(this, &JoyAxis::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); } void JoyAxis::setButtonsSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setSpringRelativeStatus(value); naxisbutton->setSpringRelativeStatus(value); } bool JoyAxis::isRelativeSpring() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool relative = false; if (paxisbutton->isRelativeSpring() == naxisbutton->isRelativeSpring()) relative = paxisbutton->isRelativeSpring(); return relative; } void JoyAxis::performCalibration(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); InputDevice *device = m_parentSet->getInputDevice(); if (value <= -30000) { // Assume axis is a trigger. Set default throttle to Positive. device->setCalibrationThrottle(m_index, PositiveThrottle); } else { // Ensure that default throttle is used when a device is reset. device->setCalibrationThrottle(m_index, static_cast(throttle)); } } void JoyAxis::copyAssignments(JoyAxis *destAxis) { qInstallMessageHandler(MessageHandler::myMessageOutput); destAxis->reset(); destAxis->deadZone = deadZone; destAxis->maxZoneValue = maxZoneValue; destAxis->axisName = axisName; paxisbutton->copyAssignments(destAxis->paxisbutton); naxisbutton->copyAssignments(destAxis->naxisbutton); if (!destAxis->isDefault()) emit propertyUpdated(); } void JoyAxis::setButtonsEasingDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setEasingDuration(value); naxisbutton->setEasingDuration(value); } double JoyAxis::getButtonsEasingDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTEASINGDURATION; if (qFuzzyCompare(paxisbutton->getEasingDuration(), naxisbutton->getEasingDuration())) { result = paxisbutton->getEasingDuration(); } return result; } int JoyAxis::getLastKnownThrottleValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return lastKnownThottledValue; } int JoyAxis::getLastKnownRawValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return lastKnownRawValue; } /** * @brief Determine an appropriate release value for an axis depending * on the current throttle setting being used. * @return Release value for an axis */ int JoyAxis::getProperReleaseValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); // Handles NormalThrottle case int value = 0; if (throttle == static_cast(NegativeHalfThrottle)) { value = 0; } else if (throttle == static_cast(NegativeThrottle)) { value = getAxisMaxCal(); } else if (throttle == static_cast(PositiveThrottle)) { value = getAxisMinCal(); } else if (throttle == static_cast(PositiveHalfThrottle)) { value = 0; } return value; } void JoyAxis::setExtraAccelerationCurve(JoyButton::JoyExtraAccelerationCurve curve) { qInstallMessageHandler(MessageHandler::myMessageOutput); paxisbutton->setExtraAccelerationCurve(curve); naxisbutton->setExtraAccelerationCurve(curve); } JoyButton::JoyExtraAccelerationCurve JoyAxis::getExtraAccelerationCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve result = JoyButton::LinearAccelCurve; if (paxisbutton->getExtraAccelerationCurve() == naxisbutton->getExtraAccelerationCurve()) { result = paxisbutton->getExtraAccelerationCurve(); } return result; } void JoyAxis::copyRawValues(JoyAxis *srcAxis) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->lastKnownRawValue = srcAxis->lastKnownRawValue; this->currentRawValue = srcAxis->currentRawValue; } void JoyAxis::copyThrottledValues(JoyAxis *srcAxis) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->lastKnownThottledValue = srcAxis->lastKnownThottledValue; this->currentThrottledValue = srcAxis->currentThrottledValue; } void JoyAxis::eventReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); naxisbutton->eventReset(); paxisbutton->eventReset(); } void JoyAxis::setAxisMinCal(int value) { axis_min_cal = value; } int JoyAxis::getAxisMinCal() { return ((axis_min_cal != -1) ? axis_min_cal : GlobalVariables::JoyAxis::AXISMIN); } void JoyAxis::setAxisMaxCal(int value) { axis_max_cal = value; } int JoyAxis::getAxisMaxCal() { return ((axis_max_cal != -1) ? axis_max_cal : GlobalVariables::JoyAxis::AXISMAX); } void JoyAxis::setAxisCenterCal(int value) { axis_center_cal = value; } int JoyAxis::getAxisCenterCal() { return ((axis_center_cal != -1) ? axis_center_cal : 0); } AntiMicroX-antimicrox-2888bf6/src/joyaxis.h000066400000000000000000000152031377703515000207120ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYAXIS_H #define JOYAXIS_H #include #include #include "joybuttontypes/joyaxisbutton.h" class JoyControlStick; class SetJoystick; class JoyAxisButton; class QXmlStreamReader; class QXmlStreamWriter; class JoyAxis; class JoyAxis : public QObject { Q_OBJECT public: explicit JoyAxis(int index, int originset, SetJoystick *parentSet, QObject *parent = 0); ~JoyAxis(); enum ThrottleTypes { NegativeHalfThrottle = -2, NegativeThrottle = -1, NormalThrottle = 0, PositiveThrottle = 1, PositiveHalfThrottle = 2 }; void joyEvent(int value, bool ignoresets = false, bool updateLastValues = true); // JoyAxisEvent class void queuePendingEvent(int value, bool ignoresets = false, bool updateLastValues = true); // JoyAxisEvent class void activatePendingEvent(); // JoyAxisEvent class bool hasPendingEvent(); // JoyAxisEvent class void clearPendingEvent(); // JoyAxisEvent class bool inDeadZone(int value); virtual QString getName(bool forceFullFormat = false, bool displayNames = false); virtual QString getPartialName(bool forceFullFormat = false, bool displayNames = false); virtual QString getXmlName(); // JoyAxisXml class void setIndex(int index); int getIndex(); int getRealJoyIndex(); JoyAxisButton *getPAxisButton(); JoyAxisButton *getNAxisButton(); int getDeadZone(); int getMaxZoneValue(); void setThrottle(int value); void setInitialThrottle(int value); void updateCurrentThrottledValue(int newValue); int getThrottle(); int getCurrentThrottledValue(); int getCurrentRawValue(); int getCurrentThrottledDeadValue(); int getCurrentlyAssignedSet(); JoyAxisButton *getAxisButtonByValue(int value); double getDistanceFromDeadZone(); double getDistanceFromDeadZone(int value); double getRawDistance(int value); void setControlStick(JoyControlStick *stick); void removeControlStick(bool performRelease = true); bool isPartControlStick(); JoyControlStick *getControlStick(); bool hasControlOfButtons(); void removeVDPads(); void setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode); bool hasSameButtonsMouseMode(); JoyButton::JoyMouseMovementMode getButtonsPresetMouseMode(); void setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve); bool hasSameButtonsMouseCurve(); JoyButton::JoyMouseCurve getButtonsPresetMouseCurve(); void setButtonsSpringWidth(int value); int getButtonsPresetSpringWidth(); void setButtonsSpringHeight(int value); int getButtonsPresetSpringHeight(); void setButtonsSensitivity(double value); double getButtonsPresetSensitivity(); void setButtonsWheelSpeedX(int value); void setButtonsWheelSpeedY(int value); double getButtonsEasingDuration(); void setAxisMinCal(int value); int getAxisMinCal(); void setAxisMaxCal(int value); int getAxisMaxCal(); void setAxisCenterCal(int value); int getAxisCenterCal(); virtual QString getAxisName(); virtual int getDefaultDeadZone(); virtual int getDefaultMaxZone(); virtual ThrottleTypes getDefaultThrottle(); virtual void setDefaultAxisName(QString tempname); virtual QString getDefaultAxisName(); SetJoystick *getParentSet(); virtual bool isDefault(); bool isRelativeSpring(); void copyAssignments(JoyAxis *destAxis); int getLastKnownThrottleValue(); int getLastKnownRawValue(); int getProperReleaseValue(); void setCurrentRawValue(int value); // Don't use direct assignment but copying from a current axis. void copyRawValues(JoyAxis *srcAxis); void copyThrottledValues(JoyAxis *srcAxis); void setExtraAccelerationCurve(JoyButton::JoyExtraAccelerationCurve curve); JoyButton::JoyExtraAccelerationCurve getExtraAccelerationCurve(); virtual void eventReset(); // JoyAxisEvent class static const ThrottleTypes DEFAULTTHROTTLE; int calculateThrottledValue(int value); protected: void createDeskEvent(bool ignoresets = false); // JoyAxisEvent class void adjustRange(); void performCalibration(int value); void stickPassEvent(int value, bool ignoresets = false, bool updateLastValues = true); // JoyAxisEvent class JoyAxisButton *paxisbutton; JoyAxisButton *naxisbutton; QString axisName; QString defaultAxisName; int throttle; int deadZone; int maxZoneValue; int currentRawValue; int currentThrottledValue; int currentThrottledDeadValue; int m_index; int axis_center_cal; int axis_min_cal; int axis_max_cal; int lastKnownThottledValue; int lastKnownRawValue; int pendingValue; bool isActive; bool pendingEvent; bool pendingIgnoreSets; bool eventActive; JoyAxisButton *activeButton; // TODO: CHECK IF PROPERTY IS NEEDED. // bool pendingUpdateLastValues; signals: void active(int value); void released(int value); void moved(int value); void throttleChangePropogated(int index); void throttleChanged(); void axisNameChanged(); void propertyUpdated(); public slots: virtual void reset(); virtual void reset(int index); void propogateThrottleChange(); void setDeadZone(int value); void setMaxZoneValue(int value); void setAxisName(QString tempName); void setButtonsSpringRelativeStatus(bool value); void setButtonsEasingDuration(double value); void establishPropertyUpdatedConnection(); void disconnectPropertyUpdatedConnection(); private: int m_originset; JoyControlStick *m_stick; SetJoystick *m_parentSet; void resetPrivateVars(); }; #endif // JOYAXIS_H AntiMicroX-antimicrox-2888bf6/src/joyaxiscontextmenu.cpp000066400000000000000000000450701377703515000235440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joyaxiscontextmenu.h" #include "antkeymapper.h" #include "common.h" #include "inputdevice.h" #include "joyaxis.h" #include "messagehandler.h" #include "mousedialog/mouseaxissettingsdialog.h" #include #include JoyAxisContextMenu::JoyAxisContextMenu(JoyAxis *axis, QWidget *parent) : QMenu(parent) , helper(axis) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->axis = axis; getHelperLocal().moveToThread(axis->thread()); connect(this, &JoyAxisContextMenu::aboutToHide, this, &JoyAxisContextMenu::deleteLater); } void JoyAxisContextMenu::buildMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool actAsTrigger = false; PadderCommon::inputDaemonMutex.lock(); if ((axis->getThrottle() == static_cast(JoyAxis::PositiveThrottle)) || (axis->getThrottle() == static_cast(JoyAxis::PositiveHalfThrottle))) { actAsTrigger = true; } PadderCommon::inputDaemonMutex.unlock(); if (actAsTrigger) buildTriggerMenu(); else buildAxisMenu(); } void JoyAxisContextMenu::buildAxisMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); QActionGroup *presetGroup = new QActionGroup(this); int presetMode = 0; int currentPreset = getPresetIndex(); QAction *action = this->addAction(tr("Mouse (Horizontal)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Mouse (Inverted Horizontal)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Mouse (Vertical)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Mouse (Inverted Vertical)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Arrows: Up | Down")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Arrows: Left | Right")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Keys: W | S")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Keys: A | D")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("NumPad: KP_8 | KP_2")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("NumPad: KP_4 | KP_6")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("None")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setAxisPreset(action); }); presetGroup->addAction(action); this->addSeparator(); action = this->addAction(tr("Mouse Settings")); action->setCheckable(false); connect(action, &QAction::triggered, this, &JoyAxisContextMenu::openMouseSettingsDialog); } int JoyAxisContextMenu::getPresetIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = 0; JoyAxisButton *naxisbutton = axis->getNAxisButton(); QList *naxisslots = naxisbutton->getAssignedSlots(); JoyAxisButton *paxisbutton = axis->getPAxisButton(); QList *paxisslots = paxisbutton->getAssignedSlots(); if ((naxisslots->length() == 1) && (paxisslots->length() == 1)) { JoyButtonSlot *nslot = naxisslots->at(0); JoyButtonSlot *pslot = paxisslots->at(0); if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseRight)) { result = 1; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseRight) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { result = 2; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseUp) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseDown)) { result = 3; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (nslot->getSlotCode() == JoyButtonSlot::MouseDown) && (pslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (pslot->getSlotCode() == JoyButtonSlot::MouseUp)) { result = 4; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down))) { result = 5; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right))) { result = 6; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S))) { result = 7; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D))) { result = 8; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2))) { result = 9; } else if ((nslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (nslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4)) && (pslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (pslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6))) { result = 10; } } else if ((naxisslots->length() == 0) && (paxisslots->length() == 0)) { result = 11; } PadderCommon::inputDaemonMutex.unlock(); return result; } void JoyAxisContextMenu::setAxisPreset(QAction *action) { qInstallMessageHandler(MessageHandler::myMessageOutput); int item = action->data().toInt(); JoyButtonSlot *nbuttonslot = nullptr; JoyButtonSlot *pbuttonslot = nullptr; switch (item) { case 0: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); break; case 1: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); break; case 2: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); break; case 3: nbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); break; case 4: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up), Qt::Key_Up, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down), Qt::Key_Down, JoyButtonSlot::JoyKeyboard, this); break; case 5: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left), Qt::Key_Left, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right), Qt::Key_Right, JoyButtonSlot::JoyKeyboard, this); break; case 6: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W), Qt::Key_W, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S), Qt::Key_S, JoyButtonSlot::JoyKeyboard, this); break; case 7: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A), Qt::Key_A, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D), Qt::Key_D, JoyButtonSlot::JoyKeyboard, this); break; case 8: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); break; case 9: nbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); pbuttonslot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); break; case 10: QMetaObject::invokeMethod(&helper, "clearAndResetAxisButtons", Qt::BlockingQueuedConnection); break; } if (nbuttonslot != nullptr) { QMetaObject::invokeMethod(&helper, "setNAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, nbuttonslot->getSlotCode()), Q_ARG(int, nbuttonslot->getSlotCodeAlias()), Q_ARG(JoyButtonSlot::JoySlotInputAction, nbuttonslot->getSlotMode())); nbuttonslot->deleteLater(); } if (pbuttonslot != nullptr) { QMetaObject::invokeMethod(&helper, "setPAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, nbuttonslot->getSlotCode()), Q_ARG(int, nbuttonslot->getSlotCodeAlias()), Q_ARG(JoyButtonSlot::JoySlotInputAction, nbuttonslot->getSlotMode())); pbuttonslot->deleteLater(); } } void JoyAxisContextMenu::openMouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); MouseAxisSettingsDialog *dialog = new MouseAxisSettingsDialog(this->axis, parentWidget()); dialog->show(); } void JoyAxisContextMenu::buildTriggerMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); QActionGroup *presetGroup = new QActionGroup(this); int presetMode = 0; int currentPreset = getTriggerPresetIndex(); QAction *action = this->addAction(tr("Left Mouse Button")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setTriggerPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Right Mouse Button")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setTriggerPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("None")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action]() { setTriggerPreset(action); }); presetGroup->addAction(action); this->addSeparator(); action = this->addAction(tr("Mouse Settings")); action->setCheckable(false); connect(action, &QAction::triggered, this, &JoyAxisContextMenu::openMouseSettingsDialog); } int JoyAxisContextMenu::getTriggerPresetIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = 0; PadderCommon::inputDaemonMutex.lock(); JoyAxisButton *paxisbutton = axis->getPAxisButton(); QList *paxisslots = paxisbutton->getAssignedSlots(); if (paxisslots->length() == 1) { JoyButtonSlot *pslot = paxisslots->at(0); if ((pslot->getSlotMode() == JoyButtonSlot::JoyMouseButton) && (pslot->getSlotCode() == JoyButtonSlot::MouseLB)) { result = 1; } else if ((pslot->getSlotMode() == JoyButtonSlot::JoyMouseButton) && (pslot->getSlotCode() == JoyButtonSlot::MouseRB)) { result = 2; } } else if (paxisslots->length() == 0) { result = 3; } PadderCommon::inputDaemonMutex.unlock(); return result; } void JoyAxisContextMenu::setTriggerPreset(QAction *action) { qInstallMessageHandler(MessageHandler::myMessageOutput); int item = action->data().toInt(); JoyButtonSlot *pbuttonslot = nullptr; switch (item) { case 0: pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseLB, JoyButtonSlot::JoyMouseButton, this); break; case 1: pbuttonslot = new JoyButtonSlot(JoyButtonSlot::MouseRB, JoyButtonSlot::JoyMouseButton, this); break; case 2: JoyAxisButton *pbutton = axis->getPAxisButton(); QMetaObject::invokeMethod(pbutton, "clearSlotsEventReset", Qt::BlockingQueuedConnection); break; } if (pbuttonslot != nullptr) { QMetaObject::invokeMethod(&helper, "setPAssignedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, pbuttonslot->getSlotCode()), Q_ARG(int, pbuttonslot->getSlotCodeAlias()), Q_ARG(JoyButtonSlot::JoySlotInputAction, pbuttonslot->getSlotMode())); pbuttonslot->deleteLater(); } } JoyAxisContextMenuHelper &JoyAxisContextMenu::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/joyaxiscontextmenu.h000066400000000000000000000030271377703515000232050ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYAXISCONTEXTMENU_H #define JOYAXISCONTEXTMENU_H #include "uihelpers/joyaxiscontextmenuhelper.h" #include class JoyAxis; class QWidget; class JoyAxisContextMenu : public QMenu { Q_OBJECT public: explicit JoyAxisContextMenu(JoyAxis *axis, QWidget *parent = nullptr); void buildMenu(); void buildAxisMenu(); void buildTriggerMenu(); protected: int getPresetIndex(); int getTriggerPresetIndex(); private slots: void setAxisPreset(QAction *action); void setTriggerPreset(QAction *action); void openMouseSettingsDialog(); private: JoyAxisContextMenuHelper &getHelperLocal(); JoyAxis *axis; JoyAxisContextMenuHelper helper; }; #endif // JOYAXISCONTEXTMENU_H AntiMicroX-antimicrox-2888bf6/src/joyaxiswidget.cpp000066400000000000000000000074531377703515000224610ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joyaxiswidget.h" #include "joyaxis.h" #include "joyaxiscontextmenu.h" #include "messagehandler.h" #include JoyAxisWidget::JoyAxisWidget(JoyAxis *axis, bool displayNames, QWidget *parent) : FlashButtonWidget(displayNames, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_axis = axis; refreshLabel(); enableFlashes(); this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &JoyAxisWidget::customContextMenuRequested, this, &JoyAxisWidget::showContextMenu); JoyAxisButton *nAxisButton = m_axis->getNAxisButton(); JoyAxisButton *pAxisButton = m_axis->getPAxisButton(); tryFlash(); connect(m_axis, &JoyAxis::throttleChanged, this, &JoyAxisWidget::refreshLabel); connect(m_axis, &JoyAxis::axisNameChanged, this, &JoyAxisWidget::refreshLabel); connect(nAxisButton, &JoyAxisButton::propertyUpdated, this, &JoyAxisWidget::refreshLabel); connect(pAxisButton, &JoyAxisButton::propertyUpdated, this, &JoyAxisWidget::refreshLabel); connect(nAxisButton, &JoyAxisButton::activeZoneChanged, this, &JoyAxisWidget::refreshLabel); connect(pAxisButton, &JoyAxisButton::activeZoneChanged, this, &JoyAxisWidget::refreshLabel); m_axis->establishPropertyUpdatedConnection(); nAxisButton->establishPropertyUpdatedConnections(); pAxisButton->establishPropertyUpdatedConnections(); } JoyAxis *JoyAxisWidget::getAxis() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_axis; } void JoyAxisWidget::disableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(m_axis, &JoyAxis::active, this, &JoyAxisWidget::flash); disconnect(m_axis, &JoyAxis::released, this, &JoyAxisWidget::unflash); this->unflash(); } void JoyAxisWidget::enableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(m_axis, &JoyAxis::active, this, &JoyAxisWidget::flash, Qt::QueuedConnection); connect(m_axis, &JoyAxis::released, this, &JoyAxisWidget::unflash, Qt::QueuedConnection); } /** * @brief Generate the string that will be displayed on the button * @return Display string */ QString JoyAxisWidget::generateLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = m_axis->getName(false, ifDisplayNames()).replace("&", "&&"); qDebug() << "Name of joy axis is: " << temp; return temp; } void JoyAxisWidget::showContextMenu(const QPoint &point) { qInstallMessageHandler(MessageHandler::myMessageOutput); QPoint globalPos = this->mapToGlobal(point); JoyAxisContextMenu *contextMenu = new JoyAxisContextMenu(m_axis, this); contextMenu->buildMenu(); contextMenu->popup(globalPos); } void JoyAxisWidget::tryFlash() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *nAxisButton = m_axis->getNAxisButton(); JoyAxisButton *pAxisButton = m_axis->getPAxisButton(); if (nAxisButton->getButtonState() || pAxisButton->getButtonState()) { flash(); } } AntiMicroX-antimicrox-2888bf6/src/joyaxiswidget.h000066400000000000000000000026101377703515000221140ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYAXISWIDGET_H #define JOYAXISWIDGET_H #include "flashbuttonwidget.h" class JoyAxis; class QWidget; class JoyAxisWidget : public FlashButtonWidget { Q_OBJECT public: explicit JoyAxisWidget(JoyAxis *axis, bool displayNames, QWidget *parent = 0); JoyAxis *getAxis() const; void tryFlash(); protected: virtual QString generateLabel() override; public slots: void disableFlashes() override; void enableFlashes() override; private slots: void showContextMenu(const QPoint &point); private: JoyAxis *m_axis; }; #endif // JOYAXISWIDGET_H AntiMicroX-antimicrox-2888bf6/src/joybutton.cpp000066400000000000000000004712551377703515000216310ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybutton.h" #include "event.h" #include "inputdevice.h" #include "logger.h" #include "messagehandler.h" #include "setjoystick.h" #include "vdpad.h" #include "SDL2/SDL_events.h" #include "eventhandlerfactory.h" #include //#include #include #include #include #include #include #include const JoyButton::JoyMouseCurve JoyButton::DEFAULTMOUSECURVE = JoyButton::EnhancedPrecisionCurve; const JoyButton::SetChangeCondition JoyButton::DEFAULTSETCONDITION = JoyButton::SetChangeDisabled; const JoyButton::JoyMouseMovementMode JoyButton::DEFAULTMOUSEMODE = JoyButton::MouseCursor; const JoyButton::TurboMode JoyButton::DEFAULTTURBOMODE = JoyButton::NormalTurbo; const JoyButton::JoyExtraAccelerationCurve JoyButton::DEFAULTEXTRAACCELCURVE = JoyButton::LinearAccelCurve; JoyButtonSlot *JoyButton::lastActiveKey = nullptr; // Keep track of active Mouse Speed Mod slots. QList JoyButton::mouseSpeedModList; // Lists used for cursor mode calculations. QList JoyButton::cursorXSpeeds; QList JoyButton::cursorYSpeeds; // Lists used for spring mode calculations. QList JoyButton::springXSpeeds; QList JoyButton::springYSpeeds; // Temporary test object to test old mouse time behavior. QTime JoyButton::testOldMouseTime; // time when minislots next to each other in thread pool are waiting to execute function // at the same time int JoyButton::timeBetweenMiniSlots = 55; int JoyButton::allSlotTimeBetweenSlots = 0; // Helper object to have a single mouse event for all JoyButton // instances. JoyButtonMouseHelper JoyButton::mouseHelper; QTimer JoyButton::staticMouseEventTimer; QList JoyButton::pendingMouseButtons; // IT CAN BE HERE // LOOK FOR JoyCycle and put JoyMix next to the slots types JoyButton::JoyButton(int index, int originset, SetJoystick *parentSet, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "Thread in Joybutton"; m_vdpad = nullptr; slotiter = nullptr; threadPool = QThreadPool::globalInstance(); turboTimer.setParent(this); pauseTimer.setParent(this); holdTimer.setParent(this); pauseWaitTimer.setParent(this); createDeskTimer.setParent(this); releaseDeskTimer.setParent(this); mouseWheelVerticalEventTimer.setParent(this); mouseWheelHorizontalEventTimer.setParent(this); setChangeTimer.setParent(this); keyPressTimer.setParent(this); delayTimer.setParent(this); slotSetChangeTimer.setParent(this); activeZoneTimer.setParent(this); setChangeTimer.setSingleShot(true); slotSetChangeTimer.setSingleShot(true); m_parentSet = parentSet; connect(&pauseWaitTimer, &QTimer::timeout, this, &JoyButton::pauseWaitEvent); connect(&keyPressTimer, &QTimer::timeout, this, &JoyButton::keyPressEvent); connect(&holdTimer, &QTimer::timeout, this, &JoyButton::holdEvent); connect(&delayTimer, &QTimer::timeout, this, &JoyButton::delayEvent); connect(&createDeskTimer, &QTimer::timeout, this, &JoyButton::waitForDeskEvent); connect(&releaseDeskTimer, &QTimer::timeout, this, &JoyButton::waitForReleaseDeskEvent); connect(&turboTimer, &QTimer::timeout, this, &JoyButton::turboEvent); connect(&mouseWheelVerticalEventTimer, &QTimer::timeout, this, &JoyButton::wheelEventVertical); connect(&mouseWheelHorizontalEventTimer, &QTimer::timeout, this, &JoyButton::wheelEventHorizontal); connect(&setChangeTimer, &QTimer::timeout, this, &JoyButton::checkForSetChange); connect(&slotSetChangeTimer, &QTimer::timeout, this, &JoyButton::slotSetChange); connect(&activeZoneTimer, &QTimer::timeout, this, &JoyButton::buildActiveZoneSummaryString); activeZoneTimer.setInterval(0); activeZoneTimer.setSingleShot(true); // Will only matter on the first call establishMouseTimerConnections(); // Make sure to call before calling reset resetAllProperties(); m_index = index; m_originset = originset; quitEvent = true; } JoyButton::~JoyButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); // threadPool->clear(); reset(); // resetPrivVars(); } void JoyButton::queuePendingEvent(bool pressed, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); updatePendingParams(false, false, false); if (m_vdpad != nullptr) vdpadPassEvent(pressed, ignoresets); else updatePendingParams(true, pressed, ignoresets); } void JoyButton::activatePendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (pendingEvent) { joyEvent(pendingPress, pendingIgnoreSets); updatePendingParams(false, false, false); } } bool JoyButton::hasPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); return pendingEvent; } void JoyButton::clearPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); updatePendingParams(false, false, false); } void JoyButton::vdpadPassEvent(bool pressed, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((m_vdpad != nullptr) && (pressed != isButtonPressed)) { isButtonPressed = pressed; if (isButtonPressed) emit clicked(m_index); else emit released(m_index); if (!ignoresets) m_vdpad->queueJoyEvent(ignoresets); else m_vdpad->joyEvent(pressed, ignoresets); } } void JoyButton::joyEvent(bool pressed, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((m_vdpad != nullptr) && !pendingEvent) { vdpadPassEvent(pressed, ignoresets); } else if (ignoreEvents && (pressed != isButtonPressed)) { isButtonPressed = pressed; if (isButtonPressed) emit clicked(m_index); else emit released(m_index); } else { if (pressed != isDown) { if (pressed) { emit clicked(m_index); if (updateInitAccelValues) oldAccelMulti = updateOldAccelMulti = accelTravel = 0.0; } else { emit released(m_index); } bool activePress = pressed; setChangeTimer.stop(); if (m_toggle && pressed) { isDown = true; toggleActiveState = !toggleActiveState; if (!isButtonPressed) { m_ignoresets = ignoresets; isButtonPressed = !isButtonPressed; ignoreSetQueue.enqueue(ignoresets); isButtonPressedQueue.enqueue(isButtonPressed); } else { activePress = false; } } else if (m_toggle && !pressed && isDown) { isDown = false; if (!toggleActiveState) { m_ignoresets = ignoresets; isButtonPressed = !isButtonPressed; ignoreSetQueue.enqueue(ignoresets); isButtonPressedQueue.enqueue(isButtonPressed); } } else { m_ignoresets = ignoresets; isButtonPressed = isDown = pressed; ignoreSetQueue.enqueue(ignoresets); isButtonPressedQueue.enqueue(isButtonPressed); } if (m_useTurbo) { if (isButtonPressed && activePress && !turboTimer.isActive()) { startSequenceOfPressActive(true, tr("Processing turbo for #%1 - %2")); turboEvent(); } else if (!isButtonPressed && !activePress && turboTimer.isActive()) { turboTimer.stop(); Logger::LogDebug(tr("Finishing turbo for button #%1 - %2") .arg(m_parentSet->getInputDevice()->getRealJoyNumber()) .arg(getPartialName())); if (isKeyPressed) turboEvent(); else lastDistance = getMouseDistanceFromDeadZone(); activeZoneTimer.start(); } } // Toogle is enabled and a controller button change has occurred. // Switch to a different distance zone if appropriate else if (m_toggle && !activePress && isButtonPressed) { updateParamsAfterDistEvent(); } else if (isButtonPressed && activePress) { startSequenceOfPressActive(false, tr("Processing press for button #%1 - %2")); if (!keyPressTimer.isActive()) { checkForPressedSetChange(); if (!setChangeTimer.isActive()) waitForDeskEvent(); } } else if (!isButtonPressed && !activePress) { Logger::LogDebug(tr("Processing release for button #%1 - %2") .arg(m_parentSet->getInputDevice()->getRealJoyNumber()) .arg(getPartialName())); waitForReleaseDeskEvent(); } if (updateInitAccelValues) updateMouseParams(false, false, 0.0); } else if (!m_useTurbo && isButtonPressed) { resetAccelerationDistances(); currentAccelerationDistance = getAccelerationDistance(); if (!setChangeTimer.isActive()) updateParamsAfterDistEvent(); } } updateInitAccelValues = true; } void JoyButton::updateParamsAfterDistEvent() { if (distanceEvent()) { Logger::LogDebug(tr("Distance change for button #%1 - %2") .arg(m_parentSet->getInputDevice()->getRealJoyNumber()) .arg(getPartialName())); quitEvent = true; buttonHold.restart(); buttonHeldRelease.restart(); keyPressHold.restart(); releaseDeskTimer.stop(); if (!keyPressTimer.isActive()) waitForDeskEvent(); } } void JoyButton::startSequenceOfPressActive(bool isTurbo, QString debugText) { if (cycleResetActive && (cycleResetHold.elapsed() >= cycleResetInterval) && (slotiter != nullptr)) { slotiter->toFront(); currentCycle = nullptr; previousCycle = nullptr; } buttonHold.restart(); buttonHeldRelease.restart(); keyPressHold.restart(); cycleResetHold.restart(); if (isTurbo) turboTimer.start(); else releaseDeskTimer.stop(); // Newly activated button. Just entered safe zone. if (updateInitAccelValues) initializeDistanceValues(); currentAccelerationDistance = getAccelerationDistance(); Logger::LogDebug(debugText.arg(m_parentSet->getInputDevice()->getRealJoyNumber()).arg(getPartialName())); } /** * @brief Get 0 indexed number of button * @return 0 indexed button index number */ int JoyButton::getJoyNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index; } /** * @brief Get a 1 indexed number of button * @return 1 indexed button index number */ int JoyButton::getRealJoyNumber() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index + 1; } void JoyButton::setJoyNumber(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_index = index; } void JoyButton::setToggle(bool toggle) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (toggle != m_toggle) { m_toggle = toggle; emit toggleChanged(toggle); emit propertyUpdated(); } } void JoyButton::setTurboInterval(int interval) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((interval < 10) && (interval != this->turboInterval)) { this->setUseTurbo(false); interval = 0; } this->turboInterval = interval; emit turboIntervalChanged(interval); emit propertyUpdated(); } void JoyButton::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); resetPrivVars(); } void JoyButton::resetPrivVars() { disconnectPropertyUpdatedConnections(); stopTimers(false, false, true); releaseActiveSlots(); clearAssignedSlots(); clearQueues(); resetAllProperties(); // quitEvent changed here } void JoyButton::reset(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::reset(); m_index = index; } bool JoyButton::getToggleState() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_toggle; } int JoyButton::getTurboInterval() { qInstallMessageHandler(MessageHandler::myMessageOutput); return turboInterval; } void JoyButton::turboEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeTurboParams(isKeyPressed, isButtonPressed); } void JoyButton::changeTurboParams(bool _isKeyPressed, bool isButtonPressed) { if (!isButtonPressedQueue.isEmpty()) { if (!_isKeyPressed) { ignoreSetQueue.clear(); isButtonPressedQueue.clear(); isButtonPressedQueue.enqueue(isButtonPressed); } else { isButtonPressedQueue.enqueue(!isButtonPressed); } ignoreSetQueue.enqueue(false); } if (!_isKeyPressed) createDeskEvent(); else releaseDeskEvent(); isKeyPressed = !_isKeyPressed; if (turboTimer.isActive()) { int tempInterval = turboInterval / 2; if (turboTimer.interval() != tempInterval) turboTimer.start(tempInterval); } } bool JoyButton::distanceEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool released = false; if (slotiter != nullptr) { QReadLocker tempLocker(&assignmentsLock); if (containsDistanceSlots()) { double currentDistance = getDistanceFromDeadZone(); double tempDistance = 0.0; JoyButtonSlot *previousDistanceSlot = nullptr; QListIterator iter(*getAssignedSlots()); if (previousCycle != nullptr) { qDebug() << "find previous Cycle in next steps in assignments and skip to it"; iter.findNext(previousCycle); } while (iter.hasNext()) { JoyButtonSlot *slot = iter.next(); int tempcode = slot->getSlotCode(); if (slot->getSlotMode() == JoyButtonSlot::JoyDistance) { tempDistance += (tempcode / 100.0); if (currentDistance < tempDistance) iter.toBack(); else previousDistanceSlot = slot; } else if (slot->getSlotMode() == JoyButtonSlot::JoyCycle) { tempDistance = 0.0; iter.toBack(); } } // No applicable distance slot if (!previousDistanceSlot) { if (m_currentDistance != nullptr) { // Distance slot is currently active. // Release slots, return iterator to // the front, and nullify currentDistance pauseWaitTimer.stop(); holdTimer.stop(); // Release stuff releaseActiveSlots(); currentPause = currentHold = nullptr; slotiter->toFront(); if (previousCycle != nullptr) slotiter->findNext(previousCycle); m_currentDistance = nullptr; released = true; } } // An applicable distance slot was found else { if (m_currentDistance != previousDistanceSlot) { // Active distance slot is not the applicable slot. // Deactive slots in previous distance range and // activate new slots. Set currentDistance to // new slot. pauseWaitTimer.stop(); holdTimer.stop(); // Release stuff releaseActiveSlots(); currentPause = currentHold = nullptr; qDebug() << "Deactive slots in previous range and activate new slots"; slotiter->toFront(); if (previousCycle != nullptr) { qDebug() << "Find previous Cycle in slotiter starting from beginning"; slotiter->findNext(previousCycle); } slotiter->findNext(previousDistanceSlot); m_currentDistance = previousDistanceSlot; released = true; } } } } return released; } void JoyButton::createDeskEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); quitEvent = false; if (slotiter == nullptr) { assignmentsLock.lockForRead(); slotiter = new QListIterator(*getAssignedSlots()); assignmentsLock.unlock(); distanceEvent(); } else if (!slotiter->hasPrevious()) { distanceEvent(); } else if (currentCycle != nullptr) { currentCycle = nullptr; distanceEvent(); } assignmentsLock.lockForRead(); activateSlots(); assignmentsLock.unlock(); if (currentCycle != nullptr) quitEvent = true; else if ((currentPause == nullptr) && (currentHold == nullptr) && !keyPressTimer.isActive()) quitEvent = true; } void JoyButton::activateSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool countForAllTime = false; if (allSlotTimeBetweenSlots == 0) countForAllTime = true; if (slotiter != nullptr) { QWriteLocker tempLocker(&activeZoneLock); bool exit = false; bool delaySequence = false; int i = 0; while (slotiter->hasNext() && !exit) { JoyButtonSlot *slot = slotiter->next(); if (slot->getSlotMode() == JoyButtonSlot::JoyMix) { qDebug() << "JOYMIX IN ACTIVATESLOTS"; if (slot->getMixSlots() != nullptr) { QListIterator mini_it(*slot->getMixSlots()); QListIterator *it(&mini_it); int countMinis = slot->getMixSlots()->count(); int timeX = countMinis; std::chrono::time_point t1, t2; t1 = std::chrono::high_resolution_clock::now(); while (it->hasNext()) { JoyButtonSlot *slotmini = it->next(); qDebug() << "Run activated mini slot - name - deviceCode - mode: " << slotmini->getSlotString() << " - " << slotmini->getSlotCode() << " - " << slotmini->getSlotMode(); MiniSlotRun *minijob = new MiniSlotRun(slot, slotmini, this, timeBetweenMiniSlots * timeX); minijob->setAutoDelete(false); threadPool->start(minijob); timeX--; if (timeBetweenMiniSlots == 55) { t2 = std::chrono::high_resolution_clock::now(); timeBetweenMiniSlots = std::chrono::duration_cast(t2 - t1).count(); } } if (countForAllTime) { allSlotTimeBetweenSlots += countMinis * timeBetweenMiniSlots; } threadPool->waitForDone(); i++; if (!slotiter->hasNext()) break; } } else { qDebug() << "Check now simple slots"; addEachSlotToActives(slot, i, delaySequence, exit, slotiter); } } if (delaySequence && !getActiveSlots().isEmpty()) { keyPressHold.restart(); keyPressEvent(); } activeZoneTimer.start(); } } void JoyButton::activateMiniSlots(JoyButtonSlot *slot, JoyButtonSlot *mix) { int tempcode = slot->getSlotCode(); JoyButtonSlot::JoySlotInputAction mode = slot->getSlotMode(); switch (mode) { case JoyButtonSlot::JoyKeyboard: { sendKeybEvent(slot, true); getActiveSlotsLocal().append(slot); int oldvalue = GlobalVariables::JoyButton::JoyButton::activeKeys.value(tempcode, 0) + 1; GlobalVariables::JoyButton::JoyButton::activeKeys.insert(tempcode, oldvalue); if (!slot->isModifierKey()) { qDebug() << "There has been assigned a lastActiveKey " << slot->getSlotString(); lastActiveKey = mix; } else { qDebug() << "It's not modifier key. lastActiveKey is null pointer"; lastActiveKey = nullptr; } break; } } } void JoyButton::addEachSlotToActives(JoyButtonSlot *slot, int &i, bool &delaySequence, bool &exit, QListIterator *slotiter) { int tempcode = slot->getSlotCode(); JoyButtonSlot::JoySlotInputAction mode = slot->getSlotMode(); switch (mode) { case JoyButtonSlot::JoyKeyboard: { i++; qDebug() << i << ": It's a JoyKeyboard with code: " << tempcode << " and name: " << slot->getSlotString(); sendevent(slot, true); getActiveSlotsLocal().append(slot); int oldvalue = GlobalVariables::JoyButton::JoyButton::activeKeys.value(tempcode, 0) + 1; GlobalVariables::JoyButton::JoyButton::activeKeys.insert(tempcode, oldvalue); if (!slot->isModifierKey()) { qDebug() << "There has been assigned a lastActiveKey " << slot->getSlotString(); lastActiveKey = slot; } else { qDebug() << "It's not modifier key. lastActiveKey is null pointer"; lastActiveKey = nullptr; } break; } case JoyButtonSlot::JoyMouseButton: { i++; qDebug() << i << ": It's a JoyMouseButton with code: " << tempcode << " and name: " << slot->getSlotString(); if ((tempcode == static_cast(JoyButtonSlot::MouseWheelUp)) || (tempcode == static_cast(JoyButtonSlot::MouseWheelDown))) { slot->getMouseInterval()->restart(); wheelVerticalTime.restart(); currentWheelVerticalEvent = slot; getActiveSlotsLocal().append(slot); wheelEventVertical(); currentWheelVerticalEvent = nullptr; } else if ((tempcode == static_cast(JoyButtonSlot::MouseWheelLeft)) || (tempcode == static_cast(JoyButtonSlot::MouseWheelRight))) { slot->getMouseInterval()->restart(); wheelHorizontalTime.restart(); currentWheelHorizontalEvent = slot; getActiveSlotsLocal().append(slot); wheelEventHorizontal(); currentWheelHorizontalEvent = nullptr; } else { sendevent(slot, true); getActiveSlotsLocal().append(slot); int oldvalue = GlobalVariables::JoyButton::JoyButton::activeMouseButtons.value(tempcode, 0) + 1; GlobalVariables::JoyButton::JoyButton::activeMouseButtons.insert(tempcode, oldvalue); } break; } case JoyButtonSlot::JoyMouseMovement: { i++; qDebug() << i << ": It's a JoyMouseMovement with code: " << tempcode << " and name: " << slot->getSlotString(); slot->getMouseInterval()->restart(); getActiveSlotsLocal().append(slot); if (pendingMouseButtons.size() == 0) mouseHelper.setFirstSpringStatus(true); pendingMouseButtons.append(this); mouseEventQueue.enqueue(slot); // Temporarily lower timer interval. Helps improve mouse control // precision on the lower end of an axis. if (!staticMouseEventTimer.isActive() || (staticMouseEventTimer.interval() != 0)) { if (!staticMouseEventTimer.isActive() || (staticMouseEventTimer.interval() == GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE)) { int tempRate = qBound(0, GlobalVariables::JoyButton::mouseRefreshRate - GlobalVariables::JoyButton::gamepadRefreshRate, GlobalVariables::JoyButton::MAXIMUMMOUSEREFRESHRATE); staticMouseEventTimer.start(tempRate); testOldMouseTime.restart(); accelExtraDurationTime.restart(); } } break; } case JoyButtonSlot::JoyPause: { i++; qDebug() << i << ": It's a JoyPause with code: " << tempcode << " and name: " << slot->getSlotString(); if (!getActiveSlots().isEmpty()) { qDebug() << "active slots QHash is not empty"; if (slotiter->hasPrevious()) { i--; slotiter->previous(); } delaySequence = true; exit = true; } // Segment can be ignored on a 0 interval pause else if (tempcode > 0) { qDebug() << "active slots QHash is empty"; currentPause = slot; pauseHold.restart(); inpauseHold.restart(); pauseWaitTimer.start(0); exit = true; } break; } case JoyButtonSlot::JoyHold: { i++; qDebug() << i << ": It's a JoyHold with code: " << tempcode << " and name: " << slot->getSlotString(); currentHold = slot; holdTimer.start(0); exit = true; break; } case JoyButtonSlot::JoyDelay: { i++; qDebug() << i << ": It's a JoyDelay with code: " << tempcode << " and name: " << slot->getSlotString(); currentDelay = slot; buttonDelay.restart(); delayTimer.start(0); exit = true; break; } case JoyButtonSlot::JoyCycle: { i++; qDebug() << i << ": It's a JoyCycle with code: " << tempcode << " and name: " << slot->getSlotString(); currentCycle = slot; exit = true; break; } case JoyButtonSlot::JoyDistance: { i++; qDebug() << i << ": It's a JoyDistance with code: " << tempcode << " and name: " << slot->getSlotString(); exit = true; break; } case JoyButtonSlot::JoyRelease: { i++; qDebug() << i << ": It's a JoyRelease with code: " << tempcode << " and name: " << slot->getSlotString(); if (currentRelease == nullptr) { findJoySlotsEnd(slotiter); } else if ((currentRelease != nullptr) && getActiveSlots().isEmpty()) { qDebug() << "current is release but activeSlots is empty"; exit = true; } else if ((currentRelease != nullptr) && !getActiveSlots().isEmpty()) { qDebug() << "current is release and activeSlots is not empty"; if (slotiter->hasPrevious()) { qDebug() << "Back to previous slotiter from release"; i--; slotiter->previous(); } delaySequence = true; exit = true; } break; } case JoyButtonSlot::JoyMouseSpeedMod: { i++; qDebug() << i << ": It's a JoyMouseSpeedMod with code: " << tempcode << " and name: " << slot->getSlotString(); GlobalVariables::JoyButton::mouseSpeedModifier = tempcode * 0.01; mouseSpeedModList.append(slot); getActiveSlotsLocal().append(slot); break; } case JoyButtonSlot::JoyKeyPress: { i++; qDebug() << i << ": It's a JoyKeyPress with code: " << tempcode << " and name: " << slot->getSlotString(); if (getActiveSlots().isEmpty()) { qDebug() << "activeSlots is empty. It's a true delaySequence and assigned currentKeyPress"; delaySequence = true; currentKeyPress = slot; } else { qDebug() << "activeSlots is not empty. It's a true delaySequence and exit"; if (slotiter->hasPrevious()) { qDebug() << "Back to previous slotiter from JoyKeyPress"; i--; slotiter->previous(); } delaySequence = true; exit = true; } break; } case JoyButtonSlot::JoyLoadProfile: { i++; qDebug() << i << ": It's a JoyLoadProfile with code: " << tempcode << " and name: " << slot->getSlotString(); releaseActiveSlots(); slotiter->toBack(); exit = true; QString location = slot->getTextData(); if (!location.isEmpty()) m_parentSet->getInputDevice()->sendLoadProfileRequest(location); break; } case JoyButtonSlot::JoySetChange: { i++; qDebug() << i << ": It's a JoySetChange with code: " << tempcode << " and name: " << slot->getSlotString(); getActiveSlotsLocal().append(slot); break; } case JoyButtonSlot::JoyTextEntry: case JoyButtonSlot::JoyExecute: { i++; qDebug() << i << ": It's a JoyExecute or JoyTextEntry with code: " << tempcode << " and name: " << slot->getSlotString(); sendevent(slot, true); break; } } } void JoyButton::slotSetChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (currentSetChangeSlot != nullptr) { // Get set change slot and then remove reference. int setChangeIndex = currentSetChangeSlot->getSlotCode(); currentSetChangeSlot = nullptr; // Ensure that a change to the current set is not attempted. if (setChangeIndex != m_originset) { emit released(m_index); emit setChangeActivated(setChangeIndex); } } } /** * @brief Calculate mouse movement coordinates for mouse movement slots * currently active. */ void JoyButton::mouseEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *buttonslot = nullptr; bool singleShot = false; if (currentMouseEvent != nullptr) { buttonslot = currentMouseEvent; singleShot = true; } if ((buttonslot != nullptr) || !mouseEventQueue.isEmpty()) { updateMouseParams(true, true, 0.0); QQueue tempQueue; if (buttonslot == nullptr) buttonslot = mouseEventQueue.dequeue(); int timeElapsed = testOldMouseTime.elapsed(); // Presumed initial mouse movement. Use full duration rather than // partial. if (staticMouseEventTimer.interval() < GlobalVariables::JoyButton::mouseRefreshRate) { timeElapsed = GlobalVariables::JoyButton::mouseRefreshRate + (timeElapsed - staticMouseEventTimer.interval()); } while (buttonslot != nullptr) { QElapsedTimer *mouseInterval = buttonslot->getMouseInterval(); int mousedirection = buttonslot->getSlotCode(); JoyButton::JoyMouseMovementMode mousemode = getMouseMode(); bool isActive = getActiveSlots().contains(buttonslot); if (isActive) { int mousespeed = 0; if (mousemode == JoyButton::MouseCursor) { switch (mousedirection) { case 1: case 2: mousespeed = mouseSpeedY; break; case 3: case 4: mousespeed = mouseSpeedX; break; } double difference = getMouseDistanceFromDeadZone(); double mouse1 = 0; double mouse2 = 0; double sumDist = buttonslot->getMouseDistance(); JoyMouseCurve currentCurve = getMouseCurve(); switch (currentCurve) { case QuadraticCurve: { difference = difference * difference; break; } case CubicCurve: { difference = difference * difference * difference; break; } case QuadraticExtremeCurve: { double temp = difference; difference = difference * difference; difference = (temp >= 0.95) ? (difference * 1.5) : difference; break; } case PowerCurve: { double tempsensitive = qMin(qMax(sensitivity, 1.0e-3), 1.0e+3); double temp = qMin(qMax(pow(difference, 1.0 / tempsensitive), 0.0), 1.0); difference = temp; break; } case EnhancedPrecisionCurve: { // Perform different forms of acceleration depending on // the range of the element from its assigned dead zone. // Useful for more precise controls with an axis. double temp = difference; if (temp <= 0.4) { // Low slope value for really slow acceleration difference = (difference * 0.37); } else if (temp <= 0.75) { // Perform Linear accleration with an appropriate // offset. difference = (difference - 0.252); } else { // Perform mouse acceleration. Make up the difference // due to the previous two segments. Maxes out at 1.0. difference = (difference * 2.008) - 1.008; } break; } case EasingQuadraticCurve: case EasingCubicCurve: { // Perform different forms of acceleration depending on // the range of the element from its assigned dead zone. // Useful for more precise controls with an axis. double temp = difference; if (temp <= 0.4) { // Low slope value for really slow acceleration difference = (difference * 0.38); // Out of high end. Reset easing status. if (buttonslot->isEasingActive()) { buttonslot->setEasingStatus(false); buttonslot->getEasingTime()->restart(); } } else if (temp <= 0.75) { // Perform Linear accleration with an appropriate // offset. difference = (difference - 0.248); // Out of high end. Reset easing status. if (buttonslot->isEasingActive()) { buttonslot->setEasingStatus(false); buttonslot->getEasingTime()->restart(); } } else { // Gradually increase the mouse speed until the specified elapsed duration // time has passed. int easingElapsed = buttonslot->getEasingTime()->elapsed(); double easingDuration = m_easingDuration; // Time in seconds if (!buttonslot->isEasingActive()) { buttonslot->setEasingStatus(true); buttonslot->getEasingTime()->restart(); easingElapsed = 0; } // Determine the multiplier to use for the current maximum mouse speed // based on how much time has passed. double elapsedDiff = 1.0; if ((easingDuration > 0.0) && ((easingElapsed * .001) < easingDuration)) { elapsedDiff = ((easingElapsed * .001) / easingDuration); if (currentCurve == EasingQuadraticCurve) { elapsedDiff = (1.5 - 1.0) * elapsedDiff * elapsedDiff + 1.0; } else { elapsedDiff = (1.5 - 1.0) * (elapsedDiff * elapsedDiff * elapsedDiff) + 1.0; } } else { elapsedDiff = 1.5; } // Allow gradient control on the high end of an axis. difference = (elapsedDiff * difference); difference = (difference * 1.33067 - 0.496005); } break; } default: break; } double distance = 0; difference = (GlobalVariables::JoyButton::mouseSpeedModifier == 1.0) ? difference : (difference * GlobalVariables::JoyButton::mouseSpeedModifier); double mintravel = minMouseDistanceAccelThreshold * 0.01; double minstop = qMax(0.05, mintravel); // Last check ensures that acceleration is only applied for the same direction. if (extraAccelerationEnabled && isPartRealAxis() && (fabs(getAccelerationDistance() - lastAccelerationDistance) >= mintravel) && (((getAccelerationDistance() - lastAccelerationDistance) >= 0) == (getAccelerationDistance() >= 0))) { double magfactor = extraAccelerationMultiplier; double minfactor = qMax((GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER * 0.001) + 1.0, magfactor * (startAccelMultiplier * 0.01)); double maxtravel = maxMouseDistanceAccelThreshold * 0.01; double slope = (magfactor - minfactor) / (maxtravel - mintravel); double intercept = minfactor - (slope * mintravel); double intermediateTravel = qMin(maxtravel, fabs(getAccelerationDistance() - lastAccelerationDistance)); if ((currentAccelMulti > 1.0) && (oldAccelMulti == 0.0)) { intermediateTravel = qMin(maxtravel, intermediateTravel + mintravel); } double currentAccelMultiTemp = (slope * intermediateTravel + intercept); if (extraAccelCurve == EaseOutSineCurve) { double getMultiDiff2 = ((currentAccelMultiTemp - minfactor) / (extraAccelerationMultiplier - minfactor)); currentAccelMultiTemp = (extraAccelerationMultiplier - minfactor) * sin(getMultiDiff2 * (GlobalVariables::JoyControlStick::PI / 2.0)) + minfactor; } else if (extraAccelCurve == EaseOutQuadAccelCurve) { double getMultiDiff2 = ((currentAccelMultiTemp - minfactor) / (extraAccelerationMultiplier - minfactor)); currentAccelMultiTemp = -(extraAccelerationMultiplier - minfactor) * (getMultiDiff2 * (getMultiDiff2 - 2)) + minfactor; } else if (extraAccelCurve == EaseOutCubicAccelCurve) { double getMultiDiff = ((currentAccelMultiTemp - minfactor) / (extraAccelerationMultiplier - minfactor)) - 1; currentAccelMultiTemp = (extraAccelerationMultiplier - minfactor) * ((getMultiDiff) * (getMultiDiff) * (getMultiDiff) + 1) + minfactor; } difference = difference * currentAccelMultiTemp; currentAccelMulti = currentAccelMultiTemp; updateOldAccelMulti = currentAccelMulti; accelTravel = intermediateTravel; accelExtraDurationTime.restart(); } else if (extraAccelerationEnabled && isPartRealAxis() && (accelDuration > 0.0) && (currentAccelMulti > 0.0) && (fabs(getAccelerationDistance() - startingAccelerationDistance) < minstop)) { qDebug() << "Keep Trying: " << fabs(getAccelerationDistance() - lastAccelerationDistance); qDebug() << "MIN TRAVEL: " << mintravel; updateStartingMouseDistance = true; double magfactor = extraAccelerationMultiplier; double minfactor = qMax((GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER * 0.001) + 1.0, magfactor * (startAccelMultiplier * 0.01)); double maxtravel = maxMouseDistanceAccelThreshold * 0.01; double slope = (magfactor - minfactor) / (maxtravel - mintravel); double intercept = minfactor - (slope * mintravel); int elapsedElapsed = accelExtraDurationTime.elapsed(); double intermediateTravel = accelTravel; if (((getAccelerationDistance() - startingAccelerationDistance) >= 0) != (getAccelerationDistance() >= 0)) { // Travelling towards dead zone. Decrease acceleration and duration. intermediateTravel = qMax(intermediateTravel - fabs(getAccelerationDistance() - startingAccelerationDistance), mintravel); } // Linear case double currentAccelMultiTemp = (slope * intermediateTravel + intercept); double elapsedDuration = accelDuration * ((currentAccelMultiTemp - minfactor) / (extraAccelerationMultiplier - minfactor)); switch (extraAccelCurve) { case EaseOutSineCurve: { double multiDiff = ((currentAccelMultiTemp - minfactor) / (extraAccelerationMultiplier - minfactor)); double temp = sin(multiDiff * (GlobalVariables::JoyControlStick::PI / 2.0)); elapsedDuration = accelDuration * temp + 0; currentAccelMultiTemp = (extraAccelerationMultiplier - minfactor) * sin(multiDiff * (GlobalVariables::JoyControlStick::PI / 2.0)) + minfactor; break; } case EaseOutQuadAccelCurve: { double getMultiDiff2 = ((currentAccelMultiTemp - minfactor) / (extraAccelerationMultiplier - minfactor)); double temp = (getMultiDiff2 * (getMultiDiff2 - 2)); elapsedDuration = -accelDuration * temp + 0; currentAccelMultiTemp = -(extraAccelerationMultiplier - minfactor) * temp + minfactor; break; } case EaseOutCubicAccelCurve: { double getMultiDiff = ((currentAccelMultiTemp - minfactor) / (extraAccelerationMultiplier - minfactor)) - 1; double temp = ((getMultiDiff) * (getMultiDiff) * (getMultiDiff) + 1); elapsedDuration = accelDuration * temp + 0; currentAccelMultiTemp = (extraAccelerationMultiplier - minfactor) * temp + minfactor; break; } default: { break; } } double tempAccel = currentAccelMultiTemp; double elapsedDiff = 1.0; if ((elapsedDuration > 0.0) && ((elapsedElapsed * 0.001) < elapsedDuration)) { elapsedDiff = ((elapsedElapsed * 0.001) / elapsedDuration); elapsedDiff = (1.0 - tempAccel) * (elapsedDiff * elapsedDiff * elapsedDiff) + tempAccel; difference = elapsedDiff * difference; // As acceleration is applied, do not update last // distance values when not necessary. updateStartingMouseDistance = false; updateOldAccelMulti = currentAccelMulti; } else { elapsedDiff = 1.0; currentAccelMulti = 0.0; updateOldAccelMulti = 0.0; accelTravel = 0.0; } } else if (extraAccelerationEnabled && isPartRealAxis()) { currentAccelMulti = 0.0; updateStartingMouseDistance = true; oldAccelMulti = updateOldAccelMulti = 0.0; accelTravel = 0.0; } sumDist += difference * (mousespeed * GlobalVariables::JoyButtonSlot::JOYSPEED * timeElapsed) * 0.001; distance = sumDist; switch (mousedirection) { case 1: mouse2 = -distance; break; case 2: mouse2 = distance; break; case 3: mouse1 = -distance; break; case 4: mouse1 = distance; break; } mouseCursorInfo infoX; infoX.code = mouse1; infoX.slot = buttonslot; cursorXSpeeds.append(infoX); mouseCursorInfo infoY; infoY.code = mouse2; infoY.slot = buttonslot; cursorYSpeeds.append(infoY); sumDist = 0; buttonslot->setDistance(sumDist); } else if (mousemode == JoyButton::MouseSpring) { double mouse1 = -2.0; double mouse2 = -2.0; double difference = getMouseDistanceFromDeadZone(); switch (mousedirection) { case 1: setDistanceForSpring(mouseHelper, mouse1, mouse2, -difference); break; case 2: setDistanceForSpring(mouseHelper, mouse1, mouse2, difference); break; case 3: setDistanceForSpring(mouseHelper, mouse2, mouse1, -difference); break; case 4: setDistanceForSpring(mouseHelper, mouse2, mouse1, difference); break; } updateMouseProperties(mouse1, 0.0, springWidth, springHeight, relativeSpring, GlobalVariables::JoyButton::springModeScreen, springXSpeeds, 'X'); updateMouseProperties(mouse2, 0.0, springWidth, springHeight, relativeSpring, GlobalVariables::JoyButton::springModeScreen, springYSpeeds, 'Y'); mouseInterval->restart(); } tempQueue.enqueue(buttonslot); } if (!mouseEventQueue.isEmpty() && !singleShot) buttonslot = mouseEventQueue.dequeue(); else buttonslot = nullptr; } if (!tempQueue.isEmpty()) { while (!tempQueue.isEmpty()) { JoyButtonSlot *tempslot = tempQueue.dequeue(); mouseEventQueue.enqueue(tempslot); } } } } void JoyButton::setDistanceForSpring(JoyButtonMouseHelper &mouseHelper, double &mouseFirstAx, double &mouseSecondAx, double distanceFromDeadZone) { if (mouseHelper.getFirstSpringStatus()) { mouseFirstAx = 0.0; mouseHelper.setFirstSpringStatus(false); } mouseSecondAx = distanceFromDeadZone; } void JoyButton::updateMouseProperties(double newAxisValue, double newSpringDead, int newSpringWidth, int newSpringHeight, bool relatived, int modeScreen, QList &springSpeeds, QChar axis, double newAxisValueY, double newSpringDeadY) { PadderCommon::springModeInfo axisInfo; if (axis == 'X') { axisInfo.displacementX = newAxisValue; axisInfo.springDeadX = newSpringDead; } else if (axis == 'Y') { axisInfo.displacementY = newAxisValue; axisInfo.springDeadY = newSpringDead; } else { axisInfo.displacementX = newAxisValue; axisInfo.springDeadX = newSpringDead; axisInfo.displacementY = newAxisValueY; axisInfo.springDeadY = newSpringDeadY; } axisInfo.width = newSpringWidth; axisInfo.height = newSpringHeight; axisInfo.relative = relatived; axisInfo.screen = modeScreen; springSpeeds.append(axisInfo); } void JoyButton::wheelEventVertical() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *buttonslot = nullptr; if (currentWheelVerticalEvent != nullptr) buttonslot = currentWheelVerticalEvent; if (buttonslot && (wheelSpeedY != 0)) { bool isActive = getActiveSlots().contains(buttonslot); if (isActive) { sendevent(buttonslot, true); sendevent(buttonslot, false); mouseWheelVerticalEventQueue.enqueue(buttonslot); mouseWheelVerticalEventTimer.start(1000 / wheelSpeedY); } else { mouseWheelVerticalEventTimer.stop(); } } else if (!mouseWheelVerticalEventQueue.isEmpty() && (wheelSpeedY != 0)) { QQueue tempQueue; while (!mouseWheelVerticalEventQueue.isEmpty()) { buttonslot = mouseWheelVerticalEventQueue.dequeue(); bool isActive = getActiveSlots().contains(buttonslot); if (isActive) { sendevent(buttonslot, true); sendevent(buttonslot, false); tempQueue.enqueue(buttonslot); } } if (!tempQueue.isEmpty()) { mouseWheelVerticalEventQueue = tempQueue; mouseWheelVerticalEventTimer.start(1000 / wheelSpeedY); } else { mouseWheelVerticalEventTimer.stop(); } } else { mouseWheelVerticalEventTimer.stop(); } } void JoyButton::wheelEventHorizontal() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *buttonslot = nullptr; if (currentWheelHorizontalEvent != nullptr) buttonslot = currentWheelHorizontalEvent; if (buttonslot && (wheelSpeedX != 0)) { bool isActive = getActiveSlots().contains(buttonslot); if (isActive) { sendevent(buttonslot, true); sendevent(buttonslot, false); mouseWheelHorizontalEventQueue.enqueue(buttonslot); mouseWheelHorizontalEventTimer.start(1000 / wheelSpeedX); } else { mouseWheelHorizontalEventTimer.stop(); } } else if (!mouseWheelHorizontalEventQueue.isEmpty() && (wheelSpeedX != 0)) { QQueue tempQueue; while (!mouseWheelHorizontalEventQueue.isEmpty()) { buttonslot = mouseWheelHorizontalEventQueue.dequeue(); bool isActive = getActiveSlots().contains(buttonslot); if (isActive) { sendevent(buttonslot, true); sendevent(buttonslot, false); tempQueue.enqueue(buttonslot); } } if (!tempQueue.isEmpty()) { mouseWheelHorizontalEventQueue = tempQueue; mouseWheelHorizontalEventTimer.start(1000 / wheelSpeedX); } else { mouseWheelHorizontalEventTimer.stop(); } } else { mouseWheelHorizontalEventTimer.stop(); } } void JoyButton::setUseTurbo(bool useTurbo) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool initialState = m_useTurbo; if (useTurbo != m_useTurbo) { if (useTurbo && this->containsSequence()) m_useTurbo = false; else m_useTurbo = useTurbo; if (initialState != m_useTurbo) { emit turboChanged(m_useTurbo); emit propertyUpdated(); if (m_useTurbo && (this->turboInterval == 0)) this->setTurboInterval(GlobalVariables::JoyButton::ENABLEDTURBODEFAULT); } } } bool JoyButton::isUsingTurbo() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_useTurbo; } QString JoyButton::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyButton::xmlName; } QString JoyButton::getName(bool forceFullFormat, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString newlabel = getPartialName(forceFullFormat, displayNames); qDebug() << "partial name is: " << newlabel; newlabel.append(": "); qDebug() << "actionName is " << actionName; if (!actionName.isEmpty() && displayNames) newlabel.append(actionName); else newlabel.append(getCalculatedActiveZoneSummary()); qDebug() << "name in getName(bool forceFullFormat, bool displayNames) is now: " << newlabel; return newlabel; } QString JoyButton::getPartialName(bool forceFullFormat, bool displayNames) const { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (!buttonName.isEmpty() && displayNames) { if (forceFullFormat) temp.append(tr("Button")).append(" "); temp.append(buttonName); } else if (!defaultButtonName.isEmpty()) { if (forceFullFormat) temp.append(tr("Button")).append(" "); temp.append(defaultButtonName); } else { temp.append(tr("Button")).append(" ").append(QString::number(getRealJoyNumber())); } return temp; } /** * @brief Generate a string representing a summary of the slots currently * assigned to a button * @return String of currently assigned slots */ QString JoyButton::getSlotsSummary() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString newlabel = QString(); int slotCount = getAssignedSlots()->size(); if (slotCount > 0) { QListIterator iter(*getAssignedSlots()); QStringList stringlist = QStringList(); int i = 0; while (iter.hasNext()) { JoyButtonSlot *slot = iter.next(); stringlist.append(slot->getSlotString()); i++; if ((i > 4) && iter.hasNext()) { stringlist.append(" ..."); iter.toBack(); } } newlabel = stringlist.join(", "); } else { newlabel = newlabel.append(tr("[NO KEY]")); } return newlabel; } /** * @brief Generate a string that represents slots that will be activated or * slots that are currently active if a button is pressed * @return String of currently applicable slots for a button */ QString JoyButton::getActiveZoneSummary() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList tempList = getActiveZoneList(); return buildActiveZoneSummary(tempList); } QString JoyButton::getCalculatedActiveZoneSummary() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); lockForWritedString(temp, activeZoneString); return temp; } /** * @brief Generate active zone string and notify other objects. */ void JoyButton::buildActiveZoneSummaryString() { qInstallMessageHandler(MessageHandler::myMessageOutput); lockForWritedString(activeZoneString, getActiveZoneSummary()); qDebug() << "activeZoneString after getActiveZoneSummary() is: " << activeZoneString; emit activeZoneChanged(); } /** * @brief Generate active zone string but do not notify any other object. */ void JoyButton::localBuildActiveZoneSummaryString() { qInstallMessageHandler(MessageHandler::myMessageOutput); lockForWritedString(activeZoneString, getActiveZoneSummary()); } QString JoyButton::buildActiveZoneSummary(QList &tempList) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString newlabel = QString(); QListIterator iter(tempList); QListIterator *iterMain(&iter); QStringList stringlist = QStringList(); QStringList stringListMix = QStringList(); int i = 0; int j = 0; bool slotsActive = !getActiveSlots().isEmpty(); if (setSelectionCondition == SetChangeOneWay) { newlabel.append(tr("[Set %1 1W]").arg(setSelection + 1)); if (iterMain->hasNext()) newlabel.append(" "); } else if (setSelectionCondition == SetChangeTwoWay) { newlabel = newlabel.append(tr("[Set %1 2W]").arg(setSelection + 1)); if (iterMain->hasNext()) newlabel.append(" "); } if (setSelectionCondition == SetChangeWhileHeld) { newlabel.append(tr("[Set %1 WH]").arg(setSelection + 1)); } else if (iterMain->hasNext()) { bool behindHold = false; while (iterMain->hasNext()) { JoyButtonSlot *slot = iterMain->next(); JoyButtonSlot::JoySlotInputAction mode = slot->getSlotMode(); if (mode == JoyButtonSlot::JoySlotInputAction::JoyMix) { QListIterator iterMini(*slot->getMixSlots()); QListIterator *iterM(&iterMini); while (iterM->hasNext()) { JoyButtonSlot *slotMini = iterM->next(); JoyButtonSlot::JoySlotInputAction modeMini = slotMini->getSlotMode(); qDebug() << "modeMini is " << modeMini; qDebug() << "slotsActive are empty? " << slotsActive; buildActiveZoneSummarySwitchSlots(modeMini, slotMini, behindHold, &stringListMix, j, iterM, slotsActive); stringListMix.append("+"); qDebug() << "Create summary for JoyMix. Progress: " << stringListMix; } j = 0; i++; if (!stringListMix.isEmpty()) { if (stringListMix.last() == '+') stringListMix.removeLast(); qDebug() << "Create summary for JoyMix. Progress: " << stringListMix; QString res = ""; for (const QString &strListEl : stringListMix) res += strListEl; stringlist.append(res); stringListMix.clear(); } else { stringlist.append(slot->getTextData()); stringListMix.clear(); } behindHold = false; } else { buildActiveZoneSummarySwitchSlots(mode, slot, behindHold, &stringlist, i, iterMain, slotsActive); } if ((i > 4) && iterMain->hasNext()) { stringlist.append(" ..."); iterMain->toBack(); } } newlabel.append(stringlist.join(", ")); } else if (setSelectionCondition == SetChangeDisabled) { newlabel.append(tr("[NO KEY]")); } qDebug() << "NEW LABEL IS: " << newlabel; qDebug() << "i: " << i; qDebug() << "j: " << j; return newlabel; } void JoyButton::buildActiveZoneSummarySwitchSlots(JoyButtonSlot::JoySlotInputAction mode, JoyButtonSlot *slot, bool &behindHold, QStringList *stringlist, int &i, QListIterator *iter, bool slotsActive) { switch (mode) { case JoyButtonSlot::JoyKeyboard: case JoyButtonSlot::JoyMouseButton: case JoyButtonSlot::JoyMouseMovement: { QString temp = slot->getSlotString(); if (behindHold) { temp.prepend("[H] "); behindHold = false; } stringlist->append(temp); i++; break; } case JoyButtonSlot::JoyKeyPress: { // Skip slot if a press time slot was inserted. break; } case JoyButtonSlot::JoyHold: { if (!slotsActive && (i == 0)) { // If button is not active and first slot is a hold, // keep processing slots but take note of the hold. behindHold = true; } else { // Move iter to back so loop will end. iter->toBack(); } break; } case JoyButtonSlot::JoyLoadProfile: case JoyButtonSlot::JoySetChange: case JoyButtonSlot::JoyTextEntry: case JoyButtonSlot::JoyExecute: { QString temp = slot->getSlotString(); if (behindHold) { temp.prepend("[H] "); behindHold = false; } stringlist->append(temp); i++; break; } case JoyButtonSlot::JoyRelease: { if (currentRelease == nullptr) findJoySlotsEnd(iter); break; } case JoyButtonSlot::JoyDistance: { iter->toBack(); break; } case JoyButtonSlot::JoyDelay: { iter->toBack(); break; } case JoyButtonSlot::JoyCycle: { iter->toBack(); break; } default: if (mode > 15 || mode < 0) { QString temp = slot->getSlotString(); if (behindHold) { temp.prepend("[H] "); behindHold = false; } stringlist->append(temp); i++; break; } break; } } QList JoyButton::getActiveZoneList() { qInstallMessageHandler(MessageHandler::myMessageOutput); QListIterator activeSlotsIter(getActiveSlots()); QListIterator assignmentsIter(*getAssignedSlots()); QListIterator *iter = nullptr; QReadWriteLock *tempLock = nullptr; qDebug() << "Active slots are: "; int x, y; x = 0; y = 0; for (auto actSlot : getActiveSlots()) { x++; qDebug() << x << ") " << actSlot->getSlotString(); } qDebug() << "Assigned slots are: "; for (auto assignedSlot : *getAssignedSlots()) { y++; qDebug() << y << ") " << assignedSlot->getSlotString(); } activeZoneLock.lockForRead(); int numActiveSlots = getActiveSlots().size(); activeZoneLock.unlock(); if (numActiveSlots > 0) { tempLock = &activeZoneLock; iter = &activeSlotsIter; } else { tempLock = &assignmentsLock; iter = &assignmentsIter; } QReadLocker tempLocker(tempLock); Q_UNUSED(tempLocker); if (tempLock == &assignmentsLock) { if (previousCycle != nullptr) { qDebug() << "if there exists previous Cycle, find it in activeSlots"; iter->findNext(previousCycle); } } QList tempSlotList; if ((setSelectionCondition != SetChangeWhileHeld) && iter->hasNext()) { while (iter->hasNext()) { JoyButtonSlot *slot = iter->next(); JoyButtonSlot::JoySlotInputAction mode = slot->getSlotMode(); switch (mode) { case JoyButtonSlot::JoyKeyboard: case JoyButtonSlot::JoyMouseButton: case JoyButtonSlot::JoyMouseMovement: case JoyButtonSlot::JoyKeyPress: case JoyButtonSlot::JoyHold: case JoyButtonSlot::JoyLoadProfile: case JoyButtonSlot::JoySetChange: case JoyButtonSlot::JoyTextEntry: case JoyButtonSlot::JoyExecute: case JoyButtonSlot::JoyMix: { tempSlotList.append(slot); break; } case JoyButtonSlot::JoyRelease: { if (currentRelease == nullptr) findJoySlotsEnd(iter); break; } case JoyButtonSlot::JoyDistance: case JoyButtonSlot::JoyCycle: { iter->toBack(); break; } default: { break; } } } } return tempSlotList; } /** * @brief Generate a string representing all the currently assigned slots for * a button * @return String representing all assigned slots for a button */ QString JoyButton::getSlotsString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); if (getAssignedSlots()->size() > 0) { qDebug() << "There is more assignments than 0 in getSlotsString(): " << getAssignedSlots()->count(); QListIterator iter(*getAssignedSlots()); QStringList stringlist = QStringList(); while (iter.hasNext()) { JoyButtonSlot *slot = iter.next(); qDebug() << "deviceCode = " << slot->getSlotCode(); qDebug() << "slotMode = " << slot->getSlotMode(); QString slotString = slot->getSlotString(); if (slotString == tr("[NO KEY]")) { qDebug() << "EMPTY ASSIGNED SLOT"; } stringlist.append(slotString); // tu } label = stringlist.join(", "); } else { qDebug() << "There is no assignments for button in getSlotsString()"; label = label.append(tr("[NO KEY]")); } return label; } void JoyButton::setCustomName(QString name) { qInstallMessageHandler(MessageHandler::myMessageOutput); customName = name; } QString JoyButton::getCustomName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return customName; } /** * @brief Create new JoyButtonSlot with data provided and append the new slot * an existing to the assignment list. * @param Native virtual code being used. * @param Mode of the slot. * @return Whether the new slot was successfully added to the assignment list. */ bool JoyButton::setAssignedSlot(int code, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool slotInserted = false; JoyButtonSlot *slot = new JoyButtonSlot(code, mode, this); if (slot->getSlotMode() == JoyButtonSlot::JoyDistance && (slot->getSlotCode() >= 1) && (slot->getSlotCode() <= 100) && (getTotalSlotDistance(slot) <= 1.0)) { assignmentsLock.lockForWrite(); getAssignmentsLocal().append(slot); assignmentsLock.unlock(); buildActiveZoneSummaryString(); slotInserted = true; } else if (slot->getSlotCode() >= 0) { assignmentsLock.lockForWrite(); getAssignmentsLocal().append(slot); assignmentsLock.unlock(); buildActiveZoneSummaryString(); slotInserted = true; } if (slotInserted) { checkTurboCondition(slot); emit slotsChanged(); } else if (slot != nullptr) { delete slot; slot = nullptr; } return slotInserted; } /** * @brief Create new JoyButtonSlot with data provided and append the new slot * an existing to the assignment list. * @param Native virtual code being used. * @param Qt key alias used for abstracting native virtual code. * @param Mode of the slot. * @return Whether the new slot was successfully added to the assignment list. */ bool JoyButton::setAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool slotInserted = false; JoyButtonSlot *slot = new JoyButtonSlot(code, alias, mode, this); if (slot->getSlotMode() == JoyButtonSlot::JoyDistance && (slot->getSlotCode() >= 1) && (slot->getSlotCode() <= 100) && (getTotalSlotDistance(slot) <= 1.0)) { assignmentsLock.lockForWrite(); getAssignmentsLocal().append(slot); assignmentsLock.unlock(); buildActiveZoneSummaryString(); slotInserted = true; } else if (slot->getSlotCode() >= 0) { assignmentsLock.lockForWrite(); getAssignmentsLocal().append(slot); assignmentsLock.unlock(); buildActiveZoneSummaryString(); slotInserted = true; } if (slotInserted) { checkTurboCondition(slot); emit slotsChanged(); } else if (slot != nullptr) { delete slot; slot = nullptr; } return slotInserted; } /** * @brief Create new JoyButtonSlot with data provided and replace an existing * slot in the assignment list if one exists. * @param Native virtual code being used. * @param Qt key alias used for abstracting native virtual code. * @param Index number in the list. * @param Mode of the slot. * @return Whether the new slot was successfully added to the assignment list. */ bool JoyButton::setAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool permitSlot = true; JoyButtonSlot *slot = new JoyButtonSlot(code, alias, mode, this); if ((slot->getSlotMode() == JoyButtonSlot::JoyDistance) && (slot->getSlotCode() >= 1) && (slot->getSlotCode() <= 100)) { if (getTotalSlotDistance(slot) > 1.0) permitSlot = false; } else if (slot->getSlotCode() < 0) { permitSlot = false; } if (permitSlot) { assignmentsLock.lockForWrite(); if ((index >= 0) && (index < getAssignedSlots()->count())) { // Insert slot and move existing slots. JoyButtonSlot *temp = getAssignedSlots()->at(index); if (temp != nullptr) { delete temp; temp = nullptr; } getAssignmentsLocal().replace(index, slot); } else if (index >= getAssignmentsLocal().count()) { // Append code into a new slot getAssignmentsLocal().append(slot); } checkTurboCondition(slot); assignmentsLock.unlock(); buildActiveZoneSummaryString(); emit slotsChanged(); } else if (slot != nullptr) { delete slot; slot = nullptr; } return permitSlot; } /** * @brief Create new JoyButtonSlot with data provided and insert it into * assignments list if it is valid. * @param Native virtual code being used. * @param Qt key alias used for abstracting native virtual code. * @param Index number in the list. * @param Mode of the slot. * @return Whether the new slot was successfully added to the assignment list. */ bool JoyButton::insertAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool permitSlot = true; JoyButtonSlot *slot = new JoyButtonSlot(code, alias, mode, this); if (slot->getSlotMode() == JoyButtonSlot::JoyDistance && (slot->getSlotCode() >= 1) && (slot->getSlotCode() <= 100)) { if (getTotalSlotDistance(slot) > 1.0) permitSlot = false; } else if (slot->getSlotCode() < 0) { permitSlot = false; } if (permitSlot) { assignmentsLock.lockForWrite(); if ((index >= 0) && (index < getAssignedSlots()->count())) { // Insert new slot into list. Move old slots if needed. getAssignmentsLocal().insert(index, slot); } else if (index >= getAssignedSlots()->count()) { // Append new slot into list. getAssignmentsLocal().append(slot); } qDebug() << "assignments variable in joybutton has now: " << getAssignedSlots()->count() << " input slots"; checkTurboCondition(slot); assignmentsLock.unlock(); buildActiveZoneSummaryString(); emit slotsChanged(); } else if (slot != nullptr) { delete slot; slot = nullptr; } return permitSlot; } bool JoyButton::insertAssignedSlot(JoyButtonSlot *newSlot, bool updateActiveString) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool permitSlot = false; if ((newSlot->getSlotMode() == JoyButtonSlot::JoyDistance) && (newSlot->getSlotCode() >= 1) && (newSlot->getSlotCode() <= 100)) { if (getTotalSlotDistance(newSlot) <= 1.0) permitSlot = true; } else if ((newSlot->getSlotMode() == JoyButtonSlot::JoyTextEntry || newSlot->getSlotMode() == JoyButtonSlot::JoyExecute) && !newSlot->getTextData().isEmpty()) { permitSlot = true; } else if ((newSlot->getSlotMode() == JoyButtonSlot::JoyLoadProfile) || newSlot->getSlotCode() >= 0) { permitSlot = true; } if (permitSlot) { assignmentsLock.lockForWrite(); checkTurboCondition(newSlot); getAssignmentsLocal().append(newSlot); assignmentsLock.unlock(); if (updateActiveString) buildActiveZoneSummaryString(); emit slotsChanged(); } return permitSlot; } bool JoyButton::insertAssignedSlot(JoyButtonSlot *newSlot, int index, bool updateActiveString) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool permitSlot = true; JoyButtonSlot *slot = new JoyButtonSlot(newSlot, this); if (slot->getSlotMode() == JoyButtonSlot::JoyDistance && (slot->getSlotCode() >= 1) && (slot->getSlotCode() <= 100)) { if (getTotalSlotDistance(slot) > 1.0) permitSlot = false; } else if (slot->getSlotCode() < 0) { permitSlot = false; } if (permitSlot) { assignmentsLock.lockForWrite(); if ((index >= 0) && (index < getAssignedSlots()->count())) { // Insert new slot into list. Move old slots if needed. getAssignmentsLocal().insert(index, slot); } else if (index >= getAssignedSlots()->count()) { // Append new slot into list. getAssignmentsLocal().append(slot); } qDebug() << "assignments variable in joybutton has now: " << getAssignedSlots()->count() << " input slots"; checkTurboCondition(slot); assignmentsLock.unlock(); buildActiveZoneSummaryString(); emit slotsChanged(); } else if (slot != nullptr) { /*if (slot->getSlotMode() == 15) { qDeleteAll(*slot->getMixSlots()); }*/ delete slot; slot = nullptr; } return permitSlot; } bool JoyButton::setAssignedSlot(JoyButtonSlot *otherSlot, int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool permitSlot = false; JoyButtonSlot *newslot = new JoyButtonSlot(otherSlot, this); if (newslot->getSlotMode() == JoyButtonSlot::JoyDistance && (newslot->getSlotCode() >= 1) && (newslot->getSlotCode() <= 100)) { if (getTotalSlotDistance(newslot) <= 1.0) permitSlot = true; } else if (newslot->getSlotMode() == JoyButtonSlot::JoyLoadProfile) { permitSlot = true; } else if (newslot->getSlotMode() == JoyButtonSlot::JoyMix && newslot->getMixSlots()->count() > 1) { permitSlot = true; } else if ((newslot->getSlotMode() == JoyButtonSlot::JoyExecute || newslot->getSlotMode() == JoyButtonSlot::JoyTextEntry) && !newslot->getTextData().isEmpty()) { permitSlot = true; } else if (newslot->getSlotCode() >= 0) { permitSlot = true; } if (permitSlot) { assignmentsLock.lockForWrite(); checkTurboCondition(newslot); if ((index >= 0) && (index < getAssignedSlots()->count())) { // Slot already exists. Override code and place into desired slot JoyButtonSlot *temp = getAssignedSlots()->at(index); if (temp->getSlotMode() == JoyButtonSlot::JoySlotInputAction::JoyMix) { for (auto minislot : *temp->getMixSlots()) { delete minislot; minislot = nullptr; } delete temp->getMixSlots(); temp->assignMixSlotsToNull(); } if (temp != nullptr) { delete temp; temp = nullptr; } getAssignmentsLocal().replace(index, newslot); } else if (index >= getAssignmentsLocal().count()) { // Append code into a new slot getAssignmentsLocal().append(newslot); } assignmentsLock.unlock(); buildActiveZoneSummaryString(); emit slotsChanged(); } else if (newslot != nullptr) { delete newslot; newslot = nullptr; } return permitSlot; } QList *JoyButton::getAssignedSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &assignments; } QList const &JoyButton::getActiveSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); return activeSlots; } void JoyButton::setMouseSpeedX(int speed) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((speed >= 1) && (speed <= 300)) { mouseSpeedX = speed; emit propertyUpdated(); } } int JoyButton::getMouseSpeedX() { qInstallMessageHandler(MessageHandler::myMessageOutput); return mouseSpeedX; } void JoyButton::setMouseSpeedY(int speed) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((speed >= 1) && (speed <= 300)) { mouseSpeedY = speed; emit propertyUpdated(); } } int JoyButton::getMouseSpeedY() { qInstallMessageHandler(MessageHandler::myMessageOutput); return mouseSpeedY; } void JoyButton::setChangeSetSelection(int index, bool updateActiveString) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((index >= -1) && (index <= 7)) { setSelection = index; if (updateActiveString) buildActiveZoneSummaryString(); emit propertyUpdated(); } } int JoyButton::getSetSelection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return setSelection; } void JoyButton::setChangeSetCondition(SetChangeCondition condition, bool passive, bool updateActiveString) { qInstallMessageHandler(MessageHandler::myMessageOutput); SetChangeCondition oldCondition = setSelectionCondition; if ((condition != setSelectionCondition) && !passive) { if ((condition == SetChangeWhileHeld) || (condition == SetChangeTwoWay)) { // Set new condition emit setAssignmentChanged(m_index, setSelection, condition); } else if ((setSelectionCondition == SetChangeWhileHeld) || (setSelectionCondition == SetChangeTwoWay)) { // Remove old condition emit setAssignmentChanged(m_index, setSelection, SetChangeDisabled); } setSelectionCondition = condition; } else if (passive) { setSelectionCondition = condition; } if (setSelectionCondition == SetChangeDisabled) setChangeSetSelection(-1); if (setSelectionCondition != oldCondition) { if (updateActiveString) buildActiveZoneSummaryString(); emit propertyUpdated(); } } JoyButton::SetChangeCondition JoyButton::getChangeSetCondition() { qInstallMessageHandler(MessageHandler::myMessageOutput); return setSelectionCondition; } bool JoyButton::getButtonState() { qInstallMessageHandler(MessageHandler::myMessageOutput); return isButtonPressed; } int JoyButton::getOriginSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_originset; } void JoyButton::pauseWaitEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (currentPause != nullptr) { if (!isButtonPressedQueue.isEmpty() && createDeskTimer.isActive()) { if (slotiter != nullptr) { slotiter->toBack(); bool lastIgnoreSetState = ignoreSetQueue.last(); bool lastIsButtonPressed = isButtonPressedQueue.last(); ignoreSetQueue.clear(); isButtonPressedQueue.clear(); ignoreSetQueue.enqueue(lastIgnoreSetState); isButtonPressedQueue.enqueue(lastIsButtonPressed); currentPause = nullptr; currentRelease = nullptr; releaseDeskTimer.stop(); pauseWaitTimer.stop(); slotiter->toFront(); if (previousCycle != nullptr) slotiter->findNext(previousCycle); quitEvent = true; keyPressHold.restart(); } } } if (currentPause != nullptr) { // If release timer is active, temporarily // disable it if (releaseDeskTimer.isActive()) releaseDeskTimer.stop(); if (inpauseHold.elapsed() < currentPause->getSlotCode()) { startTimerOverrun(currentPause->getSlotCode(), &inpauseHold, &pauseWaitTimer, 0); } else { pauseWaitTimer.stop(); createDeskTimer.stop(); currentPause = nullptr; createDeskEvent(); // If release timer was disabled but if the button // is not pressed, restart the release timer. if (!releaseDeskTimer.isActive() && (isButtonPressedQueue.isEmpty() || !isButtonPressedQueue.last())) waitForReleaseDeskEvent(); } } else { pauseWaitTimer.stop(); } } void JoyButton::checkForSetChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!ignoreSetQueue.isEmpty() && !isButtonPressedQueue.isEmpty()) { bool tempFinalState = isButtonPressedQueue.last(); bool tempFinalIgnoreSetsState = ignoreSetQueue.last(); if (!tempFinalIgnoreSetsState) { if (!tempFinalState && (setSelectionCondition == SetChangeOneWay) && (setSelection > -1)) { restartAllForSetChange(); } else if (!tempFinalState && (setSelectionCondition == SetChangeTwoWay) && (setSelection > -1)) { restartAllForSetChange(); } else if ((setSelectionCondition == SetChangeWhileHeld) && (setSelection > -1)) { if (tempFinalState) whileHeldStatus = true; else whileHeldStatus = false; restartAllForSetChange(); } } // Clear queue except for a press if it is last in if (!isButtonPressedQueue.isEmpty()) { isButtonPressedQueue.clear(); if (tempFinalState) isButtonPressedQueue.enqueue(tempFinalState); } // Clear queue except for a press if it is last in if (!ignoreSetQueue.isEmpty()) { bool tempFinalIgnoreSetsState_local = ignoreSetQueue.last(); ignoreSetQueue.clear(); if (tempFinalState) ignoreSetQueue.enqueue(tempFinalIgnoreSetsState_local); } } } void JoyButton::restartAllForSetChange() { if (createDeskTimer.isActive()) createDeskTimer.stop(); if (releaseDeskTimer.isActive()) releaseDeskTimer.stop(); isButtonPressedQueue.clear(); ignoreSetQueue.clear(); emit released(m_index); emit setChangeActivated(setSelection); } void JoyButton::waitForDeskEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (quitEvent && !isButtonPressedQueue.isEmpty() && isButtonPressedQueue.last()) { if (createDeskTimer.isActive()) { keyPressTimer.stop(); createDeskTimer.stop(); releaseDeskTimer.stop(); createDeskEvent(); } else { keyPressTimer.stop(); releaseDeskTimer.stop(); createDeskEvent(); } } else if (!createDeskTimer.isActive()) { #ifdef Q_CC_MSVC createDeskTimer.start(5); releaseDeskTimer.stop(); #else createDeskTimer.start(0); releaseDeskTimer.stop(); #endif } else if (createDeskTimer.isActive()) { // Decrease timer interval of active timer. createDeskTimer.start(0); releaseDeskTimer.stop(); } } void JoyButton::waitForReleaseDeskEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (quitEvent && !keyPressTimer.isActive()) { if (releaseDeskTimer.isActive()) releaseDeskTimer.stop(); createDeskTimer.stop(); keyPressTimer.stop(); releaseDeskEvent(); } else if (!releaseDeskTimer.isActive()) { #ifdef Q_CC_MSVC releaseDeskTimer.start(1); createDeskTimer.stop(); #else releaseDeskTimer.start(1); createDeskTimer.stop(); #endif } else if (releaseDeskTimer.isActive()) { createDeskTimer.stop(); } } bool JoyButton::containsSequence() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; assignmentsLock.lockForRead(); QListIterator tempiter(*getAssignedSlots()); while (tempiter.hasNext()) { JoyButtonSlot *slot = tempiter.next(); JoyButtonSlot::JoySlotInputAction mode = slot->getSlotMode(); if ((mode == JoyButtonSlot::JoyPause) || (mode == JoyButtonSlot::JoyHold) || (mode == JoyButtonSlot::JoyDistance)) { result = true; tempiter.toBack(); } } assignmentsLock.unlock(); return result; } void JoyButton::holdEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (currentHold != nullptr) { bool currentlyPressed = false; if (!isButtonPressedQueue.isEmpty()) currentlyPressed = isButtonPressedQueue.last(); // Activate hold event if (currentlyPressed && (buttonHold.elapsed() > currentHold->getSlotCode())) { qDebug() << buttonHold.elapsed() << " > " << currentHold->getSlotCode(); qDebug() << "Activate hold event"; releaseActiveSlots(); currentHold = nullptr; holdTimer.stop(); buttonHold.restart(); createDeskEvent(); } // Elapsed time has not occurred else if (currentlyPressed) { qDebug() << "Elapsed time has not occurred, because buttonHold: " << buttonHold.elapsed() << " is not greater than currentHoldCode: " << currentHold->getSlotCode(); startTimerOverrun(currentHold->getSlotCode(), &buttonHold, &holdTimer); } // Pre-emptive release else { qDebug() << "Hold button is not pressed"; currentHold = nullptr; holdTimer.stop(); if (slotiter != nullptr) { qDebug() << "slotiter exists"; findJoySlotsEnd(slotiter); createDeskEvent(); } } } else { holdTimer.stop(); } } void JoyButton::startTimerOverrun(int slotCode, QElapsedTimer *currSlotTime, QTimer *currSlotTimer, bool releasedDeskTimer) { int proposedInterval = slotCode - currSlotTime->elapsed(); proposedInterval = (proposedInterval > 0) ? proposedInterval : 0; int newTimerInterval = qMin(10, proposedInterval); currSlotTimer->start(newTimerInterval); if (releasedDeskTimer) { // If release timer is active, push next run until // after keyDelayTimer will timeout again. Helps // reduce CPU usage of an excessively repeating timer. if (releaseDeskTimer.isActive()) releaseDeskTimer.start(proposedInterval); } } void JoyButton::delayEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (currentDelay != nullptr) { bool currentlyPressed = false; if (!isButtonPressedQueue.isEmpty()) currentlyPressed = isButtonPressedQueue.last(); if ((currentDelay != nullptr) && (buttonDelay.elapsed() > currentDelay->getSlotCode())) { // Delay time has elapsed. Continue processing slots. currentDelay = nullptr; delayTimer.stop(); buttonDelay.restart(); createDeskEvent(); } else if (currentlyPressed) { // Elapsed time has not occurred startTimerOverrun(currentDelay->getSlotCode(), &buttonDelay, &delayTimer); } else { // Pre-emptive release currentDelay = nullptr; delayTimer.stop(); } } else { delayTimer.stop(); } } void JoyButton::releaseDeskEvent(bool skipsetchange) { qInstallMessageHandler(MessageHandler::myMessageOutput); quitEvent = false; pauseWaitTimer.stop(); holdTimer.stop(); createDeskTimer.stop(); keyPressTimer.stop(); delayTimer.stop(); setChangeTimer.stop(); releaseActiveSlots(); if (!isButtonPressedQueue.isEmpty() && (currentRelease == nullptr)) releaseSlotEvent(); else currentRelease = nullptr; if (!skipsetchange && (setSelectionCondition != SetChangeDisabled) && !isButtonPressedQueue.isEmpty() && (currentRelease == nullptr)) { bool tempButtonPressed = isButtonPressedQueue.last(); bool tempFinalIgnoreSetsState = ignoreSetQueue.last(); if (!tempButtonPressed && !tempFinalIgnoreSetsState) { if ((setSelectionCondition == SetChangeWhileHeld) && whileHeldStatus) setChangeTimer.start(0); else if (setSelectionCondition != SetChangeWhileHeld) setChangeTimer.start(); } else { changeStatesQueue(false); } } else { changeStatesQueue(true); } if (currentRelease == nullptr) { restartAccelParams(true, true, false); lastMouseDistance = 0.0; currentMouseDistance = 0.0; updateStartingMouseDistance = true; if ((slotiter != nullptr) && !slotiter->hasNext()) { // At the end of the list of assignments. qDebug() << "There is end of slotiter. Set currentCycle and previousCycle as null pointers"; currentCycle = nullptr; previousCycle = nullptr; slotiter->toFront(); } else if ((slotiter != nullptr) && slotiter->hasNext() && (currentCycle != nullptr)) { // Cycle at the end of a segment. qDebug() << "There exists next element in slotiter and exists currentCycle. Skip to currentCycle in slotiter " "starting from beginning"; slotiter->toFront(); slotiter->findNext(currentCycle); } else if ((slotiter != nullptr) && slotiter->hasPrevious() && slotiter->hasNext() && (currentCycle == nullptr)) { // Check if there is a cycle action slot after // current slot. Useful after dealing with pause // actions. qDebug() << "There exists next element and previous element in slotiter but doesn't exists currentCycle. From " "current point in slotiter find JoyButtonSlot::JoyCycle as slotMode and assign to currentCycle"; JoyButtonSlot *tempslot = nullptr; bool exit = false; while (slotiter->hasNext() && !exit) { tempslot = slotiter->next(); if (tempslot->getSlotMode() == JoyButtonSlot::JoyCycle) { currentCycle = tempslot; exit = true; } } // Didn't find any cycle. Move iterator // to the front. if (currentCycle == nullptr) { qDebug() << "Didn't find any cycle. Back to start of slotiter"; slotiter->toFront(); previousCycle = nullptr; } } if (currentCycle != nullptr) { qDebug() << "currentCycle exists and previousCycle will be current but current will be null pointer"; previousCycle = currentCycle; currentCycle = nullptr; } else if ((slotiter != nullptr) && slotiter->hasNext() && containsReleaseSlots()) { qDebug() << "Slotiter has next element on the list. In assignments exists JoyButtonSlot::JoyRelease starting " "from current point. CurrentCycle and previousCycle are set null pointers now"; currentCycle = nullptr; previousCycle = nullptr; slotiter->toFront(); } m_currentDistance = nullptr; this->currentKeyPress = nullptr; quitEvent = true; } } void JoyButton::changeStatesQueue(bool currentReleased) { bool tempFinalState = false; if (!isButtonPressedQueue.isEmpty()) { tempFinalState = isButtonPressedQueue.last(); isButtonPressedQueue.clear(); if (currentReleased) { if (tempFinalState || (currentRelease != nullptr)) isButtonPressedQueue.enqueue(tempFinalState); } else { if (tempFinalState) isButtonPressedQueue.enqueue(tempFinalState); } } if (!ignoreSetQueue.isEmpty()) { bool tempFinalIgnoreSetsState = ignoreSetQueue.last(); ignoreSetQueue.clear(); if (currentReleased) { if (tempFinalState || (currentRelease != nullptr)) ignoreSetQueue.enqueue(tempFinalIgnoreSetsState); } else { if (tempFinalState) ignoreSetQueue.enqueue(tempFinalIgnoreSetsState); } } } /** * @brief Get the distance that an element is away from its assigned * dead zone * @return Normalized distance away from dead zone */ double JoyButton::getDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return isButtonPressed ? 1.0 : 0.0; } double JoyButton::getAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); return this->getDistanceFromDeadZone(); } /** * @brief Get the distance factor that should be used for mouse movement * @return Distance factor that should be used for mouse movement */ double JoyButton::getMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return this->getDistanceFromDeadZone(); } double JoyButton::getTotalSlotDistance(JoyButtonSlot *slot) { qInstallMessageHandler(MessageHandler::myMessageOutput); double tempDistance = 0.0; QListIterator iter(*getAssignedSlots()); while (iter.hasNext()) { JoyButtonSlot *currentSlot = iter.next(); int tempcode = currentSlot->getSlotCode(); JoyButtonSlot::JoySlotInputAction mode = currentSlot->getSlotMode(); if (mode == JoyButtonSlot::JoyDistance) { tempDistance += tempcode / 100.0; if (slot == currentSlot) iter.toBack(); } else if (mode == JoyButtonSlot::JoyCycle) // Reset tempDistance { tempDistance = 0.0; } } return tempDistance; } bool JoyButton::containsDistanceSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QListIterator iter(*getAssignedSlots()); while (iter.hasNext()) { JoyButtonSlot *slot = iter.next(); if (slot->getSlotMode() == JoyButtonSlot::JoyDistance) { result = true; iter.toBack(); } } return result; } void JoyButton::clearAssignedSlots(bool signalEmit) { qInstallMessageHandler(MessageHandler::myMessageOutput); QListIterator iter(*getAssignedSlots()); while (iter.hasNext()) { auto *slot = iter.next(); qDebug() << "AssignedSLot mode: " << slot->getSlotMode(); qDebug() << "cleared assigned slot's mode: " << slot->getSlotMode(); qDebug() << "list of mix slots is a null pointer? " << ((slot->getMixSlots() == nullptr) ? "yes" : "no"); if (slot != nullptr) { if (slot->getMixSlots() != nullptr && slot->getMixSlots() != NULL) { slot->cleanMixSlots(); } delete slot; slot = nullptr; } } getAssignmentsLocal().clear(); if (signalEmit) emit slotsChanged(); } void JoyButton::removeAssignedSlot(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); QWriteLocker tempAssignLocker(&assignmentsLock); int j = 0; qDebug() << "Assigned list slots after joining"; for (auto el : *getAssignedSlots()) { qDebug() << j << ")"; qDebug() << "code: " << el->getSlotCode(); qDebug() << "mode: " << el->getSlotMode(); qDebug() << "string: " << el->getSlotString(); j++; } if ((index >= 0) && (index < getAssignedSlots()->size())) { JoyButtonSlot *slot = getAssignedSlots()->takeAt(index); if (slot->getSlotMode() == JoyButtonSlot::JoyMix) { for (auto minislot : *slot->getMixSlots()) { delete minislot; minislot = nullptr; } slot->getMixSlots()->clear(); delete slot->getMixSlots(); slot->assignMixSlotsToNull(); getAssignedSlots()->removeAt(index); } else { delete slot; slot = nullptr; } tempAssignLocker.unlock(); buildActiveZoneSummaryString(); emit slotsChanged(); } } void JoyButton::clearSlotsEventReset(bool clearSignalEmit) { qWarning() << "RECEIVED"; qInstallMessageHandler(MessageHandler::myMessageOutput); QWriteLocker tempAssignLocker(&assignmentsLock); resetSlotsProp(); stopTimers(true, false, false); releaseActiveSlots(); clearAssignedSlots(clearSignalEmit); clearQueues(); qWarning() << "all current slots and previous slots ale cleared"; } void JoyButton::eventReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QWriteLocker tempAssignLocker(&assignmentsLock); resetSlotsProp(); stopTimers(false, true, false); clearQueues(); qDebug() << "all current slots and previous slots ale cleared"; releaseActiveSlots(); } void JoyButton::releaseActiveSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getActiveSlots().isEmpty()) { QWriteLocker tempLocker(&activeZoneLock); bool changeRepeatState = false; QListIterator iter(getActiveSlots()); iter.toBack(); while (iter.hasPrevious()) { JoyButtonSlot *slot = iter.previous(); int tempcode = slot->getSlotCode(); int references = 0; JoyButtonSlot::JoySlotInputAction mode = slot->getSlotMode(); if (mode == JoyButtonSlot::JoySlotInputAction::JoyMix) { QListIterator iterMini(*slot->getMixSlots()); iterMini.toBack(); // go through all slots in JoyMix slot while (iterMini.hasPrevious()) { JoyButtonSlot *slotMini = iterMini.previous(); int tempcodeMini = slotMini->getSlotCode(); int referencesMini = 0; JoyButtonSlot::JoySlotInputAction mode = slotMini->getSlotMode(); releaseEachSlot(changeRepeatState, referencesMini, tempcodeMini, mode, slotMini); } if (!slot->getMixSlots()->isEmpty()) { qDeleteAll(*slot->getMixSlots()); slot->getMixSlots()->clear(); delete slot->getMixSlots(); slot->assignMixSlotsToNull(); } } else { releaseEachSlot(changeRepeatState, references, tempcode, mode, slot); } } getActiveSlotsLocal().clear(); currentMouseEvent = nullptr; if (!mouseEventQueue.isEmpty()) mouseEventQueue.clear(); pendingMouseButtons.removeAll(this); currentWheelVerticalEvent = nullptr; currentWheelHorizontalEvent = nullptr; mouseWheelVerticalEventTimer.stop(); mouseWheelHorizontalEventTimer.stop(); if (!mouseWheelVerticalEventQueue.isEmpty()) { mouseWheelVerticalEventQueue.clear(); lastWheelVerticalDistance = getMouseDistanceFromDeadZone(); wheelVerticalTime.restart(); } if (!mouseWheelHorizontalEventQueue.isEmpty()) { mouseWheelHorizontalEventQueue.clear(); lastWheelHorizontalDistance = getMouseDistanceFromDeadZone(); wheelHorizontalTime.restart(); } // Check if mouse remainder should be zero. // Only need to check one list from cursor speeds and spring speeds // since the correspond Y lists will be the same size. if ((pendingMouseButtons.length() == 0) && (cursorXSpeeds.length() == 0) && (springXSpeeds.length() == 0)) { GlobalVariables::JoyButton::cursorRemainderX = 0; GlobalVariables::JoyButton::cursorRemainderY = 0; } activeZoneTimer.start(); } } void JoyButton::releaseEachSlot(bool &changeRepeatState, int &references, int tempcode, JoyButtonSlot::JoySlotInputAction mode, JoyButtonSlot *slot) { if (mode == JoyButtonSlot::JoyKeyboard) { countActiveSlots(tempcode, references, slot, GlobalVariables::JoyButton::activeKeys, changeRepeatState, true); if ((lastActiveKey == slot) && (references <= 0)) lastActiveKey = nullptr; } else if (mode == JoyButtonSlot::JoyMouseButton) { if ((tempcode != static_cast(JoyButtonSlot::MouseWheelUp)) && (tempcode != static_cast(JoyButtonSlot::MouseWheelDown)) && (tempcode != static_cast(JoyButtonSlot::MouseWheelLeft)) && (tempcode != static_cast(JoyButtonSlot::MouseWheelRight))) { countActiveSlots(tempcode, references, slot, GlobalVariables::JoyButton::activeMouseButtons, changeRepeatState); } else if ((tempcode == static_cast(JoyButtonSlot::MouseWheelUp)) || (tempcode == static_cast(JoyButtonSlot::MouseWheelDown))) { mouseWheelVerticalEventQueue.removeAll(slot); } else if ((tempcode == static_cast(JoyButtonSlot::MouseWheelLeft)) || (tempcode == static_cast(JoyButtonSlot::MouseWheelRight))) { mouseWheelHorizontalEventQueue.removeAll(slot); } slot->setDistance(0.0); slot->getMouseInterval()->restart(); } else if (mode == JoyButtonSlot::JoyMouseMovement) { JoyMouseMovementMode mousemode = getMouseMode(); if (mousemode == MouseCursor) { QList indexesToRemove; releaseMoveSlots(cursorXSpeeds, slot, indexesToRemove); releaseMoveSlots(cursorYSpeeds, slot, indexesToRemove); slot->getEasingTime()->restart(); slot->setEasingStatus(false); } else if (mousemode == JoyButton::MouseSpring) { double mouse1 = (tempcode == static_cast(JoyButtonSlot::MouseLeft) || tempcode == static_cast(JoyButtonSlot::MouseRight)) ? 0.0 : -2.0; double mouse2 = (tempcode == static_cast(JoyButtonSlot::MouseUp) || tempcode == static_cast(JoyButtonSlot::MouseDown)) ? 0.0 : -2.0; double springDeadCircleX = 0.0; double springDeadCircleY = 0.0; checkSpringDeadCircle(tempcode, springDeadCircleX, JoyButtonSlot::MouseLeft, JoyButtonSlot::MouseRight); checkSpringDeadCircle(tempcode, springDeadCircleY, JoyButtonSlot::MouseUp, JoyButtonSlot::MouseDown); updateMouseProperties(mouse1, springDeadCircleX, springWidth, springHeight, relativeSpring, GlobalVariables::JoyButton::springModeScreen, springXSpeeds, 'n', -2.0, springDeadCircleY); updateMouseProperties(-2.0, springDeadCircleX, springWidth, springHeight, relativeSpring, GlobalVariables::JoyButton::springModeScreen, springYSpeeds, 'n', mouse2, springDeadCircleY); } mouseEventQueue.removeAll(slot); slot->setDistance(0.0); slot->getMouseInterval()->restart(); } else if (mode == JoyButtonSlot::JoyMouseSpeedMod) { int queueLength = mouseSpeedModList.length(); if (!mouseSpeedModList.isEmpty()) { mouseSpeedModList.removeAll(slot); queueLength -= 1; } if (queueLength <= 0) GlobalVariables::JoyButton::mouseSpeedModifier = GlobalVariables::JoyButton::DEFAULTMOUSESPEEDMOD; } else if (mode == JoyButtonSlot::JoySetChange) { currentSetChangeSlot = slot; slotSetChangeTimer.start(); } } void JoyButton::countActiveSlots(int tempcode, int &references, JoyButtonSlot *slot, QHash &activeSlotsHash, bool &changeRepeatState, bool activeSlotHashWindows) { changeRepeatState = false; references = activeSlotsHash.value(tempcode, 1) - 1; if (references <= 0) { sendevent(slot, false); activeSlotsHash.remove(tempcode); } else { activeSlotsHash.insert(tempcode, references); } } void JoyButton::setSpringDeadCircle(double &springDeadCircle, int mouseDirection) { if (getCurrentSpringDeadCircle() > getLastMouseDistanceFromDeadZone()) springDeadCircle = (mouseDirection == JoyButtonSlot::MouseLeft || mouseDirection == JoyButtonSlot::MouseUp) ? -getLastMouseDistanceFromDeadZone() : getLastMouseDistanceFromDeadZone(); else springDeadCircle = (mouseDirection == JoyButtonSlot::MouseLeft || mouseDirection == JoyButtonSlot::MouseUp) ? -getCurrentSpringDeadCircle() : getCurrentSpringDeadCircle(); } void JoyButton::checkSpringDeadCircle(int tempcode, double &springDeadCircle, int mouseSlot1, int mouseSlot2) { if (getSpringDeadCircleMultiplier() > 0) { if (tempcode == mouseSlot1) { setSpringDeadCircle(springDeadCircle, mouseSlot1); } else if (tempcode == mouseSlot2) { setSpringDeadCircle(springDeadCircle, mouseSlot2); } } } void JoyButton::releaseMoveSlots(QList &cursorSpeeds, JoyButtonSlot *slot, QList &indexesToRemove) { QListIterator iter(cursorSpeeds); int i = cursorSpeeds.length(); while (iter.hasNext()) { mouseCursorInfo info = iter.next(); if (info.slot == slot) indexesToRemove.append(i); i++; } QListIterator removeIter(indexesToRemove); while (removeIter.hasPrevious()) { int index = removeIter.previous(); cursorSpeeds.removeAt(index); } indexesToRemove.clear(); } bool JoyButton::containsReleaseSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QListIterator iter(*getAssignedSlots()); while (iter.hasNext()) { if (iter.next()->getSlotMode() == JoyButtonSlot::JoyRelease) { result = true; iter.toBack(); } } return result; } bool JoyButton::containsJoyMixSlot() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QListIterator iter(*getAssignedSlots()); while (iter.hasNext()) { if (iter.next()->getSlotMode() == JoyButtonSlot::JoyMix) { result = true; iter.toBack(); } } return result; } void JoyButton::releaseSlotEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *temp = nullptr; int timeElapsed = buttonHeldRelease.elapsed(); if (containsReleaseSlots()) { QListIterator iter(*getAssignedSlots()); if (previousCycle != nullptr) iter.findNext(previousCycle); int tempElapsed = 0; while (iter.hasNext()) { JoyButtonSlot *currentSlot = iter.next(); int tempcode = currentSlot->getSlotCode(); JoyButtonSlot::JoySlotInputAction mode = currentSlot->getSlotMode(); if (mode == JoyButtonSlot::JoyRelease) { tempElapsed += tempcode; if (tempElapsed <= timeElapsed) temp = currentSlot; else iter.toBack(); } else if (mode == JoyButtonSlot::JoyCycle) { tempElapsed = 0; iter.toBack(); } } if ((temp != nullptr) && (slotiter != nullptr)) { slotiter->toFront(); slotiter->findNext(temp); currentRelease = temp; activateSlots(); if (!keyPressTimer.isActive() && !pauseWaitTimer.isActive()) { releaseActiveSlots(); currentRelease = nullptr; } // Stop hold timer here to be sure that // a hold timer that could be activated // during a release event is stopped. holdTimer.stop(); currentHold = nullptr; } } } void JoyButton::findJoySlotsEnd(QListIterator *slotiter) { if (slotiter != nullptr) { bool found = false; while (!found && slotiter->hasNext()) { qDebug() << "slotiter has next element"; JoyButtonSlot::JoySlotInputAction mode = slotiter->next()->getSlotMode(); switch (mode) { case JoyButtonSlot::JoyRelease: case JoyButtonSlot::JoyCycle: case JoyButtonSlot::JoyHold: found = true; break; default: break; } } if (found && slotiter->hasPrevious()) slotiter->previous(); } } void JoyButton::setVDPad(VDPad *vdpad) { qInstallMessageHandler(MessageHandler::myMessageOutput); joyEvent(false, true); m_vdpad = vdpad; emit propertyUpdated(); } bool JoyButton::isPartVDPad() { qInstallMessageHandler(MessageHandler::myMessageOutput); return (m_vdpad != nullptr); } VDPad *JoyButton::getVDPad() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_vdpad; } void JoyButton::removeVDPad() { qInstallMessageHandler(MessageHandler::myMessageOutput); m_vdpad = nullptr; emit propertyUpdated(); } /** * @brief Check if button properties are at their default values * @return Status of possible property edits */ bool JoyButton::isDefault() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool value = true; value = value && (m_toggle == GlobalVariables::JoyButton::DEFAULTTOGGLE); value = value && (turboInterval == GlobalVariables::JoyButton::DEFAULTTURBOINTERVAL); value = value && (currentTurboMode == NormalTurbo); value = value && (m_useTurbo == GlobalVariables::JoyButton::DEFAULTUSETURBO); value = value && (mouseSpeedX == GlobalVariables::JoyButton::DEFAULTMOUSESPEEDX); value = value && (mouseSpeedY == GlobalVariables::JoyButton::DEFAULTMOUSESPEEDY); value = value && (setSelection == GlobalVariables::JoyButton::DEFAULTSETSELECTION); value = value && (setSelectionCondition == DEFAULTSETCONDITION); value = value && (getAssignedSlots()->isEmpty()); value = value && (mouseMode == DEFAULTMOUSEMODE); value = value && (mouseCurve == DEFAULTMOUSECURVE); value = value && (springWidth == GlobalVariables::JoyButton::DEFAULTSPRINGWIDTH); value = value && (springHeight == GlobalVariables::JoyButton::DEFAULTSPRINGHEIGHT); value = value && qFuzzyCompare(sensitivity, GlobalVariables::JoyButton::DEFAULTSENSITIVITY); value = value && (actionName.isEmpty()); value = value && (wheelSpeedX == GlobalVariables::JoyButton::DEFAULTWHEELX); value = value && (wheelSpeedY == GlobalVariables::JoyButton::DEFAULTWHEELY); value = value && (cycleResetActive == GlobalVariables::JoyButton::DEFAULTCYCLERESETACTIVE); value = value && (cycleResetInterval == GlobalVariables::JoyButton::DEFAULTCYCLERESET); value = value && (relativeSpring == GlobalVariables::JoyButton::DEFAULTRELATIVESPRING); value = value && qFuzzyCompare(m_easingDuration, GlobalVariables::JoyButton::DEFAULTEASINGDURATION); value = value && !extraAccelerationEnabled; value = value && qFuzzyCompare(extraAccelerationMultiplier, GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE); value = value && qFuzzyCompare(minMouseDistanceAccelThreshold, GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD); value = value && qFuzzyCompare(maxMouseDistanceAccelThreshold, GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD); value = value && qFuzzyCompare(startAccelMultiplier, GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER); value = value && qFuzzyCompare(accelDuration, GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION); value = value && (springDeadCircleMultiplier == GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS); value = value && (extraAccelCurve == DEFAULTEXTRAACCELCURVE); return value; } void JoyButton::setIgnoreEventState(bool ignore) { // qInstallMessageHandler(MessageHandler::myMessageOutput); ignoreEvents = ignore; } bool JoyButton::getIgnoreEventState() { qInstallMessageHandler(MessageHandler::myMessageOutput); return ignoreEvents; } void JoyButton::setMouseMode(JoyMouseMovementMode mousemode) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->mouseMode = mousemode; emit propertyUpdated(); } JoyButton::JoyMouseMovementMode JoyButton::getMouseMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); return mouseMode; } void JoyButton::setMouseCurve(JoyMouseCurve selectedCurve) { qInstallMessageHandler(MessageHandler::myMessageOutput); mouseCurve = selectedCurve; emit propertyUpdated(); } JoyButton::JoyMouseCurve JoyButton::getMouseCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); return mouseCurve; } void JoyButton::setSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value >= 0) { springWidth = value; emit propertyUpdated(); } } int JoyButton::getSpringWidth() { qInstallMessageHandler(MessageHandler::myMessageOutput); return springWidth; } void JoyButton::setSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (springHeight >= 0) { springHeight = value; emit propertyUpdated(); } } int JoyButton::getSpringHeight() { qInstallMessageHandler(MessageHandler::myMessageOutput); return springHeight; } void JoyButton::setSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= 0.001) && (value <= 1000)) { sensitivity = value; emit propertyUpdated(); } } double JoyButton::getSensitivity() { qInstallMessageHandler(MessageHandler::myMessageOutput); return sensitivity; } bool JoyButton::getWhileHeldStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); return whileHeldStatus; } void JoyButton::setWhileHeldStatus(bool status) { qInstallMessageHandler(MessageHandler::myMessageOutput); whileHeldStatus = status; } void JoyButton::setActionName(QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((tempName.length() <= 50) && (tempName != actionName)) { actionName = tempName; emit actionNameChanged(); emit propertyUpdated(); } } QString JoyButton::getActionName() { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "Action name is: " << actionName; return actionName; } void JoyButton::setButtonName(QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((tempName.length() <= 20) && (tempName != buttonName)) { buttonName = tempName; emit buttonNameChanged(); emit propertyUpdated(); } } QString JoyButton::getButtonName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return buttonName; } void JoyButton::setWheelSpeed(int speed, QChar ax) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((speed >= 1) && (speed <= 100)) { if (ax == 'X') wheelSpeedX = speed; else if (ax == 'Y') wheelSpeedY = speed; emit propertyUpdated(); } } int JoyButton::getWheelSpeedX() { qInstallMessageHandler(MessageHandler::myMessageOutput); return wheelSpeedX; } int JoyButton::getWheelSpeedY() { qInstallMessageHandler(MessageHandler::myMessageOutput); return wheelSpeedY; } void JoyButton::setDefaultButtonName(QString tempname) { qInstallMessageHandler(MessageHandler::myMessageOutput); defaultButtonName = tempname; } QString JoyButton::getDefaultButtonName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return defaultButtonName; } /** * @brief Take cursor mouse information provided by all buttons and * send a cursor mode mouse event to the display server. */ void JoyButton::moveMouseCursor(int &movedX, int &movedY, int &movedElapsed, QList *mouseHistoryX, QList *mouseHistoryY, QTime *testOldMouseTime, QTimer *staticMouseEventTimer, int mouseRefreshRate, int mouseHistorySize, QList *cursorXSpeeds, QList *cursorYSpeeds, double &cursorRemainderX, double &cursorRemainderY, double weightModifier, int idleMouseRefrRate, QList *pendingMouseButtons) { // qInstallMessageHandler(MessageHandler::myMessageOutput); movedX = 0; movedY = 0; int elapsedTime = testOldMouseTime->elapsed(); movedElapsed = elapsedTime; if (staticMouseEventTimer->interval() < mouseRefreshRate) movedElapsed = mouseRefreshRate + (elapsedTime - staticMouseEventTimer->interval()); if (mouseHistoryX->size() >= mouseHistorySize) mouseHistoryX->removeLast(); if (mouseHistoryY->size() >= mouseHistorySize) mouseHistoryY->removeLast(); /* * Combine all mouse events to find the distance to move the mouse * along the X and Y axis. If necessary, perform mouse smoothing. * The mouse smoothing technique used is an interpretation of the method * outlined at http://flipcode.net/archives/Smooth_Mouse_Filtering.shtml. */ if ((cursorXSpeeds->length() == cursorYSpeeds->length()) && (cursorXSpeeds->length() > 0)) { int queueLength = cursorXSpeeds->length(); double finalx = 0.0; double finaly = 0.0; for (int i = 0; i < queueLength; i++) { mouseCursorInfo infoX = cursorXSpeeds->takeFirst(); mouseCursorInfo infoY = cursorYSpeeds->takeFirst(); distanceForMovingAx(finalx, infoX); distanceForMovingAx(finaly, infoY); infoX.slot->getMouseInterval()->restart(); infoY.slot->getMouseInterval()->restart(); } // Only apply remainder if both current displacement and remainder // follow the same direction. if ((cursorRemainderX >= 0) == (finalx >= 0)) finalx += cursorRemainderX; // Cap maximum relative mouse movement. if (abs(finalx) > 127) finalx = (finalx < 0) ? -127 : 127; mouseHistoryX->prepend(finalx); // Only apply remainder if both current displacement and remainder // follow the same direction. if ((cursorRemainderY >= 0) == (finaly >= 0)) finaly += cursorRemainderY; // Cap maximum relative mouse movement. if (abs(finaly) > 127) finaly = (finaly < 0) ? -127 : 127; mouseHistoryY->prepend(finaly); cursorRemainderX = 0; cursorRemainderY = 0; double adjustedX = 0; double adjustedY = 0; adjustAxForCursor(mouseHistoryX, adjustedX, cursorRemainderX, weightModifier); adjustAxForCursor(mouseHistoryY, adjustedY, cursorRemainderY, weightModifier); // This check is more of a precaution than anything. No need to cause // a sync to happen when not needed. if (!qFuzzyIsNull(adjustedX) || !qFuzzyIsNull(adjustedY)) sendevent(adjustedX, adjustedY); movedX = adjustedX; movedY = adjustedY; } else { mouseHistoryX->prepend(0); mouseHistoryY->prepend(0); } // Check if mouse event timer should use idle time. if (pendingMouseButtons->length() == 0) { if (staticMouseEventTimer->interval() != idleMouseRefrRate) { staticMouseEventTimer->start(idleMouseRefrRate); // Clear current mouse history mouseHistoryX->clear(); mouseHistoryY->clear(); // Fill history with zeroes. for (int i = 0; i < mouseHistorySize; i++) { mouseHistoryX->append(0); mouseHistoryY->append(0); } } cursorRemainderX = 0; cursorRemainderY = 0; } else { if (staticMouseEventTimer->interval() != mouseRefreshRate) staticMouseEventTimer->start(mouseRefreshRate); // Restore intended QTimer interval. } cursorXSpeeds->clear(); cursorYSpeeds->clear(); } void JoyButton::distanceForMovingAx(double &finalAx, mouseCursorInfo infoAx) { if (!qFuzzyIsNull(infoAx.code)) { finalAx = (infoAx.code < 0) ? qMin(infoAx.code, finalAx) : qMax(infoAx.code, finalAx); } } void JoyButton::adjustAxForCursor(QList *mouseHistoryList, double &adjustedAx, double &cursorRemainder, double weightModifier) { double currentWeight = 1.0; double finalWeight = 0.0; QListIterator mouseHist(*mouseHistoryList); while (mouseHist.hasNext()) { adjustedAx += mouseHist.next() * currentWeight; finalWeight += currentWeight; currentWeight *= weightModifier; } if (fabs(adjustedAx) > 0) { adjustedAx = adjustedAx / finalWeight; double oldAx = adjustedAx; if (adjustedAx > 0) adjustedAx = floor(adjustedAx); else adjustedAx = ceil(adjustedAx); cursorRemainder = oldAx - adjustedAx; } } /** * @brief Take spring mouse information provided by all buttons and * send a spring mode mouse event to the display server. */ void JoyButton::moveSpringMouse(int &movedX, int &movedY, bool &hasMoved, int springModeScreen, QList *springXSpeeds, QList *springYSpeeds, QList *pendingMouseButtons, int mouseRefreshRate, int idleMouseRefrRate, QTimer *staticMouseEventTimer) { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::springModeInfo fullSpring = {-2.0, -2.0, 0, 0, false, springModeScreen, 0.0, 0.0}; PadderCommon::springModeInfo relativeSpring = {-2.0, -2.0, 0, 0, false, springModeScreen, 0.0, 0.0}; int realMouseX = movedX = 0; int realMouseY = movedY = 0; hasMoved = false; if ((springXSpeeds->length() == springYSpeeds->length()) && (springXSpeeds->length() > 0)) { bool complete = false; for (int i = (springXSpeeds->length() - 1); (i >= 0) && !complete; i--) { double tempx = -2.0; double tempy = -2.0; double tempSpringDeadX = 0.0; double tempSpringDeadY = 0.0; PadderCommon::springModeInfo infoX; PadderCommon::springModeInfo infoY; infoX = springXSpeeds->takeLast(); infoY = springYSpeeds->takeLast(); tempx = infoX.displacementX; tempy = infoY.displacementY; tempSpringDeadX = infoX.springDeadX; tempSpringDeadY = infoY.springDeadY; if (infoX.relative) { if (qFuzzyCompare(relativeSpring.displacementX, -2.0)) relativeSpring.displacementX = tempx; relativeSpring.relative = true; // Use largest found width for spring // mode dimensions. relativeSpring.width = qMax(infoX.width, relativeSpring.width); } else { if (qFuzzyCompare(fullSpring.displacementX, -2.0)) fullSpring.displacementX = tempx; if (fullSpring.springDeadX == 0.0) fullSpring.springDeadX = tempSpringDeadX; // Use largest found width for spring // mode dimensions. fullSpring.width = qMax(infoX.width, fullSpring.width); } if (infoY.relative) { if (qFuzzyCompare(relativeSpring.displacementY, -2.0)) relativeSpring.displacementY = tempy; relativeSpring.relative = true; // Use largest found height for spring // mode dimensions. relativeSpring.height = qMax(infoX.height, relativeSpring.height); } else { if (qFuzzyCompare(fullSpring.displacementY, -2.0)) fullSpring.displacementY = tempy; if (fullSpring.springDeadY == 0.0) fullSpring.springDeadY = tempSpringDeadY; // Use largest found height for spring // mode dimensions. fullSpring.height = qMax(infoX.height, fullSpring.height); } if ((!qFuzzyCompare(relativeSpring.displacementX, -2.0) && !qFuzzyCompare(relativeSpring.displacementY, -2.0)) && (!qFuzzyCompare(fullSpring.displacementX, -2.0) && !qFuzzyCompare(fullSpring.displacementY, -2.0))) { complete = true; } else if (((relativeSpring.springDeadX != 0.0) && (relativeSpring.springDeadY != 0.0)) && ((fullSpring.springDeadX != 0.0) && (fullSpring.springDeadY != 0.0))) { complete = true; } } fullSpring.screen = springModeScreen; relativeSpring.screen = springModeScreen; if (relativeSpring.relative) { sendSpringEvent(&fullSpring, &relativeSpring, &realMouseX, &realMouseY); } else { if (!hasFutureSpringEvents(JoyButton::getPendingMouseButtons())) { if (fullSpring.springDeadX != 0.0) fullSpring.displacementX = fullSpring.springDeadX; if (fullSpring.springDeadY != 0.0) fullSpring.displacementY = fullSpring.springDeadY; sendSpringEvent(&fullSpring, nullptr, &realMouseX, &realMouseY); } else { sendSpringEvent(&fullSpring, nullptr, &realMouseX, &realMouseY); } } movedX = realMouseX; movedY = realMouseY; hasMoved = true; } // Check if mouse event timer should use idle time. if (pendingMouseButtons->length() == 0) { staticMouseEventTimer->start(idleMouseRefrRate); } else { if (staticMouseEventTimer->interval() != mouseRefreshRate) // Restore intended QTimer interval. staticMouseEventTimer->start(mouseRefreshRate); } springXSpeeds->clear(); springYSpeeds->clear(); } void JoyButton::keyPressEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (keyPressTimer.isActive() && (keyPressHold.elapsed() >= getPreferredKeyPressTime())) { currentKeyPress = nullptr; keyPressTimer.stop(); keyPressHold.restart(); releaseActiveSlots(); createDeskTimer.stop(); if (currentRelease != nullptr) { releaseDeskTimer.stop(); createDeskEvent(); waitForReleaseDeskEvent(); } else { createDeskEvent(); } } else { createDeskTimer.stop(); startTimerOverrun(getPreferredKeyPressTime(), &keyPressHold, &keyPressTimer, true); } } /** * @brief TODO: CHECK IF METHOD WOULD BE USEFUL. CURRENTLY NOT USED. * @return Result */ bool JoyButton::checkForDelaySequence() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QListIterator tempiter(*getAssignedSlots()); // Move iterator to start of cycle. if (previousCycle != nullptr) tempiter.findNext(previousCycle); while (tempiter.hasNext()) { JoyButtonSlot *slot = tempiter.next(); if ((slot->getSlotMode() == JoyButtonSlot::JoyPause) || (slot->getSlotMode() == JoyButtonSlot::JoyRelease)) { result = true; tempiter.toBack(); } else if (slot->getSlotMode() == JoyButtonSlot::JoyCycle) { result = false; tempiter.toBack(); } } return result; } SetJoystick *JoyButton::getParentSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_parentSet; } void JoyButton::checkForPressedSetChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!isButtonPressedQueue.isEmpty() && !whileHeldStatus) { bool tempButtonPressed = isButtonPressedQueue.last(); bool tempFinalIgnoreSetsState = ignoreSetQueue.last(); if (tempButtonPressed && !tempFinalIgnoreSetsState && (setSelectionCondition == SetChangeWhileHeld) && (currentRelease == nullptr)) { setChangeTimer.start(0); quitEvent = true; } } } /** * @brief Obtain the appropriate key press time for the current event. * Order of preference: active key press time slot value -> * profile value -> program default value. * @return Appropriate key press time for current event. */ int JoyButton::getPreferredKeyPressTime() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((currentKeyPress != nullptr) && (currentKeyPress->getSlotCode() > 0)) { return currentKeyPress->getSlotCode(); } else if ((m_parentSet != nullptr) && (m_parentSet->getInputDevice()->getDeviceKeyPressTime() > 0)) { return m_parentSet->getInputDevice()->getDeviceKeyPressTime(); } return GlobalVariables::InputDevice::NUMBER_JOYSETS; } void JoyButton::setCycleResetTime(int interval) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (interval >= GlobalVariables::JoyButton::MINCYCLERESETTIME) cycleResetInterval = qBound(GlobalVariables::JoyButton::MINCYCLERESETTIME, interval, GlobalVariables::JoyButton::MAXCYCLERESETTIME); else cycleResetActive = false; emit propertyUpdated(); } int JoyButton::getCycleResetTime() { qInstallMessageHandler(MessageHandler::myMessageOutput); return cycleResetInterval; } void JoyButton::setCycleResetStatus(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); cycleResetActive = enabled; emit propertyUpdated(); } bool JoyButton::isCycleResetActive() { qInstallMessageHandler(MessageHandler::myMessageOutput); return cycleResetActive; } void JoyButton::establishPropertyUpdatedConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(this, &JoyButton::slotsChanged, m_parentSet->getInputDevice(), &InputDevice::profileEdited); connect(this, &JoyButton::propertyUpdated, m_parentSet->getInputDevice(), &InputDevice::profileEdited); } void JoyButton::disconnectPropertyUpdatedConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(this, &JoyButton::slotsChanged, nullptr, nullptr); disconnect(this, &JoyButton::propertyUpdated, m_parentSet->getInputDevice(), &InputDevice::profileEdited); } /** * @brief Change initial settings used for mouse event timer being used by * the application. */ void JoyButton::establishMouseTimerConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (staticMouseEventTimer.timerType() != Qt::PreciseTimer) staticMouseEventTimer.setTimerType(Qt::PreciseTimer); // Only one connection will be made for each. connect(&staticMouseEventTimer, &QTimer::timeout, &mouseHelper, &JoyButtonMouseHelper::mouseEvent, Qt::UniqueConnection); if (staticMouseEventTimer.interval() != GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE) staticMouseEventTimer.setInterval(GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE); } void JoyButton::setSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value != relativeSpring) { if (value) setSpringDeadCircleMultiplier(0); relativeSpring = value; emit propertyUpdated(); } } bool JoyButton::isRelativeSpring() { qInstallMessageHandler(MessageHandler::myMessageOutput); return relativeSpring; } /** * @brief Copy assignments and properties from one button to another. * Used for set copying. * @param Button instance that should be modified. */ void JoyButton::copyAssignments(JoyButton *destButton) { qInstallMessageHandler(MessageHandler::myMessageOutput); destButton->eventReset(); destButton->assignmentsLock.lockForWrite(); destButton->getAssignmentsLocal().clear(); destButton->assignmentsLock.unlock(); assignmentsLock.lockForWrite(); QListIterator iter(*getAssignedSlots()); while (iter.hasNext()) { JoyButtonSlot *slot = iter.next(); JoyButtonSlot *newslot = new JoyButtonSlot(slot, destButton); destButton->insertAssignedSlot(newslot, false); } assignmentsLock.unlock(); destButton->m_toggle = m_toggle; destButton->turboInterval = turboInterval; destButton->m_useTurbo = m_useTurbo; destButton->mouseSpeedX = mouseSpeedX; destButton->mouseSpeedY = mouseSpeedY; destButton->wheelSpeedX = wheelSpeedX; destButton->wheelSpeedY = wheelSpeedY; destButton->mouseMode = mouseMode; destButton->mouseCurve = mouseCurve; destButton->springWidth = springWidth; destButton->springHeight = springHeight; destButton->sensitivity = sensitivity; destButton->buttonName = buttonName; destButton->actionName = actionName; destButton->cycleResetActive = cycleResetActive; destButton->cycleResetInterval = cycleResetInterval; destButton->relativeSpring = relativeSpring; destButton->currentTurboMode = currentTurboMode; destButton->m_easingDuration = m_easingDuration; destButton->extraAccelerationEnabled = extraAccelerationEnabled; destButton->extraAccelerationMultiplier = extraAccelerationMultiplier; destButton->minMouseDistanceAccelThreshold = minMouseDistanceAccelThreshold; destButton->maxMouseDistanceAccelThreshold = maxMouseDistanceAccelThreshold; destButton->startAccelMultiplier = startAccelMultiplier; destButton->springDeadCircleMultiplier = springDeadCircleMultiplier; destButton->extraAccelCurve = extraAccelCurve; destButton->buildActiveZoneSummaryString(); if (!destButton->isDefault()) emit propertyUpdated(); } /** * @brief Set the turbo mode that the button should use * @param Mode that should be used */ void JoyButton::setTurboMode(TurboMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); currentTurboMode = mode; } /** * @brief Get currently assigned turbo mode * @return Currently assigned turbo mode */ JoyButton::TurboMode JoyButton::getTurboMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentTurboMode; } /** * @brief Check if button should be considered a part of a real controller * axis. Needed for some dialogs so the program won't have to resort to * type checking. * @return Status of being part of a real controller axis */ bool JoyButton::isPartRealAxis() { qInstallMessageHandler(MessageHandler::myMessageOutput); return false; } /** * @brief Calculate maximum mouse speed when using a given mouse curve. * @param Mouse curve * @param Mouse speed value * @return Final mouse speed */ int JoyButton::calculateFinalMouseSpeed(JoyMouseCurve curve, int value, const float joyspeed) { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = joyspeed * value; switch (curve) { case QuadraticExtremeCurve: case EasingQuadraticCurve: case EasingCubicCurve: { result *= 1.5; break; } default: { break; } } return result; } void JoyButton::setEasingDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= GlobalVariables::JoyButton::MINIMUMEASINGDURATION) && (value <= GlobalVariables::JoyButton::MAXIMUMEASINGDURATION) && (!qFuzzyCompare(value, m_easingDuration))) { m_easingDuration = value; emit propertyUpdated(); } } double JoyButton::getEasingDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_easingDuration; } JoyButtonMouseHelper *JoyButton::getMouseHelper() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &mouseHelper; } /** * @brief Get the list of buttons that have a pending mouse movement event. * @return QList* */ QList *JoyButton::getPendingMouseButtons() { // qInstallMessageHandler(MessageHandler::myMessageOutput); return &pendingMouseButtons; } QList *JoyButton::getCursorXSpeeds() { return &cursorXSpeeds; } QList *JoyButton::getCursorYSpeeds() { return &cursorYSpeeds; } QList *JoyButton::getSpringXSpeeds() { return &springXSpeeds; } QList *JoyButton::getSpringYSpeeds() { return &springYSpeeds; } QTimer *JoyButton::getStaticMouseEventTimer() { return &staticMouseEventTimer; } QTime *JoyButton::getTestOldMouseTime() { return &testOldMouseTime; } bool JoyButton::hasCursorEvents(QList *cursorXSpeedsList, QList *cursorYSpeedsList) { // qInstallMessageHandler(MessageHandler::myMessageOutput); return (cursorXSpeedsList->length() != 0) || (cursorYSpeedsList->length() != 0); } bool JoyButton::hasSpringEvents(QList *springXSpeedsList, QList *springYSpeedsList) { // qInstallMessageHandler(MessageHandler::myMessageOutput); return (springXSpeedsList->length() != 0) || (springYSpeedsList->length() != 0); } /** * @brief Set the weight modifier to use for mouse smoothing. * @param Weight modifier in the range of 0.0 - 1.0. */ void JoyButton::setWeightModifier(double modifier, double maxWeightModifier, double &weightModifier) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((modifier >= 0.0) && (modifier <= maxWeightModifier)) weightModifier = modifier; } /** * @brief Set mouse history buffer size used for mouse smoothing. * @param Mouse history buffer size */ void JoyButton::setMouseHistorySize(int size, int maxMouseHistSize, int &mouseHistSize, QList *mouseHistoryX, QList *mouseHistoryY) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((size >= 1) && (size <= maxMouseHistSize)) { mouseHistoryX->clear(); mouseHistoryY->clear(); mouseHistSize = size; } } /** * @brief Set the mouse refresh rate when a mouse slot is active. * @param Refresh rate in ms. */ void JoyButton::setMouseRefreshRate(int refresh, int &mouseRefreshRate, int idleMouseRefrRate, JoyButtonMouseHelper *mouseHelper, QList *mouseHistoryX, QList *mouseHistoryY, QTime *testOldMouseTime, QTimer *staticMouseEventTimer) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((refresh >= 1) && (refresh <= 16)) { mouseRefreshRate = refresh; if (staticMouseEventTimer->isActive()) { testOldMouseTime->restart(); if (staticMouseEventTimer->interval() != idleMouseRefrRate && staticMouseEventTimer->interval() != 0) { QMetaObject::invokeMethod(staticMouseEventTimer, "start", Q_ARG(int, mouseRefreshRate)); } else { // Restart QTimer to keep QTimer in line with QTime QMetaObject::invokeMethod(staticMouseEventTimer, "start", Q_ARG(int, idleMouseRefrRate)); } // Clear current mouse history mouseHistoryX->clear(); mouseHistoryY->clear(); } else { staticMouseEventTimer->setInterval(idleMouseRefrRate); } mouseHelper->carryMouseRefreshRateUpdate(mouseRefreshRate); } } /** * @brief Set the gamepad poll rate to be used in the application. * @param Poll rate in ms. */ void JoyButton::setGamepadRefreshRate(int refresh, int &gamepadRefreshRate, JoyButtonMouseHelper *mouseHelper) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((refresh >= 1) && (refresh <= 16)) { gamepadRefreshRate = refresh; mouseHelper->carryGamePollRateUpdate(gamepadRefreshRate); } } /** * @brief Check if turbo should be disabled for a slot * @param JoyButtonSlot to check */ void JoyButton::checkTurboCondition(JoyButtonSlot *slot) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot::JoySlotInputAction mode = slot->getSlotMode(); switch (mode) { case JoyButtonSlot::JoyPause: case JoyButtonSlot::JoyHold: case JoyButtonSlot::JoyDistance: case JoyButtonSlot::JoyRelease: case JoyButtonSlot::JoyLoadProfile: case JoyButtonSlot::JoySetChange: { setUseTurbo(false); break; } default: { break; } } } void JoyButton::resetProperties() { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "all current slots and previous slots ale cleared"; resetAllProperties(); } void JoyButton::resetAllProperties() { resetSlotsProp(true); actionName.clear(); m_toggle = GlobalVariables::JoyButton::DEFAULTTOGGLE; turboInterval = GlobalVariables::JoyButton::DEFAULTTURBOINTERVAL; currentTurboMode = NormalTurbo; m_useTurbo = GlobalVariables::JoyButton::DEFAULTUSETURBO; isDown = false; toggleActiveState = false; m_useTurbo = false; mouseSpeedX = GlobalVariables::JoyButton::DEFAULTMOUSESPEEDX; mouseSpeedY = GlobalVariables::JoyButton::DEFAULTMOUSESPEEDY; wheelSpeedX = GlobalVariables::JoyButton::DEFAULTWHEELX; wheelSpeedY = GlobalVariables::JoyButton::DEFAULTWHEELY; mouseMode = DEFAULTMOUSEMODE; mouseCurve = DEFAULTMOUSECURVE; springWidth = GlobalVariables::JoyButton::DEFAULTSPRINGWIDTH; springHeight = GlobalVariables::JoyButton::DEFAULTSPRINGHEIGHT; sensitivity = GlobalVariables::JoyButton::DEFAULTSENSITIVITY; setSelection = GlobalVariables::JoyButton::DEFAULTSETSELECTION; setSelectionCondition = DEFAULTSETCONDITION; m_ignoresets = false; ignoreEvents = false; whileHeldStatus = false; buttonName.clear(); actionName.clear(); cycleResetActive = GlobalVariables::JoyButton::DEFAULTCYCLERESETACTIVE; cycleResetInterval = GlobalVariables::JoyButton::DEFAULTCYCLERESET; relativeSpring = GlobalVariables::JoyButton::DEFAULTRELATIVESPRING; lastDistance = 0.0; lastMouseDistance = 0.0; currentMouseDistance = 0.0; updateMouseParams(false, false, 0.0); restartAccelParams(false, false, true); lastWheelVerticalDistance = 0.0; lastWheelHorizontalDistance = 0.0; tempTurboInterval = 0; currentTurboMode = DEFAULTTURBOMODE; m_easingDuration = GlobalVariables::JoyButton::DEFAULTEASINGDURATION; springDeadCircleMultiplier = GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS; updatePendingParams(false, false, false); lockForWritedString(activeZoneString, tr("[NO KEY]")); } bool JoyButton::isModifierButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); return false; } void JoyButton::resetActiveButtonMouseDistances(JoyButtonMouseHelper *mouseHelper) { qInstallMessageHandler(MessageHandler::myMessageOutput); mouseHelper->resetButtonMouseDistances(); } void JoyButton::resetAccelerationDistances() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (updateLastMouseDistance) { lastAccelerationDistance = currentAccelerationDistance; lastMouseDistance = currentMouseDistance; updateLastMouseDistance = false; } if (updateStartingMouseDistance) { startingAccelerationDistance = lastAccelerationDistance; updateStartingMouseDistance = false; } if (updateOldAccelMulti >= 0.0) { oldAccelMulti = updateOldAccelMulti; updateOldAccelMulti = 0.0; } currentAccelerationDistance = getAccelerationDistance(); currentMouseDistance = getMouseDistanceFromDeadZone(); } void JoyButton::initializeDistanceValues() { qInstallMessageHandler(MessageHandler::myMessageOutput); lastAccelerationDistance = getLastAccelerationDistance(); currentAccelerationDistance = getAccelerationDistance(); startingAccelerationDistance = lastAccelerationDistance; lastMouseDistance = getLastMouseDistanceFromDeadZone(); currentMouseDistance = getMouseDistanceFromDeadZone(); } double JoyButton::getLastMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return lastMouseDistance; } double JoyButton::getLastAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); return lastAccelerationDistance; } void JoyButton::copyLastMouseDistanceFromDeadZone(JoyButton *srcButton) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->lastMouseDistance = srcButton->lastMouseDistance; } void JoyButton::copyLastAccelerationDistance(JoyButton *srcButton) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->lastAccelerationDistance = srcButton->lastAccelerationDistance; } bool JoyButton::isExtraAccelerationEnabled() { qInstallMessageHandler(MessageHandler::myMessageOutput); return extraAccelerationEnabled; } double JoyButton::getExtraAccelerationMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); return extraAccelerationMultiplier; } void JoyButton::setExtraAccelerationStatus(bool status) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (isPartRealAxis()) { extraAccelerationEnabled = status; emit propertyUpdated(); } else { extraAccelerationEnabled = false; } } void JoyButton::setExtraAccelerationMultiplier(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= 1.0) && (value <= 200.0)) { extraAccelerationMultiplier = value; emit propertyUpdated(); } } void JoyButton::setMinAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= 1.0) && (value <= 100.0) && (value <= maxMouseDistanceAccelThreshold)) { minMouseDistanceAccelThreshold = value; // emit propertyUpdated(); } } double JoyButton::getMinAccelThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); return minMouseDistanceAccelThreshold; } void JoyButton::setMaxAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= 1.0) && (value <= 100.0) && (value >= minMouseDistanceAccelThreshold)) { maxMouseDistanceAccelThreshold = value; emit propertyUpdated(); } } double JoyButton::getMaxAccelThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); return maxMouseDistanceAccelThreshold; } void JoyButton::setStartAccelMultiplier(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= 0.0) && (value <= 100.0)) { startAccelMultiplier = value; emit propertyUpdated(); } } double JoyButton::getStartAccelMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); return startAccelMultiplier; } void JoyButton::setSpringModeScreen(int screen, int &springModeScreen) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (screen >= -1) springModeScreen = screen; } void JoyButton::setAccelExtraDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= 0.0) && (value <= 5.0)) { accelDuration = value; emit propertyUpdated(); } } double JoyButton::getAccelExtraDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); return accelDuration; } bool JoyButton::hasFutureSpringEvents(QList *pendingMouseButtons) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QListIterator iter(*pendingMouseButtons); while (iter.hasNext()) { JoyButton *temp = iter.next(); if (temp->getMouseMode() == MouseSpring) { result = true; iter.toBack(); } } return result; } void JoyButton::setSpringDeadCircleMultiplier(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((value >= 0) && (value <= 100)) { springDeadCircleMultiplier = value; emit propertyUpdated(); } } int JoyButton::getSpringDeadCircleMultiplier() { return springDeadCircleMultiplier; } double JoyButton::getCurrentSpringDeadCircle() { return (springDeadCircleMultiplier * 0.01); } void JoyButton::restartLastMouseTime(QTime *testOldMouseTime) { testOldMouseTime->restart(); } void JoyButton::setStaticMouseThread(QThread *thread, QTimer *staticMouseEventTimer, QTime *testOldMouseTime, int idleMouseRefrRate, JoyButtonMouseHelper *mouseHelper) { int oldInterval = staticMouseEventTimer->interval(); if (oldInterval == 0) oldInterval = idleMouseRefrRate; staticMouseEventTimer->moveToThread(thread); mouseHelper->moveToThread(thread); QMetaObject::invokeMethod(staticMouseEventTimer, "start", Q_ARG(int, oldInterval)); testOldMouseTime->start(); } void JoyButton::indirectStaticMouseThread(QThread *thread, QTimer *staticMouseEventTimer, JoyButtonMouseHelper *mouseHelper) { QMetaObject::invokeMethod(staticMouseEventTimer, "stop"); QMetaObject::invokeMethod(mouseHelper, "changeThread", Q_ARG(QThread *, thread)); } bool JoyButton::shouldInvokeMouseEvents(QList *pendingMouseButtons, QTimer *staticMouseEventTimer, QTime *testOldMouseTime) { bool result = false; if ((staticMouseEventTimer->interval() == 0) && (pendingMouseButtons->size() > 0) && staticMouseEventTimer->isActive()) result = true; else if ((testOldMouseTime->elapsed() >= staticMouseEventTimer->interval()) && (pendingMouseButtons->size() > 0) && staticMouseEventTimer->isActive()) result = true; return result; } void JoyButton::invokeMouseEvents(JoyButtonMouseHelper *mouseHelper) { mouseHelper->mouseEvent(); } bool JoyButton::hasActiveSlots() { return !getActiveSlots().isEmpty(); } void JoyButton::setExtraAccelerationCurve(JoyExtraAccelerationCurve curve) { extraAccelCurve = curve; emit propertyUpdated(); } JoyButton::JoyExtraAccelerationCurve JoyButton::getExtraAccelerationCurve() { return extraAccelCurve; } void JoyButton::copyExtraAccelerationState(JoyButton *srcButton) { this->currentAccelMulti = srcButton->currentAccelMulti; this->oldAccelMulti = srcButton->oldAccelMulti; this->accelTravel = srcButton->accelTravel; this->startingAccelerationDistance = srcButton->startingAccelerationDistance; this->lastAccelerationDistance = srcButton->lastAccelerationDistance; this->lastMouseDistance = srcButton->lastMouseDistance; this->accelExtraDurationTime.setHMS(srcButton->accelExtraDurationTime.hour(), srcButton->accelExtraDurationTime.minute(), srcButton->accelExtraDurationTime.second(), srcButton->accelExtraDurationTime.msec()); updateMouseParams((srcButton->lastMouseDistance != 0.0), srcButton->updateStartingMouseDistance, srcButton->updateOldAccelMulti); } void JoyButton::setUpdateInitAccel(bool state) { this->updateInitAccelValues = state; } QList &JoyButton::getAssignmentsLocal() { return assignments; } QList &JoyButton::getActiveSlotsLocal() { return activeSlots; } AntiMicroX-antimicrox-2888bf6/src/joybutton.h000066400000000000000000000660521377703515000212710ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTON_H #define JOYBUTTON_H #include "globalvariables.h" #include "joybuttonmousehelper.h" #include "joybuttonslot.h" #include "springmousemoveinfo.h" #include #include #include #include #include #include class VDPad; class SetJoystick; class QXmlStreamReader; class QXmlStreamWriter; // class QThread; class QThreadPool; class JoyButton : public QObject { Q_OBJECT public: explicit JoyButton(int index, int originset, SetJoystick *parentSet, QObject *parent = 0); ~JoyButton(); enum SetChangeCondition { SetChangeDisabled = 0, SetChangeOneWay, SetChangeTwoWay, SetChangeWhileHeld }; enum JoyMouseMovementMode { MouseCursor = 0, MouseSpring }; enum JoyMouseCurve { EnhancedPrecisionCurve = 0, LinearCurve, QuadraticCurve, CubicCurve, QuadraticExtremeCurve, PowerCurve, EasingQuadraticCurve, EasingCubicCurve }; enum JoyExtraAccelerationCurve { LinearAccelCurve, EaseOutSineCurve, EaseOutQuadAccelCurve, EaseOutCubicAccelCurve }; enum TurboMode { NormalTurbo = 0, GradientTurbo, PulseTurbo }; typedef struct _mouseCursorInfo { JoyButtonSlot *slot; double code; } mouseCursorInfo; void joyEvent(bool pressed, bool ignoresets = false); // JoyButtonEvents class void queuePendingEvent(bool pressed, bool ignoresets = false); // JoyButtonEvents class void activatePendingEvent(); // JoyButtonEvents class void setJoyNumber(int index); void clearPendingEvent(); // JoyButtonEvents class void setCustomName(QString name); void copyExtraAccelerationState(JoyButton *srcButton); void setUpdateInitAccel(bool state); void removeVDPad(); void setIgnoreEventState(bool ignore); // JoyButtonEvents class void setMouseMode(JoyMouseMovementMode mousemode); void setMouseCurve(JoyMouseCurve selectedCurve); void setWhileHeldStatus(bool status); void setCycleResetStatus(bool enabled); void copyAssignments(JoyButton *destButton); void resetAccelerationDistances(); void setExtraAccelerationStatus(bool status); void setExtraAccelerationMultiplier(double value); void setCycleResetTime(int interval); // .., unsigned void setMinAccelThreshold(double value); void setExtraAccelerationCurve(JoyExtraAccelerationCurve curve); void setSpringDeadCircleMultiplier(int value); void setAccelExtraDuration(double value); void setStartAccelMultiplier(double value); void setMaxAccelThreshold(double value); void setChangeSetSelection(int index, bool updateActiveString = true); void activateMiniSlots(JoyButtonSlot *slot, JoyButtonSlot *mix); bool hasPendingEvent(); // JoyButtonEvents class bool getToggleState(); bool isUsingTurbo(); bool getButtonState(); bool containsSequence(); bool containsDistanceSlots(); // JoyButtonSlots class bool containsReleaseSlots(); // JoyButtonSlots class bool getIgnoreEventState(); // JoyButtonEvents class bool getWhileHeldStatus(); bool hasActiveSlots(); // JoyButtonSlots class bool isCycleResetActive(); bool isRelativeSpring(); bool isPartVDPad(); bool isExtraAccelerationEnabled(); double getMinAccelThreshold(); double getMaxAccelThreshold(); double getStartAccelMultiplier(); double getAccelExtraDuration(); double getExtraAccelerationMultiplier(); double getSensitivity(); double getEasingDuration(); int getJoyNumber(); int getTurboInterval(); int getMouseSpeedX(); int getMouseSpeedY(); int getWheelSpeedX(); int getWheelSpeedY(); int getSetSelection(); int getOriginSet(); int getSpringWidth(); int getSpringHeight(); int getCycleResetTime(); // unsigned int getSpringDeadCircleMultiplier(); QString getCustomName(); QString getActionName(); QString getButtonName(); QList *getAssignedSlots(); // JoyButtonSlots class QList const &getActiveSlots(); // JoyButtonSlots class virtual bool isPartRealAxis(); virtual bool isModifierButton(); virtual bool isDefault(); virtual int getRealJoyNumber() const; virtual double getDistanceFromDeadZone(); virtual double getMouseDistanceFromDeadZone(); virtual double getLastMouseDistanceFromDeadZone(); virtual double getAccelerationDistance(); virtual double getLastAccelerationDistance(); virtual void initializeDistanceValues(); virtual void setTurboMode(TurboMode mode); virtual void setDefaultButtonName(QString tempname); virtual void copyLastMouseDistanceFromDeadZone( JoyButton *srcButton); // Don't use direct assignment but copying from a current button. virtual void copyLastAccelerationDistance(JoyButton *srcButton); virtual void setVDPad(VDPad *vdpad); virtual void setChangeSetCondition(SetChangeCondition condition, bool passive = false, bool updateActiveString = true); virtual QString getPartialName(bool forceFullFormat = false, bool displayNames = false) const; virtual QString getSlotsSummary(); // JoyButtonSlots class virtual QString getSlotsString(); // JoyButtonSlots class virtual QString getActiveZoneSummary(); virtual QString getCalculatedActiveZoneSummary(); virtual QString getName(bool forceFullFormat = false, bool displayNames = false); virtual QString getXmlName(); // JoyButtonXml class virtual QString getDefaultButtonName(); virtual QList getActiveZoneList(); SetChangeCondition getChangeSetCondition(); VDPad *getVDPad(); JoyMouseMovementMode getMouseMode(); JoyMouseCurve getMouseCurve(); SetJoystick *getParentSet(); TurboMode getTurboMode(); static int calculateFinalMouseSpeed(JoyMouseCurve curve, int value, const float joyspeed); static bool hasCursorEvents(QList *cursorXSpeedsList, QList *cursorYSpeedsList); // JoyButtonEvents class static bool hasSpringEvents(QList *springXSpeedsList, QList *springYSpeedsList); // JoyButtonEvents class static bool shouldInvokeMouseEvents(QList *pendingMouseButtons, QTimer *staticMouseEventTimer, QTime *testOldMouseTime); // JoyButtonEvents class static void setWeightModifier(double modifier, double maxWeightModifier, double &weightModifier); static void moveMouseCursor(int &movedX, int &movedY, int &movedElapsed, QList *mouseHistoryX, QList *mouseHistoryY, QTime *testOldMouseTime, QTimer *staticMouseEventTimer, int mouseRefreshRate, int mouseHistorySize, QList *cursorXSpeeds, QList *cursorYSpeeds, double &cursorRemainderX, double &cursorRemainderY, double weightModifier, int idleMouseRefrRate, QList *pendingMouseButtonse); static void moveSpringMouse(int &movedX, int &movedY, bool &hasMoved, int springModeScreen, QList *springXSpeeds, QList *springYSpeeds, QList *pendingMouseButtons, int mouseRefreshRate, int idleMouseRefrRate, QTimer *staticMouseEventTimer); static void setMouseHistorySize(int size, int maxMouseHistSize, int &mouseHistSize, QList *mouseHistoryX, QList *mouseHistoryY); static void setMouseRefreshRate(int refresh, int &mouseRefreshRate, int idleMouseRefrRate, JoyButtonMouseHelper *mouseHelper, QList *mouseHistoryX, QList *mouseHistoryY, QTime *testOldMouseTime, QTimer *staticMouseEventTimer); static void setSpringModeScreen(int screen, int &springModeScreen); static void resetActiveButtonMouseDistances(JoyButtonMouseHelper *mouseHelper); static void setGamepadRefreshRate(int refresh, int &gamepadRefreshRate, JoyButtonMouseHelper *mouseHelper); static void restartLastMouseTime(QTime *testOldMouseTime); static void setStaticMouseThread(QThread *thread, QTimer *staticMouseEventTimer, QTime *testOldMouseTime, int idleMouseRefrRate, JoyButtonMouseHelper *mouseHelper); static void indirectStaticMouseThread(QThread *thread, QTimer *staticMouseEventTimer, JoyButtonMouseHelper *mouseHelper); static void invokeMouseEvents(JoyButtonMouseHelper *mouseHelper); // JoyButtonEvents class static JoyButtonMouseHelper *getMouseHelper(); static QList *getPendingMouseButtons(); static QList *getCursorXSpeeds(); static QList *getCursorYSpeeds(); static QList *getSpringXSpeeds(); static QList *getSpringYSpeeds(); static QTimer *getStaticMouseEventTimer(); // JoyButtonEvents class static QTime *getTestOldMouseTime(); JoyExtraAccelerationCurve getExtraAccelerationCurve(); static const JoyMouseCurve DEFAULTMOUSECURVE; static const SetChangeCondition DEFAULTSETCONDITION; static const JoyMouseMovementMode DEFAULTMOUSEMODE; static const TurboMode DEFAULTTURBOMODE; static const JoyExtraAccelerationCurve DEFAULTEXTRAACCELCURVE; bool insertAssignedSlot(JoyButtonSlot *slot, bool updateActiveString = true); // JoyButtonSlots class bool insertAssignedSlot(JoyButtonSlot *newSlot, int index, bool updateActiveString = true); bool containsJoyMixSlot(); protected: int getPreferredKeyPressTime(); // unsigned double getTotalSlotDistance(JoyButtonSlot *slot); bool distanceEvent(); // JoyButtonEvents class bool checkForDelaySequence(); void clearAssignedSlots(bool signalEmit = true); // JoyButtonSlots class void releaseSlotEvent(); // JoyButtonEvents class void checkForPressedSetChange(); void checkTurboCondition(JoyButtonSlot *slot); void vdpadPassEvent(bool pressed, bool ignoresets = false); // JoyButtonEvents class void localBuildActiveZoneSummaryString(); static bool hasFutureSpringEvents(QList *pendingMouseButtons); static int timeBetweenMiniSlots; static int allSlotTimeBetweenSlots; virtual double getCurrentSpringDeadCircle(); TurboMode currentTurboMode; QString buildActiveZoneSummary(QList &tempList); static QList mouseSpeedModList; // JoyButtonSlots class static QList cursorXSpeeds; static QList cursorYSpeeds; static QList springXSpeeds; static QList springYSpeeds; static QList pendingMouseButtons; static JoyButtonSlot *lastActiveKey; // JoyButtonSlots class static JoyButtonMouseHelper mouseHelper; int m_index; // Used to denote the SDL index of the actual joypad button int turboInterval; int wheelSpeedX; int wheelSpeedY; int setSelection; int tempTurboInterval; int springDeadCircleMultiplier; bool isButtonPressed; // Used to denote whether the actual joypad button is pressed bool isKeyPressed; // Used to denote whether the virtual key is pressed double lastDistance; double lastWheelVerticalDistance; double lastWheelHorizontalDistance; QTimer turboTimer; QTimer mouseWheelVerticalEventTimer; QTimer mouseWheelHorizontalEventTimer; QElapsedTimer wheelVerticalTime; QElapsedTimer wheelHorizontalTime; QElapsedTimer turboHold; SetJoystick *m_parentSet; // Pointer to set that button is assigned to. SetChangeCondition setSelectionCondition; JoyButtonSlot *currentWheelVerticalEvent; // JoyButtonEvents class JoyButtonSlot *currentWheelHorizontalEvent; // JoyButtonEvents class QQueue ignoreSetQueue; QQueue isButtonPressedQueue; QQueue mouseWheelVerticalEventQueue; // JoyButtonEvents class QQueue mouseWheelHorizontalEventQueue; // JoyButtonEvents class QString buttonName; // User specified button name QString defaultButtonName; // Name used by the system signals: void clicked(int index); void released(int index); void keyChanged(int keycode); void mouseChanged(int mousecode); void setChangeActivated(int index); void setAssignmentChanged(int current_button, int associated_set, int mode); void finishedPause(); void turboChanged(bool state); void toggleChanged(bool state); void turboIntervalChanged(int interval); void slotsChanged(); // JoyButtonSlots class void actionNameChanged(); void buttonNameChanged(); void propertyUpdated(); void activeZoneChanged(); public slots: void setTurboInterval(int interval); void setToggle(bool toggle); void setUseTurbo(bool useTurbo); void setMouseSpeedX(int speed); void setMouseSpeedY(int speed); void setWheelSpeed(int speed, QChar ax); void setSpringWidth(int value); void setSpringHeight(int value); void setSensitivity(double value); void setSpringRelativeStatus(bool value); void setActionName(QString tempName); void setButtonName(QString tempName); void setEasingDuration(double value); void establishPropertyUpdatedConnections(); void disconnectPropertyUpdatedConnections(); void removeAssignedSlot(int index); virtual void reset(); virtual void reset(int index); virtual void resetProperties(); virtual void clearSlotsEventReset(bool clearSignalEmit = true); // JoyButtonEvents class virtual void eventReset(); // JoyButtonEvents class virtual void mouseEvent(); // JoyButtonEvents class static void establishMouseTimerConnections(); bool setAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); // JoyButtonSlots class bool setAssignedSlot(int code, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); // JoyButtonSlots class bool setAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); // JoyButtonSlots class bool setAssignedSlot(JoyButtonSlot *otherSlot, int index); // JoyButtonSlots class bool insertAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); // JoyButtonSlots class void buildActiveZoneSummaryString(); protected slots: virtual void turboEvent(); // JoyButtonEvents class virtual void wheelEventVertical(); // JoyButtonEvents class virtual void wheelEventHorizontal(); // JoyButtonEvents class void createDeskEvent(); // JoyButtonEvents class void releaseDeskEvent(bool skipsetchange = false); // JoyButtonEvents class private slots: void releaseActiveSlots(); // JoyButtonSlots class void activateSlots(); // JoyButtonSlots class void waitForDeskEvent(); // JoyButtonEvents class void waitForReleaseDeskEvent(); // JoyButtonEvents class void holdEvent(); // JoyButtonEvents class void delayEvent(); // JoyButtonEvents class void pauseWaitEvent(); // JoyButtonEvents class void checkForSetChange(); void keyPressEvent(); // JoyButtonEvents class void slotSetChange(); private: inline void updatePendingParams(bool isEvent, bool isPressed, bool areIgnoredSets) { pendingEvent = isEvent; pendingPress = isPressed; pendingIgnoreSets = areIgnoredSets; } inline void updateMouseParams(bool updatedLastDist, bool updatedStartDist, double oldAccelMultiVal) { updateLastMouseDistance = updatedLastDist; updateStartingMouseDistance = updatedStartDist; updateOldAccelMulti = oldAccelMultiVal; } inline void resetSlotsProp(bool currentChangedSlot = false) // JoyButtonSlots class { currentCycle = nullptr; previousCycle = nullptr; currentPause = nullptr; currentHold = nullptr; m_currentDistance = nullptr; currentRawValue = 0; currentMouseEvent = nullptr; currentRelease = nullptr; currentWheelVerticalEvent = nullptr; currentWheelHorizontalEvent = nullptr; currentKeyPress = nullptr; currentDelay = nullptr; if (currentChangedSlot) currentSetChangeSlot = nullptr; isKeyPressed = isButtonPressed = false; quitEvent = true; } inline void stopTimers(bool restartedActiveZoneTimer, bool stoppedActiveZoneTimer, bool stoppedSlotSetTimer) { if (restartedActiveZoneTimer) activeZoneTimer.start(); turboTimer.stop(); pauseWaitTimer.stop(); createDeskTimer.stop(); releaseDeskTimer.stop(); holdTimer.stop(); mouseWheelVerticalEventTimer.stop(); mouseWheelHorizontalEventTimer.stop(); setChangeTimer.stop(); keyPressTimer.stop(); delayTimer.stop(); if (stoppedActiveZoneTimer) activeZoneTimer.stop(); if (stoppedSlotSetTimer) slotSetChangeTimer.stop(); if (slotiter != nullptr) { delete slotiter; slotiter = nullptr; } } inline void clearQueues() { isButtonPressedQueue.clear(); ignoreSetQueue.clear(); mouseEventQueue.clear(); mouseWheelVerticalEventQueue.clear(); mouseWheelHorizontalEventQueue.clear(); } inline void restartAccelParams(bool updatedOldAccel, bool restartedAccelDurTimer, bool restartedRestParams) { lastAccelerationDistance = 0.0; currentAccelMulti = 0.0; currentAccelerationDistance = 0.0; startingAccelerationDistance = 0.0; if (updatedOldAccel) oldAccelMulti = updateOldAccelMulti = 0.0; else oldAccelMulti = 0.0; accelTravel = 0.0; if (restartedAccelDurTimer) accelExtraDurationTime.restart(); if (restartedRestParams) { updateInitAccelValues = true; extraAccelerationEnabled = false; extraAccelerationMultiplier = GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE; minMouseDistanceAccelThreshold = GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD; maxMouseDistanceAccelThreshold = GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD; startAccelMultiplier = GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER; accelDuration = GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION; extraAccelCurve = DEFAULTEXTRAACCELCURVE; } } inline void lockForWritedString(QString ¶m, QString value) { activeZoneStringLock.lockForWrite(); param = value; activeZoneStringLock.unlock(); } void releaseEachSlot(bool &changeRepeatState, int &references, int tempcode, JoyButtonSlot::JoySlotInputAction mode, JoyButtonSlot *slot); void resetAllProperties(); void resetPrivVars(); void restartAllForSetChange(); void startTimerOverrun(int slotCode, QElapsedTimer *currSlotTime, QTimer *currSlotTimer, bool releasedDeskTimer = false); void findJoySlotsEnd(QListIterator *slotiter); void changeStatesQueue(bool currentReleased); void countActiveSlots(int tempcode, int &references, JoyButtonSlot *slot, QHash &activeSlotsHash, bool &changeRepeatState, bool activeSlotHashWindows = false); // JoyButtonSlots class void releaseMoveSlots(QList &cursorSpeeds, JoyButtonSlot *slot, QList &indexesToRemove); // JoyButtonSlots class void setSpringDeadCircle(double &springDeadCircle, int mouseDirection); void checkSpringDeadCircle(int tempcode, double &springDeadCircle, int mouseSlot1, int mouseSlot2); static void distanceForMovingAx(double &finalAx, mouseCursorInfo infoAx); static void adjustAxForCursor(QList *mouseHistoryList, double &adjustedAx, double &cursorRemainder, double weightModifier); void setDistanceForSpring(JoyButtonMouseHelper &mouseHelper, double &mouseFirstAx, double &mouseSecondAx, double distanceFromDeadZone); void changeTurboParams(bool _isKeyPressed, bool isButtonPressed); void updateParamsAfterDistEvent(); // JoyButtonEvents class void startSequenceOfPressActive(bool isTurbo, QString debugText); QList &getAssignmentsLocal(); QList &getActiveSlotsLocal(); // JoyButtonSlots class void updateMouseProperties(double newAxisValue, double newSpringDead, int newSpringWidth, int newSpringHeight, bool relatived, int modeScreen, QList &springSpeeds, QChar axis, double newAxisValueY = 0, double newSpringDeadY = 0); // void getActiveZoneWithAppend(JoyButtonSlot::JoySlotInputAction mode, QList& tempSlotList, // QListIterator *iter, JoyButtonSlot *slot); void buildActiveZoneSummarySwitchSlots(JoyButtonSlot::JoySlotInputAction mode, JoyButtonSlot *slot, bool &behindHold, QStringList *stringlist, int &i, QListIterator *iter, bool slotsActive); bool m_toggle; bool quitEvent; // JoyButtonEvents class bool isDown; bool toggleActiveState; bool m_useTurbo; bool lastUnlessInList; bool m_ignoresets; bool ignoreEvents; // JoyButtonEvents class bool whileHeldStatus; bool updateLastMouseDistance; // Should lastMouseDistance be updated. Set after mouse event. bool updateStartingMouseDistance; // Should startingMouseDistance be updated. Set after acceleration has finally been // applied. bool relativeSpring; bool pendingPress; bool pendingEvent; // JoyButtonEvents class bool pendingIgnoreSets; bool extraAccelerationEnabled; bool cycleResetActive; bool updateInitAccelValues; int mouseSpeedX; int mouseSpeedY; int m_originset; int springWidth; int springHeight; int currentRawValue; int cycleResetInterval; // unsigned double sensitivity; double lastMouseDistance; // Keep track of the previous mouse distance from the previous gamepad poll. double lastAccelerationDistance; // Keep track of the previous full distance from the previous gamepad poll double currentAccelMulti; // Multiplier and time used for acceleration easing. double accelDuration; double oldAccelMulti; double accelTravel; // Track travel when accel started double updateOldAccelMulti; double currentMouseDistance; // Keep track of the current mouse distance after a poll. Used to update lastMouseDistance // later. double currentAccelerationDistance; // Keep track of the current mouse distance after a poll. Used to update // lastMouseDistance later. double startingAccelerationDistance; // Take into account when mouse acceleration started double minMouseDistanceAccelThreshold; double maxMouseDistanceAccelThreshold; double startAccelMultiplier; double m_easingDuration; double extraAccelerationMultiplier; QTimer pauseTimer; QTimer holdTimer; QTimer pauseWaitTimer; QTimer createDeskTimer; QTimer releaseDeskTimer; QTimer setChangeTimer; QTimer keyPressTimer; QTimer delayTimer; QTimer slotSetChangeTimer; QTimer activeZoneTimer; static QTimer staticMouseEventTimer; // JoyButtonEvents class QString customName; QString actionName; QString activeZoneString; QList assignments; QList activeSlots; QListIterator *slotiter; QQueue mouseEventQueue; // JoyButtonEvents class JoyButtonSlot *currentPause; JoyButtonSlot *currentHold; JoyButtonSlot *currentCycle; JoyButtonSlot *previousCycle; JoyButtonSlot *m_currentDistance; JoyButtonSlot *currentMouseEvent; // JoyButtonEvents class JoyButtonSlot *currentRelease; JoyButtonSlot *currentKeyPress; JoyButtonSlot *currentDelay; JoyButtonSlot *currentSetChangeSlot; QElapsedTimer buttonHold; QElapsedTimer pauseHold; QElapsedTimer inpauseHold; QElapsedTimer buttonHeldRelease; QElapsedTimer keyPressHold; QElapsedTimer buttonDelay; QTime accelExtraDurationTime; QElapsedTimer cycleResetHold; static QTime testOldMouseTime; VDPad *m_vdpad; JoyMouseMovementMode mouseMode; JoyMouseCurve mouseCurve; JoyExtraAccelerationCurve extraAccelCurve; QReadWriteLock activeZoneLock; QReadWriteLock assignmentsLock; QReadWriteLock activeZoneStringLock; QThreadPool *threadPool; void addEachSlotToActives(JoyButtonSlot *slot, int &i, bool &delaySequence, bool &exit, QListIterator *slotiter); }; class MiniSlotRun : public QRunnable, public QObject { public: MiniSlotRun(JoyButtonSlot *slot, JoyButtonSlot *slotmini, JoyButton *btn, int milisec) : QObject(btn) , m_slot(slot) , m_slotmini(slotmini) , m_btn(btn) , m_miliseconds(milisec) { } ~MiniSlotRun() {} void run() { this->thread()->wait(m_miliseconds); m_btn->activateMiniSlots(m_slotmini, m_slot); } private: JoyButtonSlot *m_slot; JoyButtonSlot *m_slotmini; JoyButton *m_btn; int m_miliseconds; }; #endif // JOYBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joybuttoncontextmenu.cpp000066400000000000000000000137461377703515000241200ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybuttoncontextmenu.h" #include "common.h" #include "globalvariables.h" #include "inputdevice.h" #include "joybutton.h" #include "messagehandler.h" #include #include #include JoyButtonContextMenu::JoyButtonContextMenu(JoyButton *button, QWidget *parent) : QMenu(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->button = button; connect(this, &JoyButtonContextMenu::aboutToHide, this, &JoyButtonContextMenu::deleteLater); } void JoyButtonContextMenu::buildMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); QAction *action = this->addAction(tr("Toggle")); action->setCheckable(true); action->setChecked(button->getToggleState()); connect(action, &QAction::triggered, this, &JoyButtonContextMenu::switchToggle); action = this->addAction(tr("Turbo")); action->setCheckable(true); action->setChecked(button->isUsingTurbo()); connect(action, &QAction::triggered, this, &JoyButtonContextMenu::switchTurbo); this->addSeparator(); action = this->addAction(tr("Clear")); action->setCheckable(false); connect(action, &QAction::triggered, this, &JoyButtonContextMenu::clearButton); this->addSeparator(); QMenu *setSectionMenu = this->addMenu(tr("Set Select")); action = setSectionMenu->addAction(tr("Disabled")); if (button->getChangeSetCondition() == JoyButton::SetChangeDisabled) { action->setCheckable(true); action->setChecked(true); } connect(action, &QAction::triggered, this, &JoyButtonContextMenu::disableSetMode); setSectionMenu->addSeparator(); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { QMenu *tempSetMenu = setSectionMenu->addMenu(tr("Set %1").arg(i + 1)); int setSelection = i * 3; if (i == button->getSetSelection()) { QFont tempFont = tempSetMenu->menuAction()->font(); tempFont.setBold(true); tempSetMenu->menuAction()->setFont(tempFont); } QActionGroup *tempGroup = new QActionGroup(tempSetMenu); createActionForGroup(tempGroup, tr("Set %1 1W"), action, tempSetMenu, setSelection, i, 0, 1); createActionForGroup(tempGroup, tr("Set %1 2W"), action, tempSetMenu, setSelection, i, 1, 2); createActionForGroup(tempGroup, tr("Set %1 WH"), action, tempSetMenu, setSelection, i, 2, 3); if (i == button->getParentSet()->getIndex()) tempSetMenu->setEnabled(false); } PadderCommon::inputDaemonMutex.unlock(); } void JoyButtonContextMenu::createActionForGroup(QActionGroup *tempGroup, QString actionText, QAction *action, QMenu *tempSetMenu, int setSelection, int currentSelection, int setDataInc, int setCondition) { action = tempSetMenu->addAction(actionText.arg(currentSelection + 1)); action->setData(QVariant(setSelection + setDataInc)); action->setCheckable(true); if ((button->getSetSelection() == currentSelection) && (button->getChangeSetCondition() == static_cast(setCondition))) { action->setChecked(true); } connect(action, &QAction::triggered, this, [this, action]() { switchSetMode(action); }); tempGroup->addAction(action); } void JoyButtonContextMenu::switchToggle() { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); button->setToggle(!button->getToggleState()); PadderCommon::inputDaemonMutex.unlock(); } void JoyButtonContextMenu::switchTurbo() { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); button->setUseTurbo(!button->isUsingTurbo()); PadderCommon::inputDaemonMutex.unlock(); } void JoyButtonContextMenu::switchSetMode(QAction *action) { qInstallMessageHandler(MessageHandler::myMessageOutput); int item = action->data().toInt(); int setSelection = item / 3; int setChangeCondition = item % 3; JoyButton::SetChangeCondition temp = JoyButton::SetChangeOneWay; switch (setChangeCondition) { case 0: temp = JoyButton::SetChangeOneWay; break; case 1: temp = JoyButton::SetChangeTwoWay; break; case 2: temp = JoyButton::SetChangeWhileHeld; break; } PadderCommon::inputDaemonMutex.lock(); // First, remove old condition for the button in both sets. // After that, make the new assignment. button->setChangeSetCondition(JoyButton::SetChangeDisabled); button->setChangeSetSelection(setSelection); button->setChangeSetCondition(temp); PadderCommon::inputDaemonMutex.unlock(); } void JoyButtonContextMenu::disableSetMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); button->setChangeSetCondition(JoyButton::SetChangeDisabled); PadderCommon::inputDaemonMutex.unlock(); } void JoyButtonContextMenu::clearButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMetaObject::invokeMethod(button, "clearSlotsEventReset"); } AntiMicroX-antimicrox-2888bf6/src/joybuttoncontextmenu.h000066400000000000000000000030231377703515000235500ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTONCONTEXTMENU_H #define JOYBUTTONCONTEXTMENU_H #include class JoyButton; class QWidget; class JoyButtonContextMenu : public QMenu { Q_OBJECT public: explicit JoyButtonContextMenu(JoyButton *button, QWidget *parent = nullptr); void buildMenu(); protected: JoyButton *button; private slots: void switchToggle(); void switchTurbo(); void switchSetMode(QAction *action); void disableSetMode(); void clearButton(); void createActionForGroup(QActionGroup *tempGroup, QString actionText, QAction *action, QMenu *tempSetMenu, int setSelection, int currentSelection, int setDataInc, int setCondition); }; #endif // JOYBUTTONCONTEXTMENU_H AntiMicroX-antimicrox-2888bf6/src/joybuttonmousehelper.cpp000066400000000000000000000123231377703515000240650ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybuttonmousehelper.h" #include "globalvariables.h" #include "joybutton.h" #include "messagehandler.h" #include #include #include JoyButtonMouseHelper::JoyButtonMouseHelper(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); firstSpringEvent = false; } /** * @brief Perform mouse movement in cursor mode. */ void JoyButtonMouseHelper::moveMouseCursor() { // qInstallMessageHandler(MessageHandler::myMessageOutput); int finalx = 0; int finaly = 0; int elapsedTime = 5; JoyButton::moveMouseCursor(finalx, finaly, elapsedTime, &GlobalVariables::JoyButton::mouseHistoryX, &GlobalVariables::JoyButton::mouseHistoryY, JoyButton::getTestOldMouseTime(), JoyButton::getStaticMouseEventTimer(), GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::mouseHistorySize, JoyButton::getCursorXSpeeds(), JoyButton::getCursorYSpeeds(), GlobalVariables::JoyButton::cursorRemainderX, GlobalVariables::JoyButton::cursorRemainderY, GlobalVariables::JoyButton::weightModifier, GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE, JoyButton::getPendingMouseButtons()); if ((finalx != 0) || (finaly != 0)) emit mouseCursorMoved(finalx, finaly, elapsedTime); } /** * @brief Perform mouse movement in spring mode. */ void JoyButtonMouseHelper::moveSpringMouse() { qInstallMessageHandler(MessageHandler::myMessageOutput); int finalx = 0; int finaly = 0; bool hasMoved = false; JoyButton::moveSpringMouse(finalx, finaly, hasMoved, GlobalVariables::JoyButton::springModeScreen, JoyButton::getSpringXSpeeds(), JoyButton::getSpringYSpeeds(), JoyButton::getPendingMouseButtons(), GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE, JoyButton::getStaticMouseEventTimer()); if (hasMoved) emit mouseSpringMoved(finalx, finaly); } /** * @brief Perform mouse events for all buttons and slots. */ void JoyButtonMouseHelper::mouseEvent() { // qInstallMessageHandler(MessageHandler::myMessageOutput); if (!JoyButton::hasCursorEvents(JoyButton::getCursorXSpeeds(), JoyButton::getCursorYSpeeds()) && !JoyButton::hasSpringEvents(JoyButton::getSpringXSpeeds(), JoyButton::getSpringYSpeeds())) { QList *buttonList = JoyButton::getPendingMouseButtons(); QListIterator iter(*buttonList); while (iter.hasNext()) { JoyButton *temp = iter.next(); temp->mouseEvent(); } } moveMouseCursor(); if (JoyButton::hasSpringEvents(JoyButton::getSpringXSpeeds(), JoyButton::getSpringYSpeeds())) { moveSpringMouse(); } JoyButton::restartLastMouseTime(JoyButton::getTestOldMouseTime()); firstSpringEvent = false; } void JoyButtonMouseHelper::resetButtonMouseDistances() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList *buttonList = JoyButton::getPendingMouseButtons(); QListIterator iter(*buttonList); while (iter.hasNext()) { JoyButton *temp = iter.next(); temp->resetAccelerationDistances(); } } void JoyButtonMouseHelper::setFirstSpringStatus(bool status) { qInstallMessageHandler(MessageHandler::myMessageOutput); firstSpringEvent = status; } bool JoyButtonMouseHelper::getFirstSpringStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); return firstSpringEvent; } void JoyButtonMouseHelper::carryGamePollRateUpdate(int pollRate) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit gamepadRefreshRateUpdated(pollRate); } void JoyButtonMouseHelper::carryMouseRefreshRateUpdate(int refreshRate) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit mouseRefreshRateUpdated(refreshRate); } void JoyButtonMouseHelper::changeThread(QThread *thread) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::setStaticMouseThread(thread, JoyButton::getStaticMouseEventTimer(), JoyButton::getTestOldMouseTime(), GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE, JoyButton::getMouseHelper()); } AntiMicroX-antimicrox-2888bf6/src/joybuttonmousehelper.h000066400000000000000000000032551377703515000235360ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTONMOUSEHELPER_H #define JOYBUTTONMOUSEHELPER_H #include class QThread; class JoyButtonMouseHelper : public QObject { Q_OBJECT public: explicit JoyButtonMouseHelper(QObject *parent = nullptr); void resetButtonMouseDistances(); void setFirstSpringStatus(bool status); bool getFirstSpringStatus(); void carryGamePollRateUpdate(int pollRate); void carryMouseRefreshRateUpdate(int refreshRate); signals: void mouseCursorMoved(int mouseX, int mouseY, int elapsed); void mouseSpringMoved(int mouseX, int mouseY); void gamepadRefreshRateUpdated(int pollRate); void mouseRefreshRateUpdated(int refreshRate); public slots: void moveMouseCursor(); void moveSpringMouse(); void mouseEvent(); void changeThread(QThread *thread); private: bool firstSpringEvent; }; #endif // JOYBUTTONMOUSEHELPER_H AntiMicroX-antimicrox-2888bf6/src/joybuttonslot.cpp000066400000000000000000000372531377703515000225270ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybuttonslot.h" #include "antkeymapper.h" #include "event.h" #include "globalvariables.h" #include "inputdevice.h" #include "messagehandler.h" #include #include JoyButtonSlot::JoyButtonSlot(QObject *parent) : QObject(parent) , extraData() { qInstallMessageHandler(MessageHandler::myMessageOutput); deviceCode = 0; m_mode = JoyKeyboard; m_distance = 0.0; previousDistance = 0.0; qkeyaliasCode = 0; easingActive = false; mix_slots = nullptr; } JoyButtonSlot::JoyButtonSlot(int code, JoySlotInputAction mode, QObject *parent) : QObject(parent) , extraData() { qInstallMessageHandler(MessageHandler::myMessageOutput); deviceCode = 0; qkeyaliasCode = 0; if (code > 0) deviceCode = code; m_mode = mode; m_distance = 0.0; easingActive = false; mix_slots = nullptr; } JoyButtonSlot::JoyButtonSlot(int code, int alias, JoySlotInputAction mode, QObject *parent) : QObject(parent) , extraData() { qInstallMessageHandler(MessageHandler::myMessageOutput); deviceCode = 0; qkeyaliasCode = 0; if (code > 0) deviceCode = code; if (alias > 0) qkeyaliasCode = alias; m_mode = mode; m_distance = 0.0; easingActive = false; mix_slots = nullptr; } JoyButtonSlot::JoyButtonSlot(JoyButtonSlot *slot, QObject *parent) : QObject(parent) , extraData() { qInstallMessageHandler(MessageHandler::myMessageOutput); this->deviceCode = slot->getSlotCode(); this->m_mode = slot->getSlotMode(); this->qkeyaliasCode = slot->getSlotCodeAlias(); this->m_distance = slot->getDistance(); this->previousDistance = slot->getPreviousDistance(); this->easingActive = slot->isEasingActive(); this->easingTime.fromString(slot->getEasingTime()->toString()); this->extraData = slot->getExtraData(); /* * if (slot->getMixSlots() != nullptr) { secureMixSlotsInit(); for(auto minislot : *slot->getMixSlots()) { this->mix_slots->append(new JoyButtonSlot(minislot->getSlotCode(), minislot->getSlotCodeAlias(), minislot->getSlotMode())); } }*/ if (slot->getMixSlots() != nullptr) this->mix_slots = slot->getMixSlots(); if (!slot->getTextData().isNull() && (slot->getTextData() != "")) this->m_textData = slot->getTextData(); } JoyButtonSlot::JoyButtonSlot(QString text, JoySlotInputAction mode, QObject *parent) : QObject(parent) , extraData() { qInstallMessageHandler(MessageHandler::myMessageOutput); deviceCode = 0; qkeyaliasCode = 0; m_mode = mode; m_distance = 0.0; easingActive = false; mix_slots = nullptr; if ((mode == JoyLoadProfile) || (mode == JoyTextEntry) || (mode == JoyExecute)) { m_textData = text; } } JoyButtonSlot::~JoyButtonSlot() {} void JoyButtonSlot::setSlotCode(int code) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (code >= 0) { deviceCode = code; qkeyaliasCode = 0; } } void JoyButtonSlot::setSlotCode(int code, int alias) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((m_mode == JoyButtonSlot::JoyKeyboard) && (code > 0)) { deviceCode = code; qkeyaliasCode = alias; } else if (code >= 0) { deviceCode = code; qkeyaliasCode = 0; } } int JoyButtonSlot::getSlotCodeAlias() { qInstallMessageHandler(MessageHandler::myMessageOutput); return qkeyaliasCode; } int JoyButtonSlot::getSlotCode() { qInstallMessageHandler(MessageHandler::myMessageOutput); return deviceCode; } void JoyButtonSlot::setSlotMode(JoySlotInputAction selectedMode) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_mode = selectedMode; } JoyButtonSlot::JoySlotInputAction JoyButtonSlot::getSlotMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_mode; } QString JoyButtonSlot::movementString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString newlabel = QString(); if (m_mode == JoyMouseMovement) { newlabel.append(tr("Mouse")).append(" "); switch (deviceCode) { case 1: newlabel.append(tr("Up")); break; case 2: newlabel.append(tr("Down")); break; case 3: newlabel.append(tr("Left")); break; case 4: newlabel.append(tr("Right")); break; } } return newlabel; } void JoyButtonSlot::setDistance(double distance) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_distance = distance; } double JoyButtonSlot::getMouseDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_distance; } QElapsedTimer *JoyButtonSlot::getMouseInterval() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &mouseInterval; } void JoyButtonSlot::restartMouseInterval() { qInstallMessageHandler(MessageHandler::myMessageOutput); mouseInterval.restart(); } QString JoyButtonSlot::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyButtonSlot::xmlName; } QString JoyButtonSlot::getSlotString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString newlabel = QString(); qDebug() << "deviceCode in getSlotString() is: " << deviceCode << " for mode: " << m_mode; if (deviceCode >= 0 || m_mode == JoyButtonSlot::JoyMix) { switch (m_mode) { case JoyButtonSlot::JoyKeyboard: { int tempDeviceCode = deviceCode; newlabel = newlabel.append(keysymToKeyString(tempDeviceCode, qkeyaliasCode).toUpper()); break; } case JoyButtonSlot::JoyMouseButton: { newlabel.append(tr("Mouse")).append(" "); switch (deviceCode) { case 1: newlabel.append(tr("LB")); break; case 2: newlabel.append(tr("MB")); break; case 3: newlabel.append(tr("RB")); break; default: newlabel.append(QString::number(deviceCode)); break; } break; } case JoyMouseMovement: { newlabel.append(movementString()); break; } case JoyPause: { int minutes = deviceCode / 1000 / 60; int seconds = (deviceCode / 1000 % 60); int hundredths = deviceCode % 1000 / 10; newlabel.append(tr("Pause")).append(" "); if (minutes > 0) newlabel.append(QString("%1:").arg(minutes, 2, 10, QChar('0'))); newlabel.append(QString("%1.%2").arg(seconds, 2, 10, QChar('0')).arg(hundredths, 2, 10, QChar('0'))); break; } case JoyHold: { int minutes = deviceCode / 1000 / 60; int seconds = (deviceCode / 1000 % 60); int hundredths = deviceCode % 1000 / 10; newlabel.append(tr("Hold")).append(" "); if (minutes > 0) newlabel.append(QString("%1:").arg(minutes, 2, 10, QChar('0'))); newlabel.append(QString("%1.%2").arg(seconds, 2, 10, QChar('0')).arg(hundredths, 2, 10, QChar('0'))); break; } case JoyButtonSlot::JoyCycle: { newlabel.append(tr("Cycle")); break; } case JoyDistance: { QString temp(tr("Distance")); temp.append(" ").append(QString::number(deviceCode).append("%")); newlabel.append(temp); break; } case JoyRelease: { int minutes = deviceCode / 1000 / 60; int seconds = (deviceCode / 1000 % 60); int hundredths = deviceCode % 1000 / 10; newlabel.append(tr("Release")).append(" "); if (minutes > 0) newlabel.append(QString("%1:").arg(minutes, 2, 10, QChar('0'))); newlabel.append(QString("%1.%2").arg(seconds, 2, 10, QChar('0')).arg(hundredths, 2, 10, QChar('0'))); break; } case JoyMouseSpeedMod: { QString temp = QString(); temp.append(tr("Mouse Mod")).append(" "); temp.append(QString::number(deviceCode).append("%")); newlabel.append(temp); break; } case JoyKeyPress: { int minutes = deviceCode / 1000 / 60; int seconds = (deviceCode / 1000 % 60); int hundredths = deviceCode % 1000 / 10; QString temp(tr("Press Time").append(" ")); if (minutes > 0) temp.append(QString("%1:").arg(minutes, 2, 10, QChar('0'))); temp.append(QString("%1.%2").arg(seconds, 2, 10, QChar('0')).arg(hundredths, 2, 10, QChar('0'))); newlabel.append(temp); break; } case JoyDelay: { int minutes = deviceCode / 1000 / 60; int seconds = (deviceCode / 1000 % 60); int hundredths = deviceCode % 1000 / 10; QString temp(tr("Delay").append(" ")); if (minutes > 0) temp.append(QString("%1:").arg(minutes, 2, 10, QChar('0'))); temp.append(QString("%1.%2").arg(seconds, 2, 10, QChar('0')).arg(hundredths, 2, 10, QChar('0'))); newlabel.append(temp); break; } case JoyLoadProfile: { if (!m_textData.isEmpty()) { QFileInfo profileInfo(m_textData); QString temp(tr("Load %1").arg(PadderCommon::getProfileName(profileInfo))); newlabel.append(temp); } break; } case JoySetChange: { newlabel.append(tr("Set Change %1").arg(deviceCode + 1)); break; } case JoyTextEntry: { QString temp = m_textData; if (temp.length() > GlobalVariables::JoyButtonSlot::MAXTEXTENTRYDISPLAYLENGTH) { temp.truncate(GlobalVariables::JoyButtonSlot::MAXTEXTENTRYDISPLAYLENGTH - 3); temp.append("..."); } newlabel.append(tr("[Text] %1").arg(temp)); break; } case JoyExecute: { QString temp = QString(); if (!m_textData.isEmpty()) { QFileInfo tempFileInfo(m_textData); temp.append(tempFileInfo.fileName()); } newlabel.append(tr("[Exec] %1").arg(temp)); break; } case JoyButtonSlot::JoyMix: { bool firstTime = true; for (auto minislot : *getMixSlots()) { if (!firstTime) newlabel.append("+"); firstTime = false; newlabel = newlabel.append(keysymToKeyString(minislot->getSlotCode(), minislot->getSlotCodeAlias()).toUpper()); } break; } } } else { newlabel = newlabel.append(tr("[NO KEY]")); } if (newlabel == tr("[NO KEY]")) { qDebug() << "EMPTY JOYBUTTONSLOT"; } return newlabel; } void JoyButtonSlot::setPreviousDistance(double distance) { qInstallMessageHandler(MessageHandler::myMessageOutput); previousDistance = distance; } double JoyButtonSlot::getPreviousDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); return previousDistance; } double JoyButtonSlot::getDistance() const { return m_distance; } bool JoyButtonSlot::isModifierKey() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool modifier = false; if ((m_mode == JoyKeyboard) && AntKeyMapper::getInstance()->isModifierKey(qkeyaliasCode)) { modifier = true; } return modifier; } bool JoyButtonSlot::isEasingActive() { qInstallMessageHandler(MessageHandler::myMessageOutput); return easingActive; } void JoyButtonSlot::setEasingStatus(bool isActive) { qInstallMessageHandler(MessageHandler::myMessageOutput); easingActive = isActive; } QTime *JoyButtonSlot::getEasingTime() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &easingTime; } void JoyButtonSlot::setTextData(QString textData) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_textData = textData; } QString JoyButtonSlot::getTextData() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_textData.isNull() || m_textData.isEmpty()) return ""; return m_textData; } void JoyButtonSlot::setExtraData(QVariant data) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->extraData = data; } QVariant JoyButtonSlot::getExtraData() { qInstallMessageHandler(MessageHandler::myMessageOutput); return extraData; } void JoyButtonSlot::secureMixSlotsInit() { if (mix_slots == nullptr) { mix_slots = new QList(); // connect(qApp, &QApplication::aboutToQuit, this, &JoyButtonSlot::cleanMixSlots); } } QList *JoyButtonSlot::getMixSlots() { secureMixSlotsInit(); return mix_slots; } void JoyButtonSlot::assignMixSlotsToNull() { mix_slots = nullptr; } void JoyButtonSlot::cleanMixSlots() { if (mix_slots != nullptr) { // disconnect(qApp, &QApplication::aboutToQuit, this, &JoyButtonSlot::cleanMixSlots); if (mix_slots->size() != 0) { qDeleteAll(*mix_slots); mix_slots->clear(); } delete mix_slots; mix_slots = nullptr; } } void JoyButtonSlot::setMixSlots(QList *mixSlots) { mix_slots = mixSlots; } bool JoyButtonSlot::isValidSlot() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; switch (m_mode) { case JoyLoadProfile: case JoyTextEntry: case JoyExecute: { if (m_textData.isEmpty()) result = false; break; } case JoySetChange: { if (deviceCode < 0) result = false; break; } case JoyMix: { if (mix_slots->count() == 0) return false; break; } default: { break; } } return result; } JoyButtonSlot &JoyButtonSlot::operator=(JoyButtonSlot *slot) { this->deviceCode = slot->getSlotCode(); this->m_mode = slot->getSlotMode(); this->qkeyaliasCode = slot->getSlotCodeAlias(); this->m_distance = slot->getDistance(); this->previousDistance = slot->getPreviousDistance(); this->easingActive = slot->isEasingActive(); this->easingTime.fromString(slot->getEasingTime()->toString()); this->extraData = slot->getExtraData(); if (slot->getMixSlots() != nullptr) this->mix_slots = slot->getMixSlots(); if (!slot->getTextData().isNull() ^ (slot->getTextData() != "")) this->m_textData = slot->getTextData(); return *this; } AntiMicroX-antimicrox-2888bf6/src/joybuttonslot.h000066400000000000000000000076271377703515000221760ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTONSLOT_H #define JOYBUTTONSLOT_H #include #include #include #include #include #include class QXmlStreamReader; class QXmlStreamWriter; class JoyButtonSlot : public QObject { Q_OBJECT public: enum JoySlotInputAction { JoyKeyboard = 0, JoyMouseButton, JoyMouseMovement, JoyPause, JoyHold, JoyCycle, JoyDistance, JoyRelease, JoyMouseSpeedMod, JoyKeyPress, JoyDelay, JoyLoadProfile, JoySetChange, JoyTextEntry, JoyExecute, JoyMix }; enum JoySlotMouseDirection { MouseUp = 1, MouseDown, MouseLeft, MouseRight }; enum JoySlotMouseWheelButton { MouseWheelUp = 4, MouseWheelDown = 5, MouseWheelLeft = 6, MouseWheelRight = 7 }; enum JoySlotMouseButton { MouseLB = 1, MouseMB, MouseRB }; explicit JoyButtonSlot(QObject *parent = nullptr); explicit JoyButtonSlot(int code, JoySlotInputAction mode, QObject *parent = nullptr); explicit JoyButtonSlot(int code, int alias, JoySlotInputAction mode, QObject *parent = nullptr); explicit JoyButtonSlot(JoyButtonSlot *slot, QObject *parent = nullptr); explicit JoyButtonSlot(QString text, JoySlotInputAction mode, QObject *parent = nullptr); ~JoyButtonSlot(); void setSlotCode(int code); int getSlotCode(); void setSlotMode(JoySlotInputAction selectedMode); JoySlotInputAction getSlotMode(); QString movementString(); void setMouseSpeed(int value); void setDistance(double distance); double getMouseDistance(); QElapsedTimer *getMouseInterval(); void restartMouseInterval(); QString getXmlName(); QString getSlotString(); void setSlotCode(int code, int alias); int getSlotCodeAlias(); void setPreviousDistance(double distance); double getPreviousDistance(); double getDistance() const; bool isModifierKey(); bool isEasingActive(); void setEasingStatus(bool isActive); QTime *getEasingTime(); void setTextData(QString textData); QString getTextData(); void setExtraData(QVariant data); QVariant getExtraData(); void setMixSlots(QList *slots); QList *getMixSlots(); template void appendMiniSlot(T minislot) { secureMixSlotsInit(); mix_slots->append(minislot); } void assignMixSlotsToNull(); bool isValidSlot(); void cleanMixSlots(); JoyButtonSlot &operator=(JoyButtonSlot *slot); private: void secureMixSlotsInit(); int deviceCode; int qkeyaliasCode; JoySlotInputAction m_mode; QList *mix_slots; double m_distance; double previousDistance; QElapsedTimer mouseInterval; QTime easingTime; bool easingActive; QString m_textData; QVariant extraData; }; Q_DECLARE_METATYPE(JoyButtonSlot *) Q_DECLARE_METATYPE(JoyButtonSlot::JoySlotInputAction) #endif // JOYBUTTONSLOT_H AntiMicroX-antimicrox-2888bf6/src/joybuttonstatusbox.cpp000066400000000000000000000041031377703515000235660ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybuttonstatusbox.h" #include "joybutton.h" #include "messagehandler.h" #include #include #include JoyButtonStatusBox::JoyButtonStatusBox(JoyButton *button, QWidget *parent) : QPushButton(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->button = button; isflashing = false; setText(QString::number(button->getRealJoyNumber())); connect(button, &JoyButton::clicked, this, &JoyButtonStatusBox::flash); connect(button, &JoyButton::released, this, &JoyButtonStatusBox::unflash); } JoyButton *JoyButtonStatusBox::getJoyButton() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return button; } bool JoyButtonStatusBox::isButtonFlashing() { qInstallMessageHandler(MessageHandler::myMessageOutput); return isflashing; } void JoyButtonStatusBox::flash() { qInstallMessageHandler(MessageHandler::myMessageOutput); isflashing = true; this->style()->unpolish(this); this->style()->polish(this); emit flashed(isflashing); } void JoyButtonStatusBox::unflash() { qInstallMessageHandler(MessageHandler::myMessageOutput); isflashing = false; this->style()->unpolish(this); this->style()->polish(this); emit flashed(isflashing); } AntiMicroX-antimicrox-2888bf6/src/joybuttonstatusbox.h000066400000000000000000000025671377703515000232470ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTONSTATUSBOX_H #define JOYBUTTONSTATUSBOX_H #include class JoyButton; class QWidget; class JoyButtonStatusBox : public QPushButton { Q_OBJECT Q_PROPERTY(bool isflashing READ isButtonFlashing) public: explicit JoyButtonStatusBox(JoyButton *button, QWidget *parent = nullptr); JoyButton *getJoyButton() const; bool isButtonFlashing(); signals: void flashed(bool flashing); private slots: void flash(); void unflash(); private: JoyButton *button; bool isflashing; }; #endif // JOYBUTTONSTATUSBOX_H AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/000077500000000000000000000000001377703515000221745ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joyaxisbutton.cpp000066400000000000000000000136201377703515000256240ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joyaxisbutton.h" #include "event.h" #include "globalvariables.h" #include "joyaxis.h" #include "joybutton.h" #include "messagehandler.h" #include "setjoystick.h" #include "vdpad.h" #include #include JoyAxisButton::JoyAxisButton(JoyAxis *axis, int index, int originset, SetJoystick *parentSet, QObject *parent) : JoyGradientButton(index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_axis = axis; } QString JoyAxisButton::getPartialName(bool forceFullFormat, bool displayNames) const { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(m_axis->getPartialName(forceFullFormat, displayNames)); temp.append(": "); if (!buttonName.isEmpty() && displayNames) { if (forceFullFormat) { temp.append(tr("Button")).append(" "); } temp.append(buttonName); } else if (!defaultButtonName.isEmpty() && displayNames) { if (forceFullFormat) { temp.append(tr("Button")).append(" "); } temp.append(defaultButtonName); } else { QString buttontype = QString(); switch (m_index) { case 0: buttontype = tr("Negative"); break; case 1: buttontype = tr("Positive"); break; default: buttontype = tr("Unknown"); break; } temp.append(tr("Button")).append(" ").append(buttontype); } return temp; } QString JoyAxisButton::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyAxisButton::xmlName; } void JoyAxisButton::setChangeSetCondition(SetChangeCondition condition, bool passive, bool updateActiveString) { qInstallMessageHandler(MessageHandler::myMessageOutput); SetChangeCondition oldCondition = setSelectionCondition; if ((condition != setSelectionCondition) && !passive) { if ((condition == SetChangeWhileHeld) || (condition == SetChangeTwoWay)) { // Set new condition emit setAssignmentChanged(m_index, m_axis->getIndex(), setSelection, condition); } else if ((setSelectionCondition == SetChangeWhileHeld) || (setSelectionCondition == SetChangeTwoWay)) { // Remove old condition emit setAssignmentChanged(m_index, m_axis->getIndex(), setSelection, SetChangeDisabled); } setSelectionCondition = condition; } else if (passive) { setSelectionCondition = condition; } if (setSelectionCondition == SetChangeDisabled) { setChangeSetSelection(-1); } if (setSelectionCondition != oldCondition) { if (updateActiveString) { buildActiveZoneSummaryString(); } emit propertyUpdated(); } } /** * @brief Get the distance that an element is away from its assigned * dead zone * @return Normalized distance away from dead zone */ double JoyAxisButton::getDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_axis->getDistanceFromDeadZone(); } /** * @brief Get the distance factor that should be used for mouse movement * @return Distance factor that should be used for mouse movement */ double JoyAxisButton::getMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return this->getDistanceFromDeadZone(); } void JoyAxisButton::setVDPad(VDPad *vdpad) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_axis->isPartControlStick()) { m_axis->removeControlStick(); } JoyButton::setVDPad(vdpad); } /** * @brief Set the turbo mode that the button should use * @param Mode that should be used */ void JoyAxisButton::setTurboMode(TurboMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (isPartRealAxis()) { currentTurboMode = mode; } } /** * @brief Check if button should be considered a part of a real controller * axis. Needed for some dialogs so the program won't have to resort to * type checking. * @return Status of being part of a real controller axis */ bool JoyAxisButton::isPartRealAxis() { qInstallMessageHandler(MessageHandler::myMessageOutput); return true; } double JoyAxisButton::getAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_axis->getRawDistance(m_axis->getCurrentThrottledValue()); } double JoyAxisButton::getLastAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_axis->getRawDistance(m_axis->getLastKnownThrottleValue()); } double JoyAxisButton::getLastMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); double distance = 0.0; if (m_axis->getAxisButtonByValue(m_axis->getLastKnownThrottleValue()) == this) { distance = m_axis->getDistanceFromDeadZone(m_axis->getLastKnownThrottleValue()); } return distance; } JoyAxis *JoyAxisButton::getAxis() const { return m_axis; } AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joyaxisbutton.h000066400000000000000000000037021377703515000252710ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYAXISBUTTON_H #define JOYAXISBUTTON_H #include "joybuttontypes/joygradientbutton.h" class VDPad; class SetJoystick; class JoyAxis; class JoyAxisButton : public JoyGradientButton { Q_OBJECT public: explicit JoyAxisButton(JoyAxis *axis, int index, int originset, SetJoystick *parentSet, QObject *parent = 0); virtual QString getPartialName(bool forceFullFormat = false, bool displayNames = false) const; virtual QString getXmlName(); virtual double getDistanceFromDeadZone(); virtual double getMouseDistanceFromDeadZone(); virtual double getLastMouseDistanceFromDeadZone(); virtual void setChangeSetCondition(SetChangeCondition condition, bool passive = false, bool updateActiveString = true); virtual void setVDPad(VDPad *vdpad); virtual void setTurboMode(TurboMode mode); virtual bool isPartRealAxis(); virtual double getAccelerationDistance(); virtual double getLastAccelerationDistance(); JoyAxis *getAxis() const; signals: void setAssignmentChanged(int current_button, int axis_index, int associated_set, int mode); private: JoyAxis *m_axis; }; #endif // JOYAXISBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joycontrolstickbutton.cpp000066400000000000000000000223601377703515000273770ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickbutton.h" #include "event.h" #include "globalvariables.h" #include "joycontrolstick.h" #include "joycontrolstickmodifierbutton.h" #include "messagehandler.h" #include "setjoystick.h" #include #include #include JoyControlStickButton::JoyControlStickButton(JoyControlStick *stick, int index, int originset, SetJoystick *parentSet, QObject *parent) : JoyGradientButton(index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->stick = stick; } JoyControlStickButton::JoyControlStickButton(JoyControlStick *stick, JoyStickDirectionsType::JoyStickDirections index, int originset, SetJoystick *parentSet, QObject *parent) : JoyGradientButton(index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->stick = stick; } QString JoyControlStickButton::getDirectionName() const { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); switch (m_index) { case 1: label.append(tr("Up")); break; case 2: label.append(tr("Up")).append("+").append(tr("Right")); break; case 3: label.append(tr("Right")); break; case 4: label.append(tr("Down")).append("+").append(tr("Right")); break; case 5: label.append(tr("Down")); break; case 6: label.append(tr("Down")).append("+").append(tr("Left")); break; case 7: label.append(tr("Left")); break; case 8: label.append(tr("Up")).append("+").append(tr("Left")); break; } return label; } QString JoyControlStickButton::getPartialName(bool forceFullFormat, bool displayNames) const { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = stick->getPartialName(forceFullFormat, displayNames); temp.append(": "); if (!buttonName.isEmpty() && displayNames) { if (forceFullFormat) { temp.append(tr("Button")).append(" "); } temp.append(buttonName); } else if (!defaultButtonName.isEmpty()) { if (forceFullFormat) { temp.append(tr("Button")).append(" "); } temp.append(defaultButtonName); } else { temp.append(tr("Button")).append(" "); temp.append(getDirectionName()); } return temp; } QString JoyControlStickButton::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyControlStickButton::xmlName; } /** * @brief Get the distance that an element is away from its assigned * dead zone * @return Normalized distance away from dead zone */ double JoyControlStickButton::getDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick->calculateDirectionalDistance(); } /** * @brief Get the distance factor that should be used for mouse movement * @return Distance factor that should be used for mouse movement */ double JoyControlStickButton::getMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick->calculateMouseDirectionalDistance(this); } void JoyControlStickButton::setChangeSetCondition(SetChangeCondition condition, bool passive, bool updateActiveString) { Q_UNUSED(updateActiveString); qInstallMessageHandler(MessageHandler::myMessageOutput); SetChangeCondition oldCondition = setSelectionCondition; if ((condition != setSelectionCondition) && !passive) { if ((condition == SetChangeWhileHeld) || (condition == SetChangeTwoWay)) { // Set new condition emit setAssignmentChanged(m_index, this->stick->getIndex(), setSelection, condition); } else if ((setSelectionCondition == SetChangeWhileHeld) || (setSelectionCondition == SetChangeTwoWay)) { // Remove old condition emit setAssignmentChanged(m_index, this->stick->getIndex(), setSelection, SetChangeDisabled); } setSelectionCondition = condition; } else if (passive) { setSelectionCondition = condition; } if (setSelectionCondition == SetChangeDisabled) { setChangeSetSelection(-1); } if (setSelectionCondition != oldCondition) { buildActiveZoneSummaryString(); emit propertyUpdated(); } } int JoyControlStickButton::getRealJoyNumber() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index; } JoyStickDirectionsType::JoyStickDirections JoyControlStickButton::getDirection() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return static_cast(m_index); } /** * @brief Set the turbo mode that the button should use * @param Mode that should be used */ void JoyControlStickButton::setTurboMode(TurboMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (isPartRealAxis()) { currentTurboMode = mode; } } /** * @brief Check if button should be considered a part of a real controller * axis. Needed for some dialogs so the program won't have to resort to * type checking. * @return Status of being part of a real controller axis */ bool JoyControlStickButton::isPartRealAxis() { qInstallMessageHandler(MessageHandler::myMessageOutput); return true; } double JoyControlStickButton::getLastAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double temp = stick->calculateLastAccelerationButtonDistance(this); return temp; } double JoyControlStickButton::getAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double temp = stick->calculateAccelerationDistance(this); return temp; } /** * @brief Generate a string that represents slots that will be activated or * slots that are currently active if a button is pressed * @return String of currently applicable slots for a button */ QString JoyControlStickButton::getActiveZoneSummary() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList tempList; tempList.append(getActiveZoneList()); QString temp = buildActiveZoneSummary(tempList); return temp; } QString JoyControlStickButton::getCalculatedActiveZoneSummary() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickModifierButton *tempButton = stick->getModifierButton(); QString temp = QString(); QStringList stringlist = QStringList(); if ((tempButton != nullptr) && tempButton->getButtonState() && tempButton->hasActiveSlots() && getButtonState()) { qDebug() << "Calculated Active Zone Summary: " << tempButton->getCalculatedActiveZoneSummary(); stringlist.append(tempButton->getCalculatedActiveZoneSummary()); } stringlist.append(JoyButton::getCalculatedActiveZoneSummary()); temp = stringlist.join(", "); qDebug() << "Returned joined zone: " << temp; return temp; } double JoyControlStickButton::getLastMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick->calculateLastMouseDirectionalDistance(this); } double JoyControlStickButton::getCurrentSpringDeadCircle() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = (springDeadCircleMultiplier * 0.01); if ((m_index == static_cast(JoyControlStick::StickLeft)) || (m_index == static_cast(JoyControlStick::StickRight))) { result = stick->getSpringDeadCircleX() * (springDeadCircleMultiplier * 0.01); } else if ((m_index == static_cast(JoyControlStick::StickUp)) || (m_index == static_cast(JoyControlStick::StickDown))) { result = stick->getSpringDeadCircleY() * (springDeadCircleMultiplier * 0.01); } else if ((m_index == static_cast(JoyControlStick::StickRightUp)) || (m_index == static_cast(JoyControlStick::StickRightDown)) || (m_index == static_cast(JoyControlStick::StickLeftDown)) || (m_index == static_cast(JoyControlStick::StickLeftUp))) { result = 0.0; } return result; } JoyControlStick *JoyControlStickButton::getStick() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick; } AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joycontrolstickbutton.h000066400000000000000000000050621377703515000270440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKBUTTON_H #define JOYCONTROLSTICKBUTTON_H #include "joybuttontypes/joygradientbutton.h" #include "joycontrolstickdirectionstype.h" class JoyControlStick; class SetJoystick; class JoyControlStickButton : public JoyGradientButton { Q_OBJECT public: explicit JoyControlStickButton(JoyControlStick *stick, int index, int originset, SetJoystick *parentSet, QObject *parent = nullptr); explicit JoyControlStickButton(JoyControlStick *stick, JoyStickDirectionsType::JoyStickDirections index, int originset, SetJoystick *parentSet, QObject *parent = nullptr); virtual int getRealJoyNumber() const; virtual QString getPartialName(bool forceFullFormat = false, bool displayNames = false) const; virtual QString getXmlName(); virtual double getDistanceFromDeadZone(); virtual double getMouseDistanceFromDeadZone(); virtual double getLastMouseDistanceFromDeadZone(); virtual void setChangeSetCondition(SetChangeCondition condition, bool passive = false, bool updateActiveString = true); virtual void setTurboMode(TurboMode mode); virtual bool isPartRealAxis(); virtual QString getActiveZoneSummary(); virtual QString getCalculatedActiveZoneSummary(); virtual double getAccelerationDistance(); virtual double getLastAccelerationDistance(); JoyControlStick *getStick() const; QString getDirectionName() const; JoyStickDirectionsType::JoyStickDirections getDirection() const; protected: virtual double getCurrentSpringDeadCircle(); signals: void setAssignmentChanged(int current_button, int axis_index, int associated_set, int mode); private: JoyControlStick *stick; }; #endif // JOYCONTROLSTICKBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joycontrolstickmodifierbutton.cpp000066400000000000000000000113761377703515000311230ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickmodifierbutton.h" #include "globalvariables.h" #include "joycontrolstick.h" #include "messagehandler.h" #include "setjoystick.h" #include #include #include JoyControlStickModifierButton::JoyControlStickModifierButton(JoyControlStick *stick, int originset, SetJoystick *parentSet, QObject *parent) : JoyGradientButton(0, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->stick = stick; } QString JoyControlStickModifierButton::getPartialName(bool forceFullFormat, bool displayNames) const { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = stick->getPartialName(forceFullFormat, displayNames); temp.append(": "); if (!buttonName.isEmpty() && displayNames) { if (forceFullFormat) { temp.append(tr("Modifier")).append(" "); } temp.append(buttonName); } else if (!defaultButtonName.isEmpty()) { if (forceFullFormat) { temp.append(tr("Modifier")).append(" "); } temp.append(defaultButtonName); } else { temp.append(tr("Modifier")); } return temp; } QString JoyControlStickModifierButton::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyControlStickModifierButton::xmlName; } /** * @brief Get the distance that an element is away from its assigned * dead zone * @return Normalized distance away from dead zone */ double JoyControlStickModifierButton::getDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick->calculateDirectionalDistance(); } /** * @brief Get the distance factor that should be used for mouse movement * @return Distance factor that should be used for mouse movement */ double JoyControlStickModifierButton::getMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getDistanceFromDeadZone(); } void JoyControlStickModifierButton::setChangeSetCondition(SetChangeCondition condition, bool passive, bool updateActiveString) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(updateActiveString); Q_UNUSED(condition); Q_UNUSED(passive); } JoyControlStick *JoyControlStickModifierButton::getStick() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick; } /** * @brief Set the turbo mode that the button should use * @param Mode that should be used */ void JoyControlStickModifierButton::setTurboMode(TurboMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (isPartRealAxis()) { currentTurboMode = mode; } } /** * @brief Check if button should be considered a part of a real controller * axis. Needed for some dialogs so the program won't have to resort to * type checking. * @return Status of being part of a real controller axis */ bool JoyControlStickModifierButton::isPartRealAxis() { qInstallMessageHandler(MessageHandler::myMessageOutput); return true; } bool JoyControlStickModifierButton::isModifierButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); return true; } double JoyControlStickModifierButton::getAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double temp = stick->getAbsoluteRawDistance(); return temp; } double JoyControlStickModifierButton::getLastAccelerationDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double temp = stick->calculateLastAccelerationDirectionalDistance(); return temp; } double JoyControlStickModifierButton::getLastMouseDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick->calculateLastDirectionalDistance(); } AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joycontrolstickmodifierbutton.h000066400000000000000000000037331377703515000305660ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKMODIFIERBUTTON_H #define JOYCONTROLSTICKMODIFIERBUTTON_H #include "joybuttontypes/joygradientbutton.h" class JoyControlStick; class SetJoystick; class JoyControlStickModifierButton : public JoyGradientButton { Q_OBJECT public: explicit JoyControlStickModifierButton(JoyControlStick *stick, int originset, SetJoystick *parentSet, QObject *parent = nullptr); virtual QString getPartialName(bool forceFullFormat = false, bool displayNames = false) const; virtual QString getXmlName(); virtual double getDistanceFromDeadZone(); virtual double getMouseDistanceFromDeadZone(); virtual double getLastMouseDistanceFromDeadZone(); virtual void setChangeSetCondition(SetChangeCondition condition, bool passive = false, bool updateActiveString = true); virtual void setTurboMode(TurboMode mode); virtual bool isPartRealAxis(); virtual bool isModifierButton(); virtual double getAccelerationDistance(); virtual double getLastAccelerationDistance(); JoyControlStick *getStick() const; private: JoyControlStick *stick; }; #endif // JOYCONTROLSTICKMODIFIERBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joydpadbutton.cpp000066400000000000000000000114031377703515000255650ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joydpadbutton.h" #include "event.h" #include "globalvariables.h" #include "joydpad.h" #include "messagehandler.h" #include "setjoystick.h" #include // Initially, qualify direction as the button's index JoyDPadButton::JoyDPadButton(int direction, int originset, JoyDPad *dpad, SetJoystick *parentSet, QObject *parent) : JoyButton(direction, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_direction = direction; m_dpad = dpad; } QString JoyDPadButton::getDirectionName() const { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); switch (m_direction) { case 1: label.append(tr("Up")); break; case 2: label.append(tr("Right")); break; case 3: label.append(tr("Up")).append("+").append(tr("Right")); break; case 4: label.append(tr("Down")); break; case 6: label.append(tr("Down")).append("+").append(tr("Right")); break; case 8: label.append(tr("Left")); break; case 9: label.append(tr("Up")).append("+").append(tr("Left")); break; case 12: label.append(tr("Down")).append("+").append(tr("Left")); break; } return label; } QString JoyDPadButton::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyDPadButton::xmlName; } int JoyDPadButton::getRealJoyNumber() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index; } QString JoyDPadButton::getPartialName(bool forceFullFormat, bool displayNames) const { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = m_dpad->getName().append(" - "); if (!buttonName.isEmpty() && displayNames) { if (forceFullFormat) { temp.append(tr("Button")).append(" "); } temp.append(buttonName); } else if (!defaultButtonName.isEmpty() && displayNames) { if (forceFullFormat) { temp.append(tr("Button")).append(" "); } temp.append(defaultButtonName); } else { temp.append(tr("Button")).append(" "); temp.append(getDirectionName()); } return temp; } void JoyDPadButton::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::reset(); } void JoyDPadButton::reset(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(index); reset(); } void JoyDPadButton::setChangeSetCondition(SetChangeCondition condition, bool passive, bool updateActiveString) { Q_UNUSED(updateActiveString); qInstallMessageHandler(MessageHandler::myMessageOutput); SetChangeCondition oldCondition = setSelectionCondition; if ((condition != setSelectionCondition) && !passive) { if ((condition == SetChangeWhileHeld) || (condition == SetChangeTwoWay)) { // Set new condition emit setAssignmentChanged(m_index, m_dpad->getJoyNumber(), setSelection, condition); } else if ((setSelectionCondition == SetChangeWhileHeld) || (setSelectionCondition == SetChangeTwoWay)) { // Remove old condition emit setAssignmentChanged(m_index, m_dpad->getJoyNumber(), setSelection, SetChangeDisabled); } setSelectionCondition = condition; } else if (passive) { setSelectionCondition = condition; } if (setSelectionCondition == SetChangeDisabled) { setChangeSetSelection(-1); } if (setSelectionCondition != oldCondition) { buildActiveZoneSummaryString(); emit propertyUpdated(); } } JoyDPad *JoyDPadButton::getDPad() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_dpad; } int JoyDPadButton::getDirection() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_direction; } AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joydpadbutton.h000066400000000000000000000041121377703515000252310ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYDPADBUTTON_H #define JOYDPADBUTTON_H #include "joybutton.h" class JoyDPad; class SetJoystick; class JoyDPadButton : public JoyButton { Q_OBJECT public: JoyDPadButton(int direction, int originset, JoyDPad *dpad, SetJoystick *parentSet, QObject *parent = 0); virtual int getRealJoyNumber() const override; virtual QString getPartialName(bool forceFullFormat = false, bool displayNames = false) const override; virtual QString getXmlName() override; virtual void setChangeSetCondition(SetChangeCondition condition, bool passive = false, bool updateActiveString = true) override; enum JoyDPadDirections { DpadCentered = 0, DpadUp = 1, DpadRight = 2, DpadDown = 4, DpadLeft = 8, DpadRightUp = 3, DpadRightDown = 6, DpadLeftUp = 9, DpadLeftDown = 12 }; QString getDirectionName() const; int getDirection() const; JoyDPad *getDPad() const; signals: void setAssignmentChanged(int current_button, int dpad_index, int associated_set, int mode); public slots: virtual void reset() override; virtual void reset(int index) override; private: int m_direction; JoyDPad *m_dpad; }; #endif // JOYDPADBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joygradientbutton.cpp000066400000000000000000000400501377703515000264520ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joygradientbutton.h" #include "event.h" #include "messagehandler.h" #include "setjoystick.h" #include #include JoyGradientButton::JoyGradientButton(int index, int originset, SetJoystick *parentSet, QObject *parent) : JoyButton(index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } /** * @brief Activate a turbo event on a button. */ void JoyGradientButton::turboEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); int m_turboInterval = containsJoyMixSlot() && allSlotTimeBetweenSlots > 0 ? allSlotTimeBetweenSlots : turboInterval; if (getTurboMode() == NormalTurbo) { JoyButton::turboEvent(); } else if ((getTurboMode() == GradientTurbo) || (getTurboMode() == PulseTurbo)) { double diff = fabs(getMouseDistanceFromDeadZone() - lastDistance); qDebug() << "DIFF: " << QString::number(diff); bool changeState = false; if (!turboTimer.isActive() && !isButtonPressed) { changeState = true; } else if ((getTurboMode() == GradientTurbo) && (diff > 0) && (getMouseDistanceFromDeadZone() >= 1.0)) { if (isKeyPressed) { changeState = false; if (!turboTimer.isActive() || (turboTimer.interval() != 5)) { turboTimer.start(5); } turboHold.restart(); lastDistance = 1.0; } else { changeState = true; } } else if (lastDistance == 0.0 || (turboHold.elapsed() > tempTurboInterval)) { changeState = true; } else if (diff >= 0.1) { int tempInterval2 = 0; if (isKeyPressed) { if (getTurboMode() == GradientTurbo) { tempInterval2 = floor((getMouseDistanceFromDeadZone() * m_turboInterval) + 0.5); } else { tempInterval2 = floor((m_turboInterval * 0.5) + 0.5); } } else { if (getTurboMode() == GradientTurbo) { tempInterval2 = floor(((1 - getMouseDistanceFromDeadZone()) * m_turboInterval) + 0.5); } else { double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempInterval2 = floor(((m_turboInterval / getMouseDistanceFromDeadZone()) * 0.5) + 0.5); } else { tempInterval2 = 0; } } } if (turboHold.elapsed() < tempInterval2) { // Still some valid time left. Continue current action with // remaining time left. tempTurboInterval = tempInterval2 - turboHold.elapsed(); int timerInterval = qMin(tempTurboInterval, 5); if (!turboTimer.isActive() || (turboTimer.interval() != timerInterval)) { turboTimer.start(timerInterval); } turboHold.restart(); changeState = false; lastDistance = getMouseDistanceFromDeadZone(); qDebug() << "diff tmpTurbo press: " << QString::number(tempTurboInterval); qDebug() << "diff timer press: " << QString::number(timerInterval); } else { changeState = true; qDebug() << "YOU GOT CHANGE"; } } if (changeState) { if (!isKeyPressed) { if (!isButtonPressedQueue.isEmpty()) { ignoreSetQueue.clear(); isButtonPressedQueue.clear(); ignoreSetQueue.enqueue(false); isButtonPressedQueue.enqueue(isButtonPressed); } createDeskEvent(); isKeyPressed = true; if (turboTimer.isActive()) { if (getTurboMode() == GradientTurbo) { tempTurboInterval = floor((getMouseDistanceFromDeadZone() * m_turboInterval) + 0.5); } else { tempTurboInterval = floor((m_turboInterval * 0.5) + 0.5); } int timerInterval = qMin(tempTurboInterval, 5); qDebug() << "tmpTurbo press: " << QString::number(tempTurboInterval); qDebug() << "timer press: " << QString::number(timerInterval); if (turboTimer.interval() != timerInterval) { turboTimer.start(timerInterval); } turboHold.restart(); } } else { if (!isButtonPressedQueue.isEmpty()) { ignoreSetQueue.enqueue(false); isButtonPressedQueue.enqueue(!isButtonPressed); } releaseDeskEvent(); isKeyPressed = false; if (turboTimer.isActive()) { if (getTurboMode() == GradientTurbo) { tempTurboInterval = floor(((1 - getMouseDistanceFromDeadZone()) * m_turboInterval) + 0.5); } else { double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempTurboInterval = floor(((m_turboInterval / getMouseDistanceFromDeadZone()) * 0.5) + 0.5); } else { tempTurboInterval = 0; } } int timerInterval = qMin(tempTurboInterval, 5); qDebug() << "tmpTurbo release: " << QString::number(tempTurboInterval); qDebug() << "timer release: " << QString::number(timerInterval); if (turboTimer.interval() != timerInterval) { turboTimer.start(timerInterval); } turboHold.restart(); } } lastDistance = getMouseDistanceFromDeadZone(); } } } void JoyGradientButton::wheelEventVertical() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *buttonslot = nullptr; bool activateEvent = false; int tempInterval = 0; double diff = fabs(getMouseDistanceFromDeadZone() - lastWheelVerticalDistance); int oldInterval = 0; if (wheelSpeedY != 0) { if (lastWheelVerticalDistance > 0.0) { oldInterval = 1000 / wheelSpeedY / lastWheelVerticalDistance; } else { oldInterval = 1000 / wheelSpeedY / 0.01; } } if (currentWheelVerticalEvent != nullptr) { buttonslot = currentWheelVerticalEvent; activateEvent = true; } if (!activateEvent) { if (!mouseWheelVerticalEventTimer.isActive()) { activateEvent = true; } else if (wheelVerticalTime.elapsed() > oldInterval) { activateEvent = true; } else if ((diff >= 0.1) && (wheelSpeedY != 0)) { double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempInterval = 1000 / wheelSpeedY / distance; } else { tempInterval = 0; } if (wheelVerticalTime.elapsed() < tempInterval) { // Still some valid time left. Continue current action with // remaining time left. tempInterval = tempInterval - wheelVerticalTime.elapsed(); tempInterval = qMin(tempInterval, 5); if (!mouseWheelVerticalEventTimer.isActive() || (mouseWheelVerticalEventTimer.interval() != tempInterval)) { mouseWheelVerticalEventTimer.start(tempInterval); } } else { // Elapsed time is greater than new interval. Change state. activateEvent = true; } } } if ((buttonslot != nullptr) && (wheelSpeedY != 0)) { bool isActive = getActiveSlots().contains(buttonslot); if (isActive && activateEvent) { sendevent(buttonslot, true); sendevent(buttonslot, false); mouseWheelVerticalEventQueue.enqueue(buttonslot); double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempInterval = 1000 / wheelSpeedY / distance; } else { tempInterval = 0; } tempInterval = qMin(tempInterval, 5); if (!mouseWheelVerticalEventTimer.isActive() || (mouseWheelVerticalEventTimer.interval() != tempInterval)) { mouseWheelVerticalEventTimer.start(tempInterval); } } else if (!isActive) { mouseWheelVerticalEventTimer.stop(); } } else if (!mouseWheelVerticalEventQueue.isEmpty() && (wheelSpeedY != 0)) { QQueue tempQueue; while (!mouseWheelVerticalEventQueue.isEmpty()) { buttonslot = mouseWheelVerticalEventQueue.dequeue(); bool isActive = getActiveSlots().contains(buttonslot); if (isActive && activateEvent) { sendevent(buttonslot, true); sendevent(buttonslot, false); tempQueue.enqueue(buttonslot); } else if (isActive) { tempQueue.enqueue(buttonslot); } } if (!tempQueue.isEmpty()) { mouseWheelVerticalEventQueue = tempQueue; double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempInterval = 1000 / wheelSpeedY / distance; } else { tempInterval = 0; } tempInterval = qMin(tempInterval, 5); if (!mouseWheelVerticalEventTimer.isActive() || (mouseWheelVerticalEventTimer.interval() != tempInterval)) { mouseWheelVerticalEventTimer.start(tempInterval); } } else { mouseWheelVerticalEventTimer.stop(); } } else { mouseWheelVerticalEventTimer.stop(); } if (activateEvent) { wheelVerticalTime.restart(); lastWheelVerticalDistance = getMouseDistanceFromDeadZone(); } } void JoyGradientButton::wheelEventHorizontal() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *buttonslot = nullptr; bool activateEvent = false; int tempInterval = 0; double diff = fabs(getMouseDistanceFromDeadZone() - lastWheelHorizontalDistance); int oldInterval = 0; if (wheelSpeedX != 0) { if (lastWheelHorizontalDistance > 0.0) { oldInterval = 1000 / wheelSpeedX / lastWheelHorizontalDistance; } else { oldInterval = 1000 / wheelSpeedX / 0.01; } } if (currentWheelHorizontalEvent != nullptr) { buttonslot = currentWheelHorizontalEvent; activateEvent = true; } if (!activateEvent) { if (!mouseWheelHorizontalEventTimer.isActive()) { activateEvent = true; } else if (wheelHorizontalTime.elapsed() > oldInterval) { activateEvent = true; } else if ((diff >= 0.1) && (wheelSpeedX != 0)) { double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempInterval = 1000 / wheelSpeedX / distance; } else { tempInterval = 0; } if (wheelHorizontalTime.elapsed() < tempInterval) { // Still some valid time left. Continue current action with // remaining time left. tempInterval = tempInterval - wheelHorizontalTime.elapsed(); tempInterval = qMin(tempInterval, 5); if (!mouseWheelHorizontalEventTimer.isActive() || (mouseWheelHorizontalEventTimer.interval() != tempInterval)) { mouseWheelHorizontalEventTimer.start(tempInterval); } } else { // Elapsed time is greater than new interval. Change state. activateEvent = true; } } } if ((buttonslot != nullptr) && (wheelSpeedX != 0)) { bool isActive = getActiveSlots().contains(buttonslot); if (isActive && activateEvent) { sendevent(buttonslot, true); sendevent(buttonslot, false); mouseWheelHorizontalEventQueue.enqueue(buttonslot); double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempInterval = 1000 / wheelSpeedX / distance; } else { tempInterval = 0; } tempInterval = qMin(tempInterval, 5); if (!mouseWheelHorizontalEventTimer.isActive() || (mouseWheelVerticalEventTimer.interval() != tempInterval)) { mouseWheelHorizontalEventTimer.start(tempInterval); } } else if (!isActive) { mouseWheelHorizontalEventTimer.stop(); } } else if (!mouseWheelHorizontalEventQueue.isEmpty() && (wheelSpeedX != 0)) { QQueue tempQueue; while (!mouseWheelHorizontalEventQueue.isEmpty()) { buttonslot = mouseWheelHorizontalEventQueue.dequeue(); bool isActive = getActiveSlots().contains(buttonslot); if (isActive) { sendevent(buttonslot, true); sendevent(buttonslot, false); tempQueue.enqueue(buttonslot); } } if (!tempQueue.isEmpty()) { mouseWheelHorizontalEventQueue = tempQueue; double distance = getMouseDistanceFromDeadZone(); if (distance > 0.0) { tempInterval = 1000 / wheelSpeedX / distance; } else { tempInterval = 0; } tempInterval = qMin(tempInterval, 5); if (!mouseWheelHorizontalEventTimer.isActive() || (mouseWheelVerticalEventTimer.interval() != tempInterval)) { mouseWheelHorizontalEventTimer.start(tempInterval); } } else { mouseWheelHorizontalEventTimer.stop(); } } else { mouseWheelHorizontalEventTimer.stop(); } if (activateEvent) { wheelHorizontalTime.restart(); lastWheelHorizontalDistance = getMouseDistanceFromDeadZone(); } } AntiMicroX-antimicrox-2888bf6/src/joybuttontypes/joygradientbutton.h000066400000000000000000000024741377703515000261270ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYGRADIENTBUTTON_H #define JOYGRADIENTBUTTON_H #include "joybutton.h" class SetJoystick; class JoyGradientButton : public JoyButton { Q_OBJECT public: explicit JoyGradientButton(int index, int originset, SetJoystick *parentSet, QObject *parent = 0); using JoyButton::getPartialName; using JoyButton::setChangeSetCondition; protected slots: virtual void turboEvent(); virtual void wheelEventVertical(); virtual void wheelEventHorizontal(); }; #endif // JOYGRADIENTBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joybuttonwidget.cpp000066400000000000000000000060021377703515000230150ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybuttonwidget.h" #include "joybutton.h" #include "joybuttoncontextmenu.h" #include "messagehandler.h" #include #include #include JoyButtonWidget::JoyButtonWidget(JoyButton *button, bool displayNames, QWidget *parent) : FlashButtonWidget(displayNames, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_button = button; refreshLabel(); enableFlashes(); tryFlash(); this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &JoyButtonWidget::customContextMenuRequested, this, &JoyButtonWidget::showContextMenu); connect(button, &JoyButton::propertyUpdated, this, &JoyButtonWidget::refreshLabel); connect(button, &JoyButton::activeZoneChanged, this, &JoyButtonWidget::refreshLabel); } JoyButton *JoyButtonWidget::getJoyButton() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_button; } void JoyButtonWidget::disableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(m_button, &JoyButton::clicked, this, &JoyButtonWidget::flash); disconnect(m_button, &JoyButton::released, this, &JoyButtonWidget::unflash); this->unflash(); } void JoyButtonWidget::enableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(m_button, &JoyButton::clicked, this, &JoyButtonWidget::flash, Qt::QueuedConnection); connect(m_button, &JoyButton::released, this, &JoyButtonWidget::unflash, Qt::QueuedConnection); } QString JoyButtonWidget::generateLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = m_button->getName(false, ifDisplayNames()).replace("&", "&&"); qDebug() << "Name of joy button is: " << temp; return temp; } void JoyButtonWidget::showContextMenu(const QPoint &point) { qInstallMessageHandler(MessageHandler::myMessageOutput); QPoint globalPos = this->mapToGlobal(point); JoyButtonContextMenu *contextMenu = new JoyButtonContextMenu(m_button, this); contextMenu->buildMenu(); contextMenu->popup(globalPos); } void JoyButtonWidget::tryFlash() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_button->getButtonState()) flash(); } AntiMicroX-antimicrox-2888bf6/src/joybuttonwidget.h000066400000000000000000000026431377703515000224710ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTONWIDGET_H #define JOYBUTTONWIDGET_H #include "flashbuttonwidget.h" class JoyButton; class QWidget; class JoyButtonWidget : public FlashButtonWidget { Q_OBJECT public: explicit JoyButtonWidget(JoyButton *button, bool displayNames, QWidget *parent = 0); JoyButton *getJoyButton() const; void tryFlash(); protected: virtual QString generateLabel() override; public slots: void disableFlashes() override; void enableFlashes() override; private slots: void showContextMenu(const QPoint &point); private: JoyButton *m_button; }; #endif // JOYBUTTONWIDGET_H AntiMicroX-antimicrox-2888bf6/src/joycontrolstick.cpp000066400000000000000000004050551377703515000230270ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstick.h" #include "globalvariables.h" #include "inputdevice.h" #include "joyaxis.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joybuttontypes/joycontrolstickmodifierbutton.h" #include "messagehandler.h" #include "xml/joybuttonxml.h" #include #include #include #include #include #include #include //#include const JoyControlStick::JoyMode JoyControlStick::DEFAULTMODE = JoyControlStick::StandardMode; JoyControlStick::JoyControlStick(JoyAxis *axis1, JoyAxis *axis2, int index, int originset, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->axisX = axis1; this->axisX->setControlStick(this); this->axisY = axis2; this->axisY->setControlStick(this); this->calibrated = false; this->index = index; this->originset = originset; this->modifierButton = nullptr; reset(); populateStickBtns(); directionDelayTimer.setSingleShot(true); connect(&directionDelayTimer, &QTimer::timeout, this, &JoyControlStick::stickDirectionChangeEvent); } JoyControlStick::~JoyControlStick() { qInstallMessageHandler(MessageHandler::myMessageOutput); axisX->removeControlStick(false); axisY->removeControlStick(false); deleteButtons(); } /** * @brief Take the input value for the two axes that make up a stick and * activate the proper event based on the current values. * @param Should set changing routines be ignored. */ void JoyControlStick::joyEvent(bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); safezone = !inDeadZone(); if (safezone && !isActive) { isActive = true; emit active(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); if (ignoresets || (stickDelay == 0)) { if (directionDelayTimer.isActive()) directionDelayTimer.stop(); createDeskEvent(ignoresets); } else { if (!directionDelayTimer.isActive()) directionDelayTimer.start(stickDelay); } } else if (!safezone && isActive) { isActive = false; emit released(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); if (ignoresets || (stickDelay == 0)) { if (directionDelayTimer.isActive()) directionDelayTimer.stop(); createDeskEvent(ignoresets); } else { if (!directionDelayTimer.isActive()) directionDelayTimer.start(stickDelay); } } else if (isActive) { if (ignoresets || (stickDelay == 0)) { if (directionDelayTimer.isActive()) directionDelayTimer.stop(); createDeskEvent(ignoresets); } else { JoyStickDirections pendingDirection = calculateStickDirection(); if (currentDirection != pendingDirection) { if (!directionDelayTimer.isActive()) directionDelayTimer.start(stickDelay); } else { if (directionDelayTimer.isActive()) directionDelayTimer.stop(); createDeskEvent(ignoresets); } } } emit moved(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); pendingStickEvent = false; } /** * @brief Check the current stick position to see if it lies in * the assigned dead zone. * @return If stick position is in the assigned dead zone */ bool JoyControlStick::inDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); int axis1Value = axisX->getCurrentRawValue(); int axis2Value = axisY->getCurrentRawValue(); int squareDist = (axis1Value * axis1Value) + (axis2Value * axis2Value); return squareDist <= (deadZone * deadZone); } /** * @brief Populate the virtual buttons assigned to an analog stick. */ void JoyControlStick::populateButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); populateStickBtns(); } void JoyControlStick::populateStickBtns() { JoyControlStickButton *button = new JoyControlStickButton(this, StickUp, originset, getParentSet(), this); buttons.insert(StickUp, button); button = new JoyControlStickButton(this, StickDown, originset, getParentSet(), this); buttons.insert(StickDown, button); button = new JoyControlStickButton(this, StickLeft, originset, getParentSet(), this); buttons.insert(StickLeft, button); button = new JoyControlStickButton(this, StickRight, originset, getParentSet(), this); buttons.insert(StickRight, button); button = new JoyControlStickButton(this, StickLeftUp, originset, getParentSet(), this); buttons.insert(StickLeftUp, button); button = new JoyControlStickButton(this, StickLeftDown, originset, getParentSet(), this); buttons.insert(StickLeftDown, button); button = new JoyControlStickButton(this, StickRightDown, originset, getParentSet(), this); buttons.insert(StickRightDown, button); button = new JoyControlStickButton(this, StickRightUp, originset, getParentSet(), this); buttons.insert(StickRightUp, button); modifierButton = new JoyControlStickModifierButton(this, originset, getParentSet(), this); } /** * @brief Get the assigned dead zone value. * @return Assigned dead zone value */ int JoyControlStick::getDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return deadZone; } /** * @brief Get the assigned diagonal range value. * @return Assigned diagonal range. */ int JoyControlStick::getDiagonalRange() { qInstallMessageHandler(MessageHandler::myMessageOutput); return diagonalRange; } /** * @brief Find the position of the two stick axes, deactivate no longer used * stick direction button and then activate direction buttons for new * direction. * @param Should set changing operations be ignored. Necessary in the middle * of a set change. */ void JoyControlStick::createDeskEvent(bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *eventbutton1 = nullptr; JoyControlStickButton *eventbutton2 = nullptr; JoyControlStickButton *eventbutton3 = nullptr; if (safezone) { switch (currentMode) { case StandardMode: determineStandardModeEvent(eventbutton1, eventbutton2); break; case EightWayMode: determineEightWayModeEvent(eventbutton1, eventbutton2, eventbutton3); break; case FourWayCardinal: determineFourWayCardinalEvent(eventbutton1, eventbutton2); break; case FourWayDiagonal: determineFourWayDiagonalEvent(eventbutton3); break; } } else { currentDirection = StickCentered; } /* * Release any currently active stick buttons. */ if ((eventbutton1 == nullptr) && (activeButton1 != nullptr)) { // Currently in deadzone. Disable currently active button. performButtonRelease(activeButton1, ignoresets); } else if ((eventbutton1 != nullptr) && (activeButton1 != nullptr) && (eventbutton1 != activeButton1)) { // Deadzone skipped. Button for new event is not the currently // active button. Disable the active button. performButtonRelease(activeButton1, ignoresets); } if ((eventbutton2 == nullptr) && (activeButton2 != nullptr)) { // Currently in deadzone. Disable currently active button. performButtonRelease(activeButton2, ignoresets); } else if ((eventbutton2 != nullptr) && (activeButton2 != nullptr) && (eventbutton2 != activeButton2)) { // Deadzone skipped. Button for new event is not the currently // active button. Disable the active button. performButtonRelease(activeButton2, ignoresets); } if ((eventbutton3 == nullptr) && (activeButton3 != nullptr)) { // Currently in deadzone. Disable currently active button. performButtonRelease(activeButton3, ignoresets); } else if ((eventbutton3 != nullptr) && (activeButton3 != nullptr) && (eventbutton3 != activeButton3)) { // Deadzone skipped. Button for new event is not the currently // active button. Disable the active button. performButtonRelease(activeButton3, ignoresets); } if (safezone) { // Activate modifier button before activating directional buttons. // Value from the new stick event will be used to determine // distance events. modifierButton->joyEvent(true, ignoresets); } else { // Release modifier button after releasing directional buttons. modifierButton->joyEvent(false, ignoresets); } /* * Enable stick buttons. */ if ((eventbutton1 != nullptr) && (activeButton1 == nullptr)) { // There is no active button. Call joyEvent and set current // button as active button performButtonPress(eventbutton1, activeButton1, ignoresets); } else if ((eventbutton1 != nullptr) && (activeButton1 != nullptr) && (eventbutton1 == activeButton1)) { // Button is currently active. Just pass current value performButtonPress(eventbutton1, activeButton1, ignoresets); } if ((eventbutton2 != nullptr) && (activeButton2 == nullptr)) { // There is no active button. Call joyEvent and set current // button as active button performButtonPress(eventbutton2, activeButton2, ignoresets); } else if ((eventbutton2 != nullptr) && (activeButton2 != nullptr) && (eventbutton2 == activeButton2)) { // Button is currently active. Just pass current value performButtonPress(eventbutton2, activeButton2, ignoresets); } if ((eventbutton3 != nullptr) && (activeButton3 == nullptr)) { // There is no active button. Call joyEvent and set current // button as active button performButtonPress(eventbutton3, activeButton3, ignoresets); } else if ((eventbutton3 != nullptr) && (activeButton3 != nullptr) && (eventbutton3 == activeButton3)) { // Button is currently active. Just pass current value performButtonPress(eventbutton3, activeButton3, ignoresets); } } /** * @brief Calculate the bearing (in degrees) corresponding to the current * position of the X and Y axes of a stick. * @return Bearing (in degrees) */ double JoyControlStick::calculateBearing() { qInstallMessageHandler(MessageHandler::myMessageOutput); return calculateBearing(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } /** * @brief Calculate the bearing (in degrees) corresponding to the * passed X and Y axes values associated with the stick. * @param X axis value * @param Y axis value * @return Bearing (in degrees) */ double JoyControlStick::calculateBearing(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalAngle = 0.0; int axis1Value = axisXValue; int axis2Value = axisYValue; if ((axis1Value == 0) && (axis2Value == 0)) { finalAngle = 0.0; } else { double temp1 = axis1Value; double temp2 = axis2Value; double angle = (atan2(temp1, -temp2) * 180) / GlobalVariables::JoyControlStick::PI; if ((axis1Value >= 0) && (axis2Value <= 0)) { // NE Quadrant finalAngle = angle; } else if ((axis1Value >= 0) && (axis2Value >= 0)) { // SE Quadrant (angle will be positive) finalAngle = angle; } else if ((axis1Value <= 0) && (axis2Value >= 0)) { // SW Quadrant (angle will be negative) finalAngle = 360.0 + angle; } else if ((axis1Value <= 0) && (axis2Value <= 0)) { // NW Quadrant (angle will be negative) finalAngle = 360.0 + angle; } } return finalAngle; } /** * @brief Get current radial distance of the stick position past the assigned * dead zone. * @return Distance percentage in the range of 0.0 - 1.0. */ double JoyControlStick::getDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } /** * @brief Get radial distance of the stick position past the assigned dead zone * based on the passed X and Y axes values associated with the stick. * @param X axis value * @param Y axis value * @return Distance percentage in the range of 0.0 - 1.0. */ double JoyControlStick::getDistanceFromDeadZone(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); double distance = 0.0; int axis1Value = axisXValue; int axis2Value = axisYValue; double angle2 = atan2(axis1Value, -axis2Value); double ang_sin = sin(angle2); double ang_cos = cos(angle2); int squared_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value); int dist = sqrt(squared_dist); double squareStickFullPhi = qMin((ang_sin != 0.0) ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2); double circle = this->circle; double circleStickFull = (squareStickFullPhi - 1) * circle + 1; double adjustedDist = (circleStickFull > 1.0) ? (dist / circleStickFull) : dist; double adjustedDeadZone = (circleStickFull > 1.0) ? (deadZone / circleStickFull) : deadZone; distance = (adjustedDist - adjustedDeadZone) / (static_cast(maxZone) - adjustedDeadZone); distance = qBound(0.0, distance, 1.0); return distance; } /** * @brief Get distance of the Y axis past the assigned dead zone. * @param Should interpolation be performed along the diagonal regions. * @return Distance percentage in the range of 0.0 - 1.0. */ double JoyControlStick::calculateYDistanceFromDeadZone(bool interpolate) { qInstallMessageHandler(MessageHandler::myMessageOutput); return calculateYDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue(), interpolate); } /** * @brief Get distance of the Y axis past the assigned dead zone based * on the passed X and Y axis values for the analog stick. * @param X axis value * @param Y axis value * @param Should interpolation be performed along the diagonal regions. * @return Distance percentage in the range of 0.0 - 1.0. */ double JoyControlStick::calculateYDistanceFromDeadZone(int axisXValue, int axisYValue, bool interpolate) { qInstallMessageHandler(MessageHandler::myMessageOutput); double distance = 0.0; int axis1Value = axisXValue; int axis2Value = axisYValue; double angle2 = atan2(axis1Value, -axis2Value); double ang_sin = sin(angle2); double ang_cos = cos(angle2); int deadY = abs(floor(deadZone * ang_cos + 0.5)); double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2); double circle = this->circle; double circleStickFull = (squareStickFullPhi - 1) * circle + 1; double adjustedAxis2Value = (circleStickFull > 1.0) ? (axis2Value / circleStickFull) : axis2Value; double adjustedDeadYZone = (circleStickFull > 1.0) ? (deadY / circleStickFull) : deadY; // Interpolation would return the correct value if diagonalRange is 90 but // the routine gets skipped to save time. if (interpolate && (diagonalRange < 90)) { JoyStickDirections direction = calculateStickDirection(axis1Value, axis2Value); if ((direction == StickRightUp) || (direction == StickUp)) { QList tempangles = getDiagonalZoneAngles(); double minangle = tempangles.at(1); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadY = fabs(square_dist * sin(minangle * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadY = qMax(adjustedDeadYZone, mindeadY); double maxRange = static_cast(maxZone) - currentDeadY; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange; distance = tempdist4; } else if ((direction == StickRightDown) || (direction == StickRight)) { QList tempfuck = getDiagonalZoneAngles(); double minangle = tempfuck.at(4); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadY = fabs(square_dist * sin((minangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadY = qMax(adjustedDeadYZone, mindeadY); double maxRange = static_cast(maxZone) - currentDeadY; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange; distance = tempdist4; } else if ((direction == StickLeftDown) || (direction == StickDown)) { QList tempangles = getDiagonalZoneAngles(); double minangle = tempangles.at(6); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadY = fabs(square_dist * sin((minangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadY = qMax(adjustedDeadYZone, mindeadY); double maxRange = static_cast(maxZone) - currentDeadY; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange; distance = tempdist4; } else if ((direction == StickLeftUp) || (direction == StickLeft)) { QList tempangles = getDiagonalZoneAngles(); double minangle = tempangles.at(8); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadY = fabs(square_dist * sin((minangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadY = qMax(adjustedDeadYZone, mindeadY); double maxRange = static_cast(maxZone) - currentDeadY; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange; distance = tempdist4; } else { // Backup plan. Should not arrive here. double maxRange = static_cast(maxZone) - adjustedDeadYZone; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis2Value) - adjustedDeadYZone) / maxRange; distance = tempdist4; } } else { // No interpolation desired or diagonal range is 90 degrees. double maxRange = static_cast(maxZone) - adjustedDeadYZone; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis2Value) - adjustedDeadYZone) / maxRange; distance = tempdist4; } distance = qBound(0.0, distance, 1.0); return distance; } /** * @brief Get distance of the X axis past the assigned dead zone. * @param Should interpolation be performed along the diagonal regions. * @return Distance percentage in the range of 0.0 - 1.0. */ double JoyControlStick::calculateXDistanceFromDeadZone(bool interpolate) { qInstallMessageHandler(MessageHandler::myMessageOutput); return calculateXDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue(), interpolate); } /** * @brief Get distance of the X axis past the assigned dead zone based * on the passed X and Y axis values for the analog stick. * @param X axis value * @param Y axis value * @param Should interpolation be performed along the diagonal regions. * @return Distance percentage in the range of 0.0 - 1.0. */ double JoyControlStick::calculateXDistanceFromDeadZone(int axisXValue, int axisYValue, bool interpolate) { qInstallMessageHandler(MessageHandler::myMessageOutput); double distance = 0.0; int axis1Value = axisXValue; int axis2Value = axisYValue; double angle2 = atan2(axis1Value, -axis2Value); double ang_sin = sin(angle2); double ang_cos = cos(angle2); int deadX = abs(floor(deadZone * ang_sin + 0.5)); double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2); double circle = this->circle; double circleStickFull = (squareStickFullPhi - 1) * circle + 1; double adjustedAxis1Value = (circleStickFull > 1.0) ? (axis1Value / circleStickFull) : axis1Value; double adjustedDeadXZone = (circleStickFull > 1.0) ? (deadX / circleStickFull) : deadX; // Interpolation would return the correct value if diagonalRange is 90 but // the routine gets skipped to save time. if (interpolate && (diagonalRange < 90)) { JoyStickDirections direction = calculateStickDirection(axis1Value, axis2Value); if ((direction == StickRightUp) || (direction == StickRight)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(3); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadX = fabs(square_dist * cos(maxangle * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadX = qMax(mindeadX, adjustedDeadXZone); double maxRange = static_cast(maxZone) - currentDeadX; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange; distance = tempdist4; } else if ((direction == StickRightDown) || (direction == StickDown)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(5); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadX = fabs(square_dist * cos((maxangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadX = qMax(mindeadX, adjustedDeadXZone); double maxRange = static_cast(maxZone) - currentDeadX; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange; distance = tempdist4; } else if ((direction == StickLeftDown) || (direction == StickLeft)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(7); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadX = fabs(square_dist * cos((maxangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadX = qMax(mindeadX, adjustedDeadXZone); double maxRange = static_cast(maxZone) - currentDeadX; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange; distance = tempdist4; } else if ((direction == StickLeftUp) || (direction == StickUp)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(1); double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value); double mindeadX = fabs(square_dist * cos((maxangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0)); double currentDeadX = qMax(mindeadX, adjustedDeadXZone); double maxRange = static_cast(maxZone) - currentDeadX; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange; distance = tempdist4; } else { // Backup plan. Should not arrive here. double maxRange = static_cast(maxZone) - adjustedDeadXZone; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis1Value) - adjustedDeadXZone) / maxRange; distance = tempdist4; } } else { // No interpolation desired or diagonal range is 90 degrees. double maxRange = static_cast(maxZone) - adjustedDeadXZone; double tempdist4 = 0.0; if (maxRange != 0.0) tempdist4 = (fabs(adjustedAxis1Value) - adjustedDeadXZone) / maxRange; distance = tempdist4; } distance = qBound(0.0, distance, 1.0); return distance; } /** * @brief Get the raw radial distance of the stick. Values will be between 0 - 32,767. * @return Radial distance in the range of 0 - 32,767. */ double JoyControlStick::getAbsoluteRawDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double temp = getAbsoluteRawDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); return temp; } double JoyControlStick::getAbsoluteRawDistance(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); int axis1Value = axisXValue; int axis2Value = axisYValue; int square_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value); return sqrt(square_dist); } double JoyControlStick::getNormalizedAbsoluteDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); int axis1Value = axisX->getCurrentRawValue(); int axis2Value = axisY->getCurrentRawValue(); int square_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value); double distance = sqrt(square_dist) / static_cast(maxZone); if (distance > 1.0) distance = 1.0; else if (distance < 0.0) distance = 0.0; return distance; } double JoyControlStick::getRadialDistance(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); int axis1Value = axisXValue; int axis2Value = axisYValue; int square_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value); double distance = sqrt(square_dist) / static_cast(maxZone); if (distance > 1.0) distance = 1.0; else if (distance < 0.0) distance = 0.0; return distance; } void JoyControlStick::setIndex(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->index = index; } int JoyControlStick::getIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); return index; } int JoyControlStick::getRealJoyIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); return index + 1; } QString JoyControlStick::getName(bool forceFullFormat, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = getPartialName(forceFullFormat, displayNames); label.append(": "); QStringList tempList = QStringList(); if (buttons.contains(StickUp)) { JoyControlStickButton *button = buttons.value(StickUp); if (!button->getButtonName().isEmpty()) tempList.append(button->getButtonName()); else tempList.append(button->getSlotsSummary()); } if (buttons.contains(StickLeft)) { JoyControlStickButton *button = buttons.value(StickLeft); if (!button->getButtonName().isEmpty()) tempList.append(button->getButtonName()); else tempList.append(button->getSlotsSummary()); } if (buttons.contains(StickDown)) { JoyControlStickButton *button = buttons.value(StickDown); if (!button->getButtonName().isEmpty()) tempList.append(button->getButtonName()); else tempList.append(button->getSlotsSummary()); } if (buttons.contains(StickRight)) { JoyControlStickButton *button = buttons.value(StickRight); if (!button->getButtonName().isEmpty()) tempList.append(button->getButtonName()); else tempList.append(button->getSlotsSummary()); } label.append(tempList.join(", ")); return label; } QString JoyControlStick::getPartialName(bool forceFullFormat, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); if (!stickName.isEmpty() && displayNames) { if (forceFullFormat) label.append(tr("Stick")).append(" "); label.append(stickName); } else if (!defaultStickName.isEmpty()) { if (forceFullFormat) label.append(tr("Stick")).append(" "); label.append(defaultStickName); } else { label.append(tr("Stick")).append(" "); label.append(QString::number(getRealJoyIndex())); } setStickName(label); return label; } void JoyControlStick::setDefaultStickName(QString tempname) { qInstallMessageHandler(MessageHandler::myMessageOutput); defaultStickName = tempname; emit stickNameChanged(); } QString JoyControlStick::getDefaultStickName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return defaultStickName; } int JoyControlStick::getMaxZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return maxZone; } int JoyControlStick::getCurrentlyAssignedSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); return originset; } void JoyControlStick::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); deadZone = 8000; maxZone = GlobalVariables::JoyAxis::AXISMAXZONE; diagonalRange = 45; isActive = false; pendingStickEvent = false; activeButton1 = nullptr; activeButton2 = nullptr; activeButton3 = nullptr; safezone = false; currentDirection = StickCentered; currentMode = StandardMode; stickName.clear(); circle = GlobalVariables::JoyControlStick::DEFAULTCIRCLE; stickDelay = GlobalVariables::JoyControlStick::DEFAULTSTICKDELAY; resetButtons(); } void JoyControlStick::setDeadZone(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); value = abs(value); if (value > getAxisX()->getAxisMaxCal()) value = getAxisX()->getAxisMaxCal(); if ((value != deadZone) && (value <= maxZone)) { deadZone = value; emit deadZoneChanged(value); emit propertyUpdated(); } } void JoyControlStick::setMaxZone(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); value = abs(value); if (value >= getAxisX()->getAxisMaxCal()) value = getAxisX()->getAxisMaxCal(); if ((value != maxZone) && (value > deadZone)) { maxZone = value; emit maxZoneChanged(value); emit propertyUpdated(); } } bool JoyControlStick::wasCalibrated() { return calibrated; } void JoyControlStick::setCalibrationFlag(bool flag) { calibrated = flag; } QString JoyControlStick::getCalibrationSummary() { return calibrationSummary; } void JoyControlStick::setCalibrationSummary(QString text) { calibrationSummary = text; } /** * @brief Set the diagonal range value for a stick. * @param Value between 1 - 90. */ void JoyControlStick::setDiagonalRange(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value < 1) value = 1; else if (value > 90) value = 90; if (value != diagonalRange) { diagonalRange = value; emit diagonalRangeChanged(value); emit propertyUpdated(); } } /** * @brief Delete old stick direction buttons and create new stick direction * buttons. */ void JoyControlStick::refreshButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); deleteButtons(); populateButtons(); } /** * @brief Delete stick direction buttons and stick modifier button. */ void JoyControlStick::deleteButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyButton *button = iter.next().value(); if (button != nullptr) { delete button; button = nullptr; } } buttons.clear(); if (modifierButton != nullptr) { delete modifierButton; modifierButton = nullptr; } } /** * @brief Take a XML stream and set the stick and direction button properties * according to the values contained within the stream. * @param QXmlStreamReader instance that will be used to read property values. */ void JoyControlStick::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == "stick")) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "stick"))) { if ((xml->name() == "deadZone") && xml->isStartElement()) { QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); this->setDeadZone(tempchoice); } else if ((xml->name() == "maxZone") && xml->isStartElement()) { QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); this->setMaxZone(tempchoice); } else if ((xml->name() == "calibrated") && xml->isStartElement()) { QString temptext = xml->readElementText(); bool tempchoice = (temptext == "true") ? true : false; this->setCalibrationFlag(tempchoice); } else if ((xml->name() == "summary") && xml->isStartElement()) { QString temptext = xml->readElementText(); this->setCalibrationSummary(temptext); } else if ((xml->name() == "diagonalRange") && xml->isStartElement()) { QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); this->setDiagonalRange(tempchoice); } else if ((xml->name() == "mode") && xml->isStartElement()) { QString temptext = xml->readElementText(); if (temptext == "eight-way") { this->setJoyMode(EightWayMode); } else if (temptext == "four-way") { this->setJoyMode(FourWayCardinal); } else if (temptext == "diagonal") { this->setJoyMode(FourWayDiagonal); } } else if ((xml->name() == "squareStick") && xml->isStartElement()) { int tempchoice = xml->readElementText().toInt(); if ((tempchoice > 0) && (tempchoice <= 100)) this->setCircleAdjust(tempchoice / 100.0); } else if ((xml->name() == GlobalVariables::JoyControlStickButton::xmlName) && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); JoyControlStickButton *button = buttons.value(static_cast(index)); QPointer joyButtonXml = new JoyButtonXml(button); if (button != nullptr) joyButtonXml->readConfig(xml); else xml->skipCurrentElement(); if (!joyButtonXml.isNull()) delete joyButtonXml; } else if ((xml->name() == GlobalVariables::JoyControlStickModifierButton::xmlName) && xml->isStartElement()) { JoyButtonXml *joyButtonXml = new JoyButtonXml(modifierButton); joyButtonXml->readConfig(xml); } else if ((xml->name() == "stickDelay") && xml->isStartElement()) { QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); this->setStickDelay(tempchoice); } else { xml->skipCurrentElement(); } xml->readNextStartElement(); } } } /** * @brief Write the status of the properties of a stick and direction buttons * to an XML stream. * @param QXmlStreamWriter instance that will be used to write a profile. */ void JoyControlStick::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!isDefault()) { xml->writeStartElement("stick"); xml->writeAttribute("index", QString::number(index + 1)); if (deadZone != GlobalVariables::JoyControlStick::DEFAULTDEADZONE) xml->writeTextElement("deadZone", QString::number(deadZone)); if (maxZone != GlobalVariables::JoyControlStick::DEFAULTMAXZONE) xml->writeTextElement("maxZone", QString::number(maxZone)); xml->writeTextElement("calibrated", (calibrated ? "true" : "false")); xml->writeTextElement("summary", (getCalibrationSummary().isEmpty() ? "" : calibrationSummary)); if ((currentMode == StandardMode || currentMode == EightWayMode) && (diagonalRange != GlobalVariables::JoyControlStick::DEFAULTDIAGONALRANGE)) { xml->writeTextElement("diagonalRange", QString::number(diagonalRange)); } switch (currentMode) { case EightWayMode: xml->writeTextElement("mode", "eight-way"); break; case FourWayCardinal: xml->writeTextElement("mode", "four-way"); break; case FourWayDiagonal: xml->writeTextElement("mode", "diagonal"); break; default: break; } if (circle > GlobalVariables::JoyControlStick::DEFAULTCIRCLE) xml->writeTextElement("squareStick", QString::number(circle * 100)); if (stickDelay > GlobalVariables::JoyControlStick::DEFAULTSTICKDELAY) xml->writeTextElement("stickDelay", QString::number(stickDelay)); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); JoyButtonXml *joyButtonXml = new JoyButtonXml(button); joyButtonXml->writeConfig(xml); delete joyButtonXml; joyButtonXml = nullptr; } if (!modifierButton->isDefault()) { JoyButtonXml *joyButtonXmlModif = new JoyButtonXml(modifierButton); joyButtonXmlModif->writeConfig(xml); } xml->writeEndElement(); } } /** * @brief Reset all the properties of the stick direction buttons and the * stick modifier button. */ void JoyControlStick::resetButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyButton *button = iter.next().value(); if (button != nullptr) button->reset(); } if (modifierButton != nullptr) modifierButton->reset(); } /** * @brief Get a pointer to the stick direction button for the desired * direction. * @param Value of the direction of the stick. * @return Pointer to the stick direction button for the stick * direction. */ JoyControlStickButton *JoyControlStick::getDirectionButton(JoyStickDirections direction) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *button = buttons.value(direction); return button; } /** * @brief Used to calculate the distance value that should be used for mouse * movement. * @param button * @return Distance factor that should be used for mouse movement */ double JoyControlStick::calculateMouseDirectionalDistance(JoyControlStickButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalDistance = 0.0; switch (currentDirection) { case StickUp: { finalDistance = calculateYDistanceFromDeadZone(true); break; } case StickRightUp: { if ((activeButton1 != nullptr) && (activeButton1 == button)) { finalDistance = calculateXDistanceFromDeadZone(true); } else if ((activeButton2 != nullptr) && (activeButton2 == button)) { finalDistance = calculateYDistanceFromDeadZone(true); } else if ((activeButton3 != nullptr) && (activeButton3 == button)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(); } break; } case StickRight: { finalDistance = calculateXDistanceFromDeadZone(true); break; } case StickRightDown: { if ((activeButton1 != nullptr) && (activeButton1 == button)) { finalDistance = calculateXDistanceFromDeadZone(true); } else if ((activeButton2 != nullptr) && (activeButton2 == button)) { finalDistance = calculateYDistanceFromDeadZone(true); } else if ((activeButton3 != nullptr) && (activeButton3 == button)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(); } break; } case StickDown: { finalDistance = calculateYDistanceFromDeadZone(true); break; } case StickLeftDown: { if ((activeButton1 != nullptr) && (activeButton1 == button)) { finalDistance = calculateXDistanceFromDeadZone(true); } else if ((activeButton2 != nullptr) && (activeButton2 == button)) { finalDistance = calculateYDistanceFromDeadZone(true); } else if ((activeButton3 != nullptr) && (activeButton3 == button)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(); } break; } case StickLeft: { finalDistance = calculateXDistanceFromDeadZone(true); break; } case StickLeftUp: { if ((activeButton1 != nullptr) && (activeButton1 == button)) { finalDistance = calculateXDistanceFromDeadZone(true); } else if ((activeButton2 != nullptr) && (activeButton2 == button)) { finalDistance = calculateYDistanceFromDeadZone(true); } else if ((activeButton3 != nullptr) && (activeButton3 == button)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(); } break; } default: break; } return finalDistance; } double JoyControlStick::calculateLastMouseDirectionalDistance(JoyControlStickButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalDistance = 0.0; JoyStickDirections direction = calculateStickDirection(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); if ((direction == StickUp) && (button->getJoyNumber() == static_cast(StickUp))) { if (axisY->getLastKnownThrottleValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (direction == StickRightUp) { if (button->getJoyNumber() == static_cast(StickRight)) { if (axisX->getLastKnownThrottleValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickUp)) { if (axisY->getLastKnownThrottleValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickRightUp)) { if ((axisX->getLastKnownThrottleValue() <= 0) || (axisY->getLastKnownThrottleValue() >= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } } } else if ((direction == StickRight) && (button->getJoyNumber() == static_cast(StickRight))) { if (axisX->getLastKnownThrottleValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (direction == StickRightDown) { if (button->getJoyNumber() == static_cast(StickRight)) { if (axisX->getLastKnownThrottleValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickDown)) { if (axisY->getLastKnownThrottleValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickRightDown)) { if ((axisX->getLastKnownThrottleValue() <= 0) || (axisY->getLastKnownThrottleValue() >= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } } } else if (direction == StickDown && (button->getJoyNumber() == static_cast(StickDown))) { if (axisY->getLastKnownThrottleValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (direction == StickLeftDown) { if (button->getJoyNumber() == static_cast(StickLeft)) { if (axisX->getLastKnownThrottleValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickDown)) { if (axisY->getLastKnownThrottleValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickLeftDown)) { if ((axisX->getLastKnownThrottleValue() >= 0) || (axisY->getLastKnownThrottleValue() <= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } } } else if ((direction == StickLeft) && (button->getJoyNumber() == static_cast(StickLeft))) { if (axisX->getLastKnownThrottleValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (direction == StickLeftUp) { if (button->getJoyNumber() == static_cast(StickLeft)) { if (axisX->getLastKnownThrottleValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickUp)) { if (axisY->getLastKnownThrottleValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true); } } else if (button->getJoyNumber() == static_cast(StickLeftUp)) { if ((axisX->getLastKnownThrottleValue() >= 0) || (axisY->getLastKnownThrottleValue() >= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } } } return finalDistance; } double JoyControlStick::calculateLastDirectionalDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalDistance = 0.0; JoyStickDirections direction = calculateStickDirection(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); switch (direction) { case StickUp: { if (!(axisX->getLastKnownThrottleValue() >= 0)) { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } case StickRightUp: { if (!(axisY->getLastKnownThrottleValue() <= 0) && !(axisY->getLastKnownThrottleValue() >= 0)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } case StickRight: { if (!(axisX->getLastKnownThrottleValue() <= 0)) { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } case StickRightDown: { if (!(axisY->getLastKnownThrottleValue() <= 0) && !(axisY->getLastKnownThrottleValue() <= 0)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } case StickDown: { if (!(axisY->getLastKnownThrottleValue() <= 0)) { finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } case StickLeftDown: { if (!(axisY->getLastKnownThrottleValue() >= 0) && !(axisY->getLastKnownThrottleValue() <= 0)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } case StickLeft: { if (!(axisX->getLastKnownThrottleValue() >= 0)) { finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } case StickLeftUp: { if (!(axisY->getLastKnownThrottleValue() >= 0) && !(axisY->getLastKnownThrottleValue() >= 0)) { finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue()); } break; } default: break; } return finalDistance; } double JoyControlStick::calculateLastAccelerationDirectionalDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalDistance = 0.0; switch (currentDirection) { case StickUp: { if (!(axisX->getLastKnownRawValue() >= 0)) finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); break; } case StickRightUp: { if (!(axisY->getLastKnownRawValue() <= 0) && !(axisY->getLastKnownRawValue() >= 0)) finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); break; } case StickRight: { if (!(axisX->getLastKnownRawValue() <= 0)) finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); break; } case StickRightDown: { if (!(axisY->getLastKnownRawValue() <= 0) && !(axisY->getLastKnownRawValue() <= 0)) finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); break; } case StickDown: { if (!(axisY->getLastKnownRawValue() <= 0)) finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); break; } case StickLeftDown: { if (!(axisY->getLastKnownRawValue() >= 0) && !(axisY->getLastKnownRawValue() <= 0)) finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); break; } case StickLeft: { if (!(axisX->getLastKnownRawValue() >= 0)) finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); break; } case StickLeftUp: { if (!(axisY->getLastKnownRawValue() >= 0) && !(axisY->getLastKnownRawValue() >= 0)) finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); break; } default: break; } return finalDistance; } /** * @brief Used to calculate the distance value that should be used for keyboard * events and distance slots * @return Distance factor that should be used for keyboard events and * distance slots */ double JoyControlStick::calculateDirectionalDistance() { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalDistance = 0.0; switch (currentDirection) { case StickUp: { finalDistance = calculateYDistanceFromDeadZone(); break; } case StickRightUp: { finalDistance = getDistanceFromDeadZone(); break; } case StickRight: { finalDistance = calculateXDistanceFromDeadZone(); break; } case StickRightDown: { finalDistance = getDistanceFromDeadZone(); break; } case StickDown: { finalDistance = calculateYDistanceFromDeadZone(); break; } case StickLeftDown: { finalDistance = getDistanceFromDeadZone(); break; } case StickLeft: { finalDistance = calculateXDistanceFromDeadZone(); break; } case StickLeftUp: { finalDistance = getDistanceFromDeadZone(); break; } default: break; } return finalDistance; } /** * @brief Get the value for the currently active stick direction. * @return Value of the corresponding active stick direction. */ JoyControlStick::JoyStickDirections JoyControlStick::getCurrentDirection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentDirection; } /** * @brief Get the value for the corresponding X axis. * @return X axis value. */ int JoyControlStick::getXCoordinate() { qInstallMessageHandler(MessageHandler::myMessageOutput); return axisX->getCurrentRawValue(); } /** * @brief Get the value for the corresponding Y axis. * @return Y axis value. */ int JoyControlStick::getYCoordinate() { qInstallMessageHandler(MessageHandler::myMessageOutput); return axisY->getCurrentRawValue(); } int JoyControlStick::getCircleXCoordinate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int axisXValue = axisX->getCurrentRawValue(); int axisYValue = axisX->getCurrentRawValue(); if (this->circle > 0.0) axisXValue = calculateCircleXValue(axisXValue, axisYValue); return axisXValue; } int JoyControlStick::getCircleYCoordinate() { qInstallMessageHandler(MessageHandler::myMessageOutput); int axisXValue = axisX->getCurrentRawValue(); int axisYValue = axisY->getCurrentRawValue(); if (this->circle > 0.0) axisYValue = calculateCircleYValue(axisXValue, axisYValue); return axisYValue; } int JoyControlStick::calculateCircleXValue(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); int value = axisXValue; if (this->circle > 0.0) { int axis1Value = axisXValue; int axis2Value = axisYValue; double angle2 = atan2(axis1Value, -axis2Value); double ang_sin = sin(angle2); double ang_cos = cos(angle2); double squareStickFull = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2); double circle = this->circle; double circleStickFull = (squareStickFull - 1) * circle + 1; value = (circleStickFull > 1.0) ? floor((axisXValue / circleStickFull) + 0.5) : value; } return value; } int JoyControlStick::calculateCircleYValue(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); int value = axisYValue; if (this->circle > 0.0) { int axis1Value = axisXValue; int axis2Value = axisYValue; double angle2 = atan2(axis1Value, -axis2Value); double ang_sin = sin(angle2); double ang_cos = cos(angle2); double squareStickFull = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2); double circle = this->circle; double circleStickFull = (squareStickFull - 1) * circle + 1; value = (circleStickFull > 1.0) ? floor((axisYValue / circleStickFull) + 0.5) : value; } return value; } QList JoyControlStick::getDiagonalZoneAngles() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList anglesList; int diagonalAngle = diagonalRange; double cardinalAngle = (360 - (diagonalAngle * 4)) / 4.0; double initialLeft = 360 - ((cardinalAngle) / 2.0); double initialRight = ((cardinalAngle) / 2.0); double upRightInitial = initialRight; double rightInitial = upRightInitial + diagonalAngle; double downRightInitial = rightInitial + cardinalAngle; double downInitial = downRightInitial + diagonalAngle; double downLeftInitial = downInitial + cardinalAngle; double leftInitial = downLeftInitial + diagonalAngle; double upLeftInitial = leftInitial + cardinalAngle; anglesList.append(initialLeft); anglesList.append(initialRight); anglesList.append(upRightInitial); anglesList.append(rightInitial); anglesList.append(downRightInitial); anglesList.append(downInitial); anglesList.append(downLeftInitial); anglesList.append(leftInitial); anglesList.append(upLeftInitial); return anglesList; } QList JoyControlStick::getFourWayCardinalZoneAngles() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList anglesList; int zoneRange = 90; int rightInitial = 45; int downInitial = rightInitial + zoneRange; int leftInitial = downInitial + zoneRange; int upInitial = leftInitial + zoneRange; anglesList.append(rightInitial); anglesList.append(downInitial); anglesList.append(leftInitial); anglesList.append(upInitial); return anglesList; } QList JoyControlStick::getFourWayDiagonalZoneAngles() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList anglesList; int zoneRange = 90; int upRightInitial = 0; int downRightInitial = zoneRange; int downLeftInitial = downRightInitial + zoneRange; int upLeftInitial = downLeftInitial + zoneRange; anglesList.append(upRightInitial); anglesList.append(downRightInitial); anglesList.append(downLeftInitial); anglesList.append(upLeftInitial); return anglesList; } QHash *JoyControlStick::getButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &buttons; } JoyAxis *JoyControlStick::getAxisX() { qInstallMessageHandler(MessageHandler::myMessageOutput); return axisX; } JoyAxis *JoyControlStick::getAxisY() { qInstallMessageHandler(MessageHandler::myMessageOutput); return axisY; } void JoyControlStick::replaceXAxis(JoyAxis *axis) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (axis->getParentSet() == axisY->getParentSet()) { axisX->removeControlStick(); this->axisX = axis; this->axisX->setControlStick(this); } } void JoyControlStick::replaceYAxis(JoyAxis *axis) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (axis->getParentSet() == axisX->getParentSet()) { axisY->removeControlStick(); this->axisY = axis; this->axisY->setControlStick(this); } } void JoyControlStick::replaceAxes(JoyAxis *axisX, JoyAxis *axisY) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (axisX->getParentSet() == axisY->getParentSet()) { this->axisX->removeControlStick(); this->axisY->removeControlStick(); this->axisX = axisX; this->axisY = axisY; this->axisX->setControlStick(this); this->axisY->setControlStick(this); } } void JoyControlStick::setJoyMode(JoyMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); currentMode = mode; emit joyModeChanged(); emit propertyUpdated(); } JoyControlStick::JoyMode JoyControlStick::getJoyMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentMode; } void JoyControlStick::releaseButtonEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->joyEvent(false, true); } } bool JoyControlStick::isDefault() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool value = true; value = value && (deadZone == GlobalVariables::JoyControlStick::DEFAULTDEADZONE); value = value && (maxZone == GlobalVariables::JoyControlStick::DEFAULTMAXZONE); value = value && (diagonalRange == GlobalVariables::JoyControlStick::DEFAULTDIAGONALRANGE); value = value && (currentMode == DEFAULTMODE); value = value && qFuzzyCompare(circle, GlobalVariables::JoyControlStick::DEFAULTCIRCLE); value = value && (stickDelay == GlobalVariables::JoyControlStick::DEFAULTSTICKDELAY); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); value = value && (button->isDefault()); } if (modifierButton != nullptr) value = value && modifierButton->isDefault(); return value; } void JoyControlStick::setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setMouseMode(mode); } } bool JoyControlStick::hasSameButtonsMouseMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; JoyButton::JoyMouseMovementMode initialMode = JoyButton::MouseCursor; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); initialMode = button->getMouseMode(); } else { JoyControlStickButton *button = iter.next().value(); JoyButton::JoyMouseMovementMode temp = button->getMouseMode(); if (temp != initialMode) { result = false; iter.toBack(); } } } return result; } JoyButton::JoyMouseMovementMode JoyControlStick::getButtonsPresetMouseMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseMovementMode resultMode = JoyButton::MouseCursor; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); resultMode = button->getMouseMode(); } else { JoyControlStickButton *button = iter.next().value(); JoyButton::JoyMouseMovementMode temp = button->getMouseMode(); if (temp != resultMode) { resultMode = JoyButton::MouseCursor; iter.toBack(); } } } return resultMode; } void JoyControlStick::setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setMouseCurve(mouseCurve); } } bool JoyControlStick::hasSameButtonsMouseCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; JoyButton::JoyMouseCurve initialCurve = JoyButton::LinearCurve; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); initialCurve = button->getMouseCurve(); } else { JoyControlStickButton *button = iter.next().value(); JoyButton::JoyMouseCurve temp = button->getMouseCurve(); if (temp != initialCurve) { result = false; iter.toBack(); } } } return result; } JoyButton::JoyMouseCurve JoyControlStick::getButtonsPresetMouseCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve resultCurve = JoyButton::LinearCurve; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); resultCurve = button->getMouseCurve(); } else { JoyControlStickButton *button = iter.next().value(); JoyButton::JoyMouseCurve temp = button->getMouseCurve(); if (temp != resultCurve) { resultCurve = JoyButton::LinearCurve; iter.toBack(); } } } return resultCurve; } void JoyControlStick::setButtonsSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setSpringWidth(value); } } void JoyControlStick::setButtonsSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setSpringHeight(value); } } int JoyControlStick::getButtonsPresetSpringWidth() { qInstallMessageHandler(MessageHandler::myMessageOutput); int presetSpringWidth = 0; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); presetSpringWidth = button->getSpringWidth(); } else { JoyControlStickButton *button = iter.next().value(); int temp = button->getSpringWidth(); if (temp != presetSpringWidth) { presetSpringWidth = 0; iter.toBack(); } } } return presetSpringWidth; } int JoyControlStick::getButtonsPresetSpringHeight() { qInstallMessageHandler(MessageHandler::myMessageOutput); int presetSpringHeight = 0; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); presetSpringHeight = button->getSpringHeight(); } else { JoyControlStickButton *button = iter.next().value(); int temp = button->getSpringHeight(); if (temp != presetSpringHeight) { presetSpringHeight = 0; iter.toBack(); } } } return presetSpringHeight; } void JoyControlStick::setButtonsSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setSensitivity(value); } } double JoyControlStick::getButtonsPresetSensitivity() { qInstallMessageHandler(MessageHandler::myMessageOutput); double presetSensitivity = 1.0; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); presetSensitivity = button->getSensitivity(); } else { JoyControlStickButton *button = iter.next().value(); double temp = button->getSensitivity(); if (!qFuzzyCompare(temp, presetSensitivity)) { presetSensitivity = 1.0; iter.toBack(); } } } return presetSensitivity; } QHash JoyControlStick::getApplicableButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash; if ((currentMode == StandardMode) || (currentMode == EightWayMode) || (currentMode == FourWayCardinal)) { temphash.insert(StickUp, buttons.value(StickUp)); temphash.insert(StickDown, buttons.value(StickDown)); temphash.insert(StickLeft, buttons.value(StickLeft)); temphash.insert(StickRight, buttons.value(StickRight)); } if ((currentMode == EightWayMode) || (currentMode == FourWayDiagonal)) { temphash.insert(StickLeftUp, buttons.value(StickLeftUp)); temphash.insert(StickRightUp, buttons.value(StickRightUp)); temphash.insert(StickRightDown, buttons.value(StickRightDown)); temphash.insert(StickLeftDown, buttons.value(StickLeftDown)); } return temphash; } void JoyControlStick::setStickName(QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((tempName.length() <= 20) && (tempName != stickName)) { stickName = tempName; emit stickNameChanged(); // emit propertyUpdated(); } } QString JoyControlStick::getStickName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return stickName; } void JoyControlStick::setButtonsWheelSpeedX(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setWheelSpeed(value, 'X'); } } void JoyControlStick::setButtonsWheelSpeedY(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setWheelSpeed(value, 'Y'); } } /** * @brief Get pointer to the set that a stick belongs to. * @return Pointer to the set that a stick belongs to. */ SetJoystick *JoyControlStick::getParentSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *temp = nullptr; if (axisX != nullptr) temp = axisX->getParentSet(); else if (axisY != nullptr) temp = axisY->getParentSet(); return temp; } /** * @brief Activate a stick direction button. * @param Stick direction button that will be activated. * @param [out] Pointer to the currently active button. * @param Should set changing routines be ignored. */ void JoyControlStick::performButtonPress(JoyControlStickButton *eventbutton, JoyControlStickButton *&activebutton, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); activebutton = eventbutton; eventbutton->joyEvent(true, ignoresets); } /** * @brief Stick direction button to release. * @param Stick direction button that will be released. * @param Should set changing routines be ignored. */ void JoyControlStick::performButtonRelease(JoyControlStickButton *&eventbutton, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); eventbutton->joyEvent(false, ignoresets); eventbutton = nullptr; } /** * @brief Determine which stick direction buttons should be active for a * standard mode stick. * @param [out] Pointer to an X axis stick direction button that should be active. * @param [out] Pointer to a Y axis stick direction button that should be active. */ void JoyControlStick::determineStandardModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2) { qInstallMessageHandler(MessageHandler::myMessageOutput); double bearing = calculateBearing(); QList anglesList = getDiagonalZoneAngles(); double initialLeft = anglesList.value(0); double initialRight = anglesList.value(1); double upRightInitial = anglesList.value(2); double rightInitial = anglesList.value(3); double downRightInitial = anglesList.value(4); double downInitial = anglesList.value(5); double downLeftInitial = anglesList.value(6); double leftInitial = anglesList.value(7); double upLeftInitial = anglesList.value(8); if ((bearing <= initialRight) || (bearing >= initialLeft)) { currentDirection = StickUp; eventbutton2 = buttons.value(StickUp); } else if ((bearing >= upRightInitial) && (bearing < rightInitial)) { currentDirection = StickRightUp; eventbutton1 = buttons.value(StickRight); eventbutton2 = buttons.value(StickUp); } else if ((bearing >= rightInitial) && (bearing < downRightInitial)) { currentDirection = StickRight; eventbutton1 = buttons.value(StickRight); } else if ((bearing >= downRightInitial) && (bearing < downInitial)) { currentDirection = StickRightDown; eventbutton1 = buttons.value(StickRight); eventbutton2 = buttons.value(StickDown); } else if ((bearing >= downInitial) && (bearing < downLeftInitial)) { currentDirection = StickDown; eventbutton2 = buttons.value(StickDown); } else if ((bearing >= downLeftInitial) && (bearing < leftInitial)) { currentDirection = StickLeftDown; eventbutton1 = buttons.value(StickLeft); eventbutton2 = buttons.value(StickDown); } else if ((bearing >= leftInitial) && (bearing < upLeftInitial)) { currentDirection = StickLeft; eventbutton1 = buttons.value(StickLeft); } else if ((bearing >= upLeftInitial) && (bearing < initialLeft)) { currentDirection = StickLeftUp; eventbutton1 = buttons.value(StickLeft); eventbutton2 = buttons.value(StickUp); } } /** * @brief Determine which stick direction button should be active for a 8 way * mode stick. * @param [out] Pointer to an X axis stick direction button that should be active. * @param [out] Pointer to a Y axis stick direction button that should be active. * @param [out] Pointer to a diagonal stick direction button that should be active. */ void JoyControlStick::determineEightWayModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2, JoyControlStickButton *&eventbutton3) { qInstallMessageHandler(MessageHandler::myMessageOutput); double bearing = calculateBearing(); QList anglesList = getDiagonalZoneAngles(); double initialLeft = anglesList.value(0); double initialRight = anglesList.value(1); double upRightInitial = anglesList.value(2); double rightInitial = anglesList.value(3); double downRightInitial = anglesList.value(4); double downInitial = anglesList.value(5); double downLeftInitial = anglesList.value(6); double leftInitial = anglesList.value(7); double upLeftInitial = anglesList.value(8); if ((bearing <= initialRight) || (bearing >= initialLeft)) { currentDirection = StickUp; eventbutton2 = buttons.value(StickUp); } else if ((bearing >= upRightInitial) && (bearing < rightInitial)) { currentDirection = StickRightUp; eventbutton3 = buttons.value(StickRightUp); } else if ((bearing >= rightInitial) && (bearing < downRightInitial)) { currentDirection = StickRight; eventbutton1 = buttons.value(StickRight); } else if ((bearing >= downRightInitial) && (bearing < downInitial)) { currentDirection = StickRightDown; eventbutton3 = buttons.value(StickRightDown); } else if ((bearing >= downInitial) && (bearing < downLeftInitial)) { currentDirection = StickDown; eventbutton2 = buttons.value(StickDown); } else if ((bearing >= downLeftInitial) && (bearing < leftInitial)) { currentDirection = StickLeftDown; eventbutton3 = buttons.value(StickLeftDown); } else if ((bearing >= leftInitial) && (bearing < upLeftInitial)) { currentDirection = StickLeft; eventbutton1 = buttons.value(StickLeft); } else if ((bearing >= upLeftInitial) && (bearing < initialLeft)) { currentDirection = StickLeftUp; eventbutton3 = buttons.value(StickLeftUp); } } /** * @brief Determine which cardinal stick direction button should be active * when using a four way cardinal stick. * @param [out] Pointer to an X axis stick direction button that should be active. * @param [out] Pointer to a Y axis stick direction button that should be active. */ void JoyControlStick::determineFourWayCardinalEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2) { qInstallMessageHandler(MessageHandler::myMessageOutput); double bearing = calculateBearing(); QList anglesList = getFourWayCardinalZoneAngles(); int rightInitial = anglesList.value(0); int downInitial = anglesList.value(1); int leftInitial = anglesList.value(2); int upInitial = anglesList.value(3); if ((bearing < rightInitial) || (bearing >= upInitial)) { currentDirection = StickUp; eventbutton2 = buttons.value(StickUp); } else if ((bearing >= rightInitial) && (bearing < downInitial)) { currentDirection = StickRight; eventbutton1 = buttons.value(StickRight); } else if ((bearing >= downInitial) && (bearing < leftInitial)) { currentDirection = StickDown; eventbutton2 = buttons.value(StickDown); } else if ((bearing >= leftInitial) && (bearing < upInitial)) { currentDirection = StickLeft; eventbutton1 = buttons.value(StickLeft); } } /** * @brief Determine which stick direction button should be active when using 4 way * diagonal mode. * @param [out] pointer to a diagonal stick direction button that should be active. */ void JoyControlStick::determineFourWayDiagonalEvent(JoyControlStickButton *&eventbutton3) { qInstallMessageHandler(MessageHandler::myMessageOutput); double bearing = calculateBearing(); QList anglesList = getFourWayDiagonalZoneAngles(); int upRightInitial = anglesList.value(0); int downRightInitial = anglesList.value(1); int downLeftInitial = anglesList.value(2); int upLeftInitial = anglesList.value(3); if ((bearing >= upRightInitial) && (bearing < downRightInitial)) { currentDirection = StickRightUp; eventbutton3 = buttons.value(StickRightUp); } else if ((bearing >= downRightInitial) && (bearing < downLeftInitial)) { currentDirection = StickRightDown; eventbutton3 = buttons.value(StickRightDown); } else if ((bearing >= downLeftInitial) && (bearing < upLeftInitial)) { currentDirection = StickLeftDown; eventbutton3 = buttons.value(StickLeftDown); } else if (bearing >= upLeftInitial) { currentDirection = StickLeftUp; eventbutton3 = buttons.value(StickLeftUp); } } /** * @brief Find the current stick direction based on a Standard mode stick. * @return Current direction the stick is positioned. */ JoyControlStick::JoyStickDirections JoyControlStick::determineStandardModeDirection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return determineStandardModeDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } JoyControlStick::JoyStickDirections JoyControlStick::determineStandardModeDirection(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyStickDirections result = StickCentered; double bearing = calculateBearing(axisXValue, axisYValue); QList anglesList = getDiagonalZoneAngles(); int initialLeft = anglesList.value(0); int initialRight = anglesList.value(1); int upRightInitial = anglesList.value(2); int rightInitial = anglesList.value(3); int downRightInitial = anglesList.value(4); int downInitial = anglesList.value(5); int downLeftInitial = anglesList.value(6); int leftInitial = anglesList.value(7); int upLeftInitial = anglesList.value(8); if ((bearing <= initialRight) || (bearing >= initialLeft)) { result = StickUp; } else if ((bearing >= upRightInitial) && (bearing < rightInitial)) { result = StickRightUp; } else if ((bearing >= rightInitial) && (bearing < downRightInitial)) { result = StickRight; } else if ((bearing >= downRightInitial) && (bearing < downInitial)) { result = StickRightDown; } else if ((bearing >= downInitial) && (bearing < downLeftInitial)) { result = StickDown; } else if ((bearing >= downLeftInitial) && (bearing < leftInitial)) { result = StickLeftDown; } else if ((bearing >= leftInitial) && (bearing < upLeftInitial)) { result = StickLeft; } else if ((bearing >= upLeftInitial) && (bearing < initialLeft)) { result = StickLeftUp; } return result; } /** * @brief Find the current stick direction based on a Eight Way mode stick. * @return Current direction the stick is positioned. */ JoyControlStick::JoyStickDirections JoyControlStick::determineEightWayModeDirection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return determineStandardModeDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } JoyControlStick::JoyStickDirections JoyControlStick::determineEightWayModeDirection(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); return determineStandardModeDirection(axisXValue, axisYValue); } /** * @brief Find the current stick direction based on a Four Way Cardinal mode * stick. * @return Current direction the stick is positioned. */ JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayCardinalDirection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return determineFourWayCardinalDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayCardinalDirection(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyStickDirections result = StickCentered; double bearing = calculateBearing(axisXValue, axisYValue); QList anglesList = getFourWayCardinalZoneAngles(); int rightInitial = anglesList.value(0); int downInitial = anglesList.value(1); int leftInitial = anglesList.value(2); int upInitial = anglesList.value(3); if ((bearing < rightInitial) || (bearing >= upInitial)) { result = StickUp; } else if ((bearing >= rightInitial) && (bearing < downInitial)) { result = StickRight; } else if ((bearing >= downInitial) && (bearing < leftInitial)) { result = StickDown; } else if ((bearing >= leftInitial) && (bearing < upInitial)) { result = StickLeft; } return result; } /** * @brief Find the current stick direction based on a Four Way Diagonal mode * stick. * @return Current direction the stick is positioned. */ JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayDiagonalDirection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return determineFourWayDiagonalDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayDiagonalDirection(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyStickDirections result = StickCentered; double bearing = calculateBearing(axisXValue, axisYValue); QList anglesList = getFourWayDiagonalZoneAngles(); int upRightInitial = anglesList.value(0); int downRightInitial = anglesList.value(1); int downLeftInitial = anglesList.value(2); int upLeftInitial = anglesList.value(3); if ((bearing >= upRightInitial) && (bearing < downRightInitial)) { result = StickRightUp; } else if ((bearing >= downRightInitial) && (bearing < downLeftInitial)) { result = StickRightDown; } else if ((bearing >= downLeftInitial) && (bearing < upLeftInitial)) { result = StickLeftDown; } else if (bearing >= upLeftInitial) { result = StickLeftUp; } return result; } /** * @brief Calculate the current direction of the stick based on the values * of the X and Y axes and the current mode of the stick. * @return Current direction the stick is positioned. */ JoyControlStick::JoyStickDirections JoyControlStick::calculateStickDirection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return calculateStickDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } JoyControlStick::JoyStickDirections JoyControlStick::calculateStickDirection(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyStickDirections result = StickCentered; switch (currentMode) { case StandardMode: { result = determineStandardModeDirection(axisXValue, axisYValue); break; } case EightWayMode: { result = determineEightWayModeDirection(axisXValue, axisYValue); break; } case FourWayCardinal: { result = determineFourWayCardinalDirection(axisXValue, axisYValue); break; } case FourWayDiagonal: { result = determineFourWayDiagonalDirection(axisXValue, axisYValue); break; } } return result; } void JoyControlStick::establishPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(this, &JoyControlStick::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); } void JoyControlStick::disconnectPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(this, &JoyControlStick::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); } /** * @brief Check all stick buttons and see if any have slots assigned. * @return Status of whether any stick button has a slot assigned. */ bool JoyControlStick::hasSlotsAssigned() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool hasSlots = false; QHashIterator iter(buttons); while (iter.hasNext()) { JoyButton *button = iter.next().value(); if (button != nullptr) { if (button->getAssignedSlots()->count() > 0) { hasSlots = true; iter.toBack(); } } } return hasSlots; } void JoyControlStick::setButtonsSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setSpringRelativeStatus(value); } } bool JoyControlStick::isRelativeSpring() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool relative = false; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); relative = button->isRelativeSpring(); } else { JoyControlStickButton *button = iter.next().value(); bool temp = button->isRelativeSpring(); if (temp != relative) { relative = false; iter.toBack(); } } } return relative; } /** * @brief Copy slots from all stick buttons and properties from a stick * onto another. * @param JoyControlStick object to be modified. */ void JoyControlStick::copyAssignments(JoyControlStick *destStick) { qInstallMessageHandler(MessageHandler::myMessageOutput); destStick->reset(); destStick->deadZone = deadZone; destStick->maxZone = maxZone; destStick->diagonalRange = diagonalRange; destStick->currentDirection = currentDirection; destStick->currentMode = currentMode; destStick->stickName = stickName; destStick->circle = circle; destStick->stickDelay = stickDelay; QHashIterator iter(destStick->buttons); while (iter.hasNext()) { JoyControlStickButton *destButton = iter.next().value(); if (destButton != nullptr) { JoyControlStickButton *sourceButton = buttons.value(destButton->getDirection()); if (sourceButton != nullptr) sourceButton->copyAssignments(destButton); } } JoyControlStickModifierButton *destModifierButton = destStick->getModifierButton(); if ((modifierButton != nullptr) && (destModifierButton != nullptr)) { modifierButton->copyAssignments(destModifierButton); } if (!destStick->isDefault()) emit propertyUpdated(); } /** * @brief Set the percentage of the outer square that should be ignored * when performing the final axis calculations. * @param Percentage represented by the range of 0.0 - 1.0. */ void JoyControlStick::setCircleAdjust(double circle) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((circle >= 0.0) && (circle <= 1.0)) { this->circle = circle; emit circleAdjustChange(circle); emit propertyUpdated(); } } /** * @brief Get the current percentage of the outer square that should be ignored * when performing the final axis calculations. * @return Percentage represented by the range of 0.0 - 1.0. */ double JoyControlStick::getCircleAdjust() { qInstallMessageHandler(MessageHandler::myMessageOutput); return circle; } /** * @brief Slot called when directionDelayTimer has timed out. The method will * call createDeskEvent. */ void JoyControlStick::stickDirectionChangeEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); createDeskEvent(); } void JoyControlStick::setStickDelay(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (((value >= 10) && (value <= 1000)) || (value == 0)) { this->stickDelay = value; emit stickDelayChanged(value); emit propertyUpdated(); } } int JoyControlStick::getStickDelay() { qInstallMessageHandler(MessageHandler::myMessageOutput); return stickDelay; } void JoyControlStick::setButtonsEasingDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setEasingDuration(value); } } double JoyControlStick::getButtonsEasingDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTEASINGDURATION; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); result = button->getEasingDuration(); } else { JoyControlStickButton *button = iter.next().value(); double temp = button->getEasingDuration(); if (!qFuzzyCompare(temp, result)) { result = GlobalVariables::JoyButton::DEFAULTEASINGDURATION; iter.toBack(); } } } return result; } JoyControlStickModifierButton *JoyControlStick::getModifierButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); return modifierButton; } void JoyControlStick::queueJoyEvent(bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(ignoresets) pendingStickEvent = true; } bool JoyControlStick::hasPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); return pendingStickEvent; } void JoyControlStick::activatePendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (pendingStickEvent) { bool ignoresets = false; joyEvent(ignoresets); pendingStickEvent = false; } } void JoyControlStick::clearPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingStickEvent = false; } void JoyControlStick::setButtonsExtraAccelerationStatus(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) button->setExtraAccelerationStatus(enabled); } } bool JoyControlStick::getButtonsExtraAccelerationStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { bool temp = button->isExtraAccelerationEnabled(); if (!temp) { result = false; iter.toBack(); } else { result = temp; } } } return result; } void JoyControlStick::setButtonsExtraAccelerationMultiplier(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) button->setExtraAccelerationMultiplier(value); } } double JoyControlStick::getButtonsExtraAccelerationMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) result = button->getExtraAccelerationMultiplier(); } else { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { double temp = button->getExtraAccelerationMultiplier(); if (!qFuzzyCompare(temp, result)) { result = GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE; iter.toBack(); } } } } return result; } void JoyControlStick::setButtonsStartAccelerationMultiplier(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) button->setStartAccelMultiplier(value); } } double JoyControlStick::getButtonsStartAccelerationMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) result = button->getStartAccelMultiplier(); } else { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { double temp = button->getStartAccelMultiplier(); if (!qFuzzyCompare(temp, result)) { result = GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER; iter.toBack(); } } } } return result; } void JoyControlStick::setButtonsMinAccelerationThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) button->setMinAccelThreshold(value); } } double JoyControlStick::getButtonsMinAccelerationThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) result = button->getMinAccelThreshold(); } else { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { double temp = button->getMinAccelThreshold(); if (!qFuzzyCompare(temp, result)) { result = GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD; iter.toBack(); } } } } return result; } void JoyControlStick::setButtonsMaxAccelerationThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) button->setMaxAccelThreshold(value); } } double JoyControlStick::getButtonsMaxAccelerationThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) result = button->getMaxAccelThreshold(); } else { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { double temp = button->getMaxAccelThreshold(); if (!qFuzzyCompare(temp, result)) { result = GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD; iter.toBack(); } } } } return result; } void JoyControlStick::setButtonsAccelerationExtraDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) button->setAccelExtraDuration(value); } } double JoyControlStick::getButtonsAccelerationEasingDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) result = button->getAccelExtraDuration(); } else { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { double temp = button->getAccelExtraDuration(); if (!qFuzzyCompare(temp, result)) { result = GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION; iter.toBack(); } } } } return result; } void JoyControlStick::setButtonsSpringDeadCircleMultiplier(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { button->setSpringDeadCircleMultiplier(value); } } } int JoyControlStick::getButtonsSpringDeadCircleMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { result = button->getSpringDeadCircleMultiplier(); } } else { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { int temp = button->getSpringDeadCircleMultiplier(); if (temp != result) { result = GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS; iter.toBack(); } } } } return result; } double JoyControlStick::calculateAccelerationDistance(JoyControlStickButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalDistance = 0.0; switch (currentDirection) { case StickUp: { if (axisY->getCurrentRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue()); } break; } case StickRightUp: { switch (button->getJoyNumber()) { case 1: if (axisY->getCurrentRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue()); } break; case 2: if ((axisX->getCurrentRawValue() <= 0) || (axisY->getCurrentRawValue() >= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } break; case 3: if (axisX->getCurrentRawValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue()); } break; } break; } case StickRight: { if (axisX->getCurrentRawValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue()); } break; } case StickRightDown: { switch (button->getJoyNumber()) { case 3: if (axisX->getCurrentRawValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue()); } break; case 4: if ((axisX->getCurrentRawValue() <= 0) || (axisY->getCurrentRawValue() <= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } break; case 5: if (axisY->getCurrentRawValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue()); } break; } break; } case StickDown: { if (axisY->getCurrentRawValue() <= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue()); } break; } case StickLeftDown: { switch (button->getJoyNumber()) { case 5: if (axisY->getCurrentRawValue() < 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue()); } break; case 6: if ((axisX->getCurrentRawValue() >= 0) || (axisY->getCurrentRawValue() <= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } break; case 7: if (axisX->getCurrentRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue()); } break; } break; } case StickLeft: { if (axisX->getCurrentRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue()); } break; } case StickLeftUp: { switch (button->getJoyNumber()) { case 1: if (axisY->getCurrentRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue()); } break; case 7: if (axisX->getCurrentRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue()); } break; case 8: if ((axisX->getCurrentRawValue() >= 0) || (axisY->getCurrentRawValue() >= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } break; } break; } default: break; } return finalDistance; } // TODO: Maybe change method name. double JoyControlStick::calculateLastAccelerationButtonDistance(JoyControlStickButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); double finalDistance = 0.0; switch (currentDirection) { case StickUp: { if (axisY->getLastKnownRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); } break; } case StickRightUp: { switch (button->getJoyNumber()) { case StickRight: { if (axisX->getLastKnownRawValue() <= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); } break; } case StickUp: { if (axisY->getLastKnownRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); } break; } case StickRightUp: { if ((axisX->getLastKnownRawValue() <= 0) || (axisY->getLastKnownRawValue() >= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); } break; } } break; } case StickRight: { if (axisX->getLastKnownRawValue() <= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); } break; } case StickRightDown: { switch (button->getJoyNumber()) { case StickRight: { if (axisX->getLastKnownRawValue() <= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); } break; } case StickDown: { if (axisY->getLastKnownRawValue() <= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); } break; } case StickRightDown: { if ((axisX->getLastKnownRawValue() <= 0) || (axisY->getLastKnownRawValue() <= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); } break; } } break; } case StickDown: { if (axisY->getLastKnownRawValue() <= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); } break; } case StickLeftDown: { switch (button->getJoyNumber()) { case 7: { if (axisX->getLastKnownRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); } break; } case 5: { if (axisY->getLastKnownRawValue() <= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); } break; } case 6: { if ((axisX->getLastKnownRawValue() >= 0) || (axisY->getLastKnownRawValue() <= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); } break; } } break; } case StickLeft: { if (axisX->getLastKnownRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); } break; } case StickLeftUp: { switch (button->getJoyNumber()) { case 7: { if (axisX->getLastKnownRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue()); } break; } case 1: { if (axisY->getLastKnownRawValue() >= 0) { finalDistance = 0.0; } else { finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue()); } break; } case 8: { if ((axisX->getLastKnownRawValue() >= 0) || (axisY->getLastKnownRawValue() >= 0)) { finalDistance = 0.0; } else { finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue()); } break; } } break; } default: break; } return finalDistance; } double JoyControlStick::calculateXAxisDistance(int axisXValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); int axis1Value = axisXValue; double distance = axis1Value / static_cast(maxZone); if (distance < -1.0) distance = -1.0; else if (distance > 1.0) distance = 1.0; qDebug() << "DISTANCE: " << distance; return distance; } double JoyControlStick::calculateYAxisDistance(int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); int axis2Value = axisYValue; double distance = axis2Value / static_cast(maxZone); if (distance < -1.0) distance = -1.0; else if (distance > 1.0) distance = 1.0; return distance; } double JoyControlStick::calculateEightWayDiagonalDistanceFromDeadZone() { qInstallMessageHandler(MessageHandler::myMessageOutput); return calculateEightWayDiagonalDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue()); } double JoyControlStick::calculateEightWayDiagonalDistanceFromDeadZone(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); double distance = 0.0; double radius = getDistanceFromDeadZone(axisXValue, axisYValue); double bearing = calculateBearing(axisXValue, axisYValue); int relativeBearing = static_cast(bearing) % 90; int diagonalAngle = relativeBearing; if (relativeBearing > 45) diagonalAngle = 90 - relativeBearing; distance = radius * (diagonalAngle / 45.0); return distance; } double JoyControlStick::calculateEightWayDiagonalDistance(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); double distance = 0.0; double radius = getRadialDistance(axisXValue, axisYValue); double bearing = calculateBearing(axisXValue, axisYValue); int relativeBearing = static_cast(bearing) % 90; int diagonalAngle = relativeBearing; if (relativeBearing > 45) diagonalAngle = 90 - relativeBearing; distance = radius * (diagonalAngle / 45.0); return distance; } double JoyControlStick::calculateXDiagonalDeadZone(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); double diagonalDeadZone = 0.0; JoyStickDirections direction = calculateStickDirection(axisXValue, axisYValue); if (diagonalRange < 90) { if ((direction == StickRightUp) || (direction == StickRight)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(3); double mindeadX = fabs(deadZone * cos(maxangle * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadX; } else if ((direction == StickRightDown) || (direction == StickDown)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(5); double mindeadX = fabs(deadZone * cos((maxangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadX; } else if ((direction == StickLeftDown) || (direction == StickLeft)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(7); double mindeadX = fabs(deadZone * cos((maxangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadX; } else if ((direction == StickLeftUp) || (direction == StickUp)) { QList tempangles = getDiagonalZoneAngles(); double maxangle = tempangles.at(1); double mindeadX = fabs(deadZone * cos((maxangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadX; } else { diagonalDeadZone = 0.0; } } else { diagonalDeadZone = 0.0; } return diagonalDeadZone; } double JoyControlStick::calculateYDiagonalDeadZone(int axisXValue, int axisYValue) { qInstallMessageHandler(MessageHandler::myMessageOutput); double diagonalDeadZone = 0.0; JoyStickDirections direction = calculateStickDirection(axisXValue, axisYValue); if (diagonalRange < 90) { if ((direction == StickRightUp) || (direction == StickUp)) { QList tempangles = getDiagonalZoneAngles(); double minangle = tempangles.at(1); double mindeadY = fabs(deadZone * sin(minangle * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadY; } else if ((direction == StickRightDown) || (direction == StickRight)) { QList tempfuck = getDiagonalZoneAngles(); double minangle = tempfuck.at(4); double mindeadY = fabs(deadZone * sin((minangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadY; } else if ((direction == StickLeftDown) || (direction == StickDown)) { QList tempangles = getDiagonalZoneAngles(); double minangle = tempangles.at(6); double mindeadY = fabs(deadZone * sin((minangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadY; } else if ((direction == StickLeftUp) || (direction == StickLeft)) { QList tempangles = getDiagonalZoneAngles(); double minangle = tempangles.at(8); double mindeadY = fabs(deadZone * sin((minangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0)); diagonalDeadZone = mindeadY; } else { diagonalDeadZone = 0.0; } } else { diagonalDeadZone = 0.0; } return diagonalDeadZone; } double JoyControlStick::getSpringDeadCircleX() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = 0.0; double angle2 = 0.0; int axis1Value = 0; int axis2Value = 0; if ((axisX->getCurrentRawValue() == 0) && (axisY->getCurrentRawValue() == 0)) { // Stick moved back to absolute center. Use previously available values // to find stick angle. angle2 = atan2(axisX->getLastKnownRawValue(), -axisY->getLastKnownRawValue()); axis1Value = axisX->getLastKnownRawValue(); axis2Value = axisY->getLastKnownRawValue(); } else { // Use current axis values to find stick angle. angle2 = atan2(axisX->getCurrentRawValue(), -axisY->getCurrentRawValue()); axis1Value = axisX->getCurrentRawValue(); axis2Value = axisY->getCurrentRawValue(); } double ang_sin = sin(angle2); double ang_cos = cos(angle2); int deadX = abs(floor(deadZone * ang_sin + 0.5)); double diagonalDeadX = calculateXDiagonalDeadZone(axis1Value, axis2Value); double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2); double circle = this->circle; double circleStickFull = (squareStickFullPhi - 1) * circle + 1; double adjustedDeadXZone = circleStickFull > 1.0 ? (deadX / circleStickFull) : deadX; double finalDeadZoneX = adjustedDeadXZone - diagonalDeadX; double maxRange = static_cast(deadZone) - diagonalDeadX; if (maxRange != 0.0) result = finalDeadZoneX / maxRange; return result; } double JoyControlStick::getSpringDeadCircleY() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = 0.0; double angle2 = 0.0; int axis1Value = 0; int axis2Value = 0; if ((axisX->getCurrentRawValue() == 0) && (axisY->getCurrentRawValue() == 0)) { // Stick moved back to absolute center. Use previously available values // to find stick angle. angle2 = atan2(axisX->getLastKnownRawValue(), -axisY->getLastKnownRawValue()); axis1Value = axisX->getLastKnownRawValue(); axis2Value = axisY->getLastKnownRawValue(); } else { // Use current axis values to find stick angle. angle2 = atan2(axisX->getCurrentRawValue(), -axisY->getCurrentRawValue()); axis1Value = axisX->getCurrentRawValue(); axis2Value = axisY->getCurrentRawValue(); } double ang_sin = sin(angle2); double ang_cos = cos(angle2); int deadY = abs(floor(deadZone * ang_cos + 0.5)); double diagonalDeadY = calculateYDiagonalDeadZone(axis1Value, axis2Value); double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2); double circle = this->circle; double circleStickFull = (squareStickFullPhi - 1) * circle + 1; double adjustedDeadYZone = (circleStickFull > 1.0) ? (deadY / circleStickFull) : deadY; double finalDeadZoneY = adjustedDeadYZone - diagonalDeadY; double maxRange = static_cast(deadZone) - diagonalDeadY; if (maxRange != 0.0) result = finalDeadZoneY / maxRange; return result; } void JoyControlStick::setButtonsExtraAccelCurve(JoyButton::JoyExtraAccelerationCurve curve) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { button->setExtraAccelerationCurve(curve); } } } JoyButton::JoyExtraAccelerationCurve JoyControlStick::getButtonsExtraAccelerationCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve result = JoyButton::LinearAccelCurve; QHashIterator iter(getApplicableButtons()); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { result = button->getExtraAccelerationCurve(); } } else { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { JoyButton::JoyExtraAccelerationCurve temp = button->getExtraAccelerationCurve(); if (temp != result) { result = JoyButton::LinearAccelCurve; iter.toBack(); } } } } return result; } void JoyControlStick::setDirButtonsUpdateInitAccel(JoyControlStick::JoyStickDirections direction, bool state) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash apphash = getButtonsForDirection(direction); // QVERIFY(apphash.isEmpty() == false); QHashIterator iter(apphash); // QVERIFY(iter.hasNext() == true); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setUpdateInitAccel(state); } } QHash JoyControlStick::getButtonsForDirection(JoyControlStick::JoyStickDirections direction) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash; switch (currentMode) { case StandardMode: { if (direction & JoyControlStick::StickUp) { JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickUp); temphash.insert(JoyControlStick::StickUp, button); } if (direction & JoyControlStick::StickRight) { JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickRight); temphash.insert(JoyControlStick::StickRight, button); } if (direction & JoyControlStick::StickDown) { JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickDown); temphash.insert(JoyControlStick::StickDown, button); } if (direction & JoyControlStick::StickLeft) { JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickLeft); temphash.insert(JoyControlStick::StickLeft, button); } break; } case EightWayMode: { if ((direction == JoyControlStick::StickUp) || (direction == JoyControlStick::StickDown) || (direction == JoyControlStick::StickLeft) || (direction == JoyControlStick::StickRight) || (direction == JoyControlStick::StickRightUp) || (direction == JoyControlStick::StickRightDown) || (direction == JoyControlStick::StickLeftDown) || (direction == JoyControlStick::StickLeftUp)) { temphash.insert(direction, buttons.value(direction)); } break; } case FourWayCardinal: { if ((direction == JoyControlStick::StickUp) || (direction == JoyControlStick::StickDown) || (direction == JoyControlStick::StickLeft) || (direction == JoyControlStick::StickRight)) { temphash.insert(direction, buttons.value(direction)); } break; } case FourWayDiagonal: { if ((direction == JoyControlStick::StickRightUp) || (direction == JoyControlStick::StickRightDown) || (direction == JoyControlStick::StickLeftDown) || (direction == JoyControlStick::StickLeftUp)) { temphash.insert(direction, buttons.value(direction)); } break; } } return temphash; } AntiMicroX-antimicrox-2888bf6/src/joycontrolstick.h000066400000000000000000000336651377703515000225000ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICK_H #define JOYCONTROLSTICK_H #include "joybutton.h" #include "joycontrolstickdirectionstype.h" class JoyAxis; class JoyControlStickButton; class JoyControlStickModifierButton; class QXmlStreamReader; class QXmlStreamWriter; class JoyControlStick : public QObject, public JoyStickDirectionsType { Q_OBJECT public: explicit JoyControlStick(JoyAxis *axisX, JoyAxis *axisY, int index, int originset = 0, QObject *parent = nullptr); ~JoyControlStick(); enum JoyMode { StandardMode = 0, EightWayMode, FourWayCardinal, FourWayDiagonal }; void joyEvent(bool ignoresets = false); // JoyControlStickEvent class void setIndex(int index); void replaceXAxis(JoyAxis *axis); // JoyControlStickAxes class void replaceYAxis(JoyAxis *axis); // JoyControlStickAxes class void replaceAxes(JoyAxis *axisX, JoyAxis *axisY); // JoyControlStickAxes class void releaseButtonEvents(); // JoyControlStickEvent class void copyAssignments(JoyControlStick *destStick); void queueJoyEvent(bool ignoresets); // JoyControlStickEvent class void activatePendingEvent(); // JoyControlStickEvent class void clearPendingEvent(); // JoyControlStickEvent class void setCalibrationFlag(bool flag); void setCalibrationSummary(QString text); QString getCalibrationSummary(); bool inDeadZone(); bool hasSlotsAssigned(); bool isRelativeSpring(); bool hasPendingEvent(); // JoyControlStickEvent class bool wasCalibrated(); int getDeadZone(); int getDiagonalRange(); int getIndex(); int getRealJoyIndex(); int getMaxZone(); int getCurrentlyAssignedSet(); int getXCoordinate(); int getYCoordinate(); int getCircleXCoordinate(); int getCircleYCoordinate(); int getStickDelay(); double getDistanceFromDeadZone(); // JoyControlStickAxes class double getDistanceFromDeadZone(int axisXValue, int axisYValue); // JoyControlStickAxes class double getAbsoluteRawDistance(); // JoyControlStickAxes class double getAbsoluteRawDistance(int axisXValue, int axisYValue); // JoyControlStickAxes class double getNormalizedAbsoluteDistance(); // JoyControlStickAxes class double calculateBearing(); // JoyControlStickAxes class double calculateBearing(int axisXValue, int axisYValue); // JoyControlStickAxes class double calculateMouseDirectionalDistance(JoyControlStickButton *button); // JoyControlStickAxes class double calculateDirectionalDistance(); // JoyControlStickAxes class double calculateLastDirectionalDistance(); // JoyControlStickAxes class double calculateLastMouseDirectionalDistance(JoyControlStickButton *button); // JoyControlStickAxes class double calculateLastAccelerationButtonDistance(JoyControlStickButton *button); // JoyControlStickAxes class double calculateAccelerationDistance(JoyControlStickButton *button); // JoyControlStickAxis class double calculateXAxisDistance(int axisXValue); // JoyControlStickAxis class double calculateYAxisDistance(int axisYValue); // JoyControlStickAxis class double calculateLastAccelerationDirectionalDistance(); // JoyControlStickAxis class double getRadialDistance(int axisXValue, int axisYValue); // JoyControlStickAxis class double getCircleAdjust(); // JoyControlStickAxis class double getButtonsEasingDuration(); double getSpringDeadCircleX(); // JoyControlStickAxis class double getSpringDeadCircleY(); // JoyControlStickAxis class QString getStickName(); virtual QString getName(bool forceFullFormat = false, bool displayNames = false); virtual QString getPartialName(bool forceFullFormat = false, bool displayNames = false); JoyStickDirections getCurrentDirection(); // JoyControlStickAxes class QList getDiagonalZoneAngles(); // JoyControlStickAxes class QList getFourWayCardinalZoneAngles(); // JoyControlStickAxes class QList getFourWayDiagonalZoneAngles(); // JoyControlStickAxes class QHash *getButtons(); JoyControlStickButton *getDirectionButton(JoyStickDirections direction); // JoyControlStickAxes class JoyControlStickModifierButton *getModifierButton(); SetJoystick *getParentSet(); JoyAxis *getAxisX(); // JoyControlStickAxes class JoyAxis *getAxisY(); // JoyControlStickAxes class void setJoyMode(JoyMode mode); JoyMode getJoyMode(); void setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode); bool hasSameButtonsMouseMode(); JoyButton::JoyMouseMovementMode getButtonsPresetMouseMode(); void setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve); bool hasSameButtonsMouseCurve(); JoyButton::JoyMouseCurve getButtonsPresetMouseCurve(); void setButtonsSpringWidth(int value); int getButtonsPresetSpringWidth(); void setButtonsSpringHeight(int value); int getButtonsPresetSpringHeight(); void setButtonsSensitivity(double value); double getButtonsPresetSensitivity(); void setButtonsWheelSpeedX(int value); void setButtonsWheelSpeedY(int value); void setButtonsExtraAccelerationStatus(bool enabled); bool getButtonsExtraAccelerationStatus(); void setButtonsExtraAccelerationMultiplier(double value); double getButtonsExtraAccelerationMultiplier(); void setButtonsStartAccelerationMultiplier(double value); double getButtonsStartAccelerationMultiplier(); void setButtonsMinAccelerationThreshold(double value); double getButtonsMinAccelerationThreshold(); void setButtonsMaxAccelerationThreshold(double value); double getButtonsMaxAccelerationThreshold(); void setButtonsAccelerationExtraDuration(double value); double getButtonsAccelerationEasingDuration(); void setButtonsSpringDeadCircleMultiplier(int value); int getButtonsSpringDeadCircleMultiplier(); void setButtonsExtraAccelCurve(JoyButton::JoyExtraAccelerationCurve curve); JoyButton::JoyExtraAccelerationCurve getButtonsExtraAccelerationCurve(); QHash getButtonsForDirection(JoyControlStick::JoyStickDirections direction); // JoyControlStickAxes class void setDirButtonsUpdateInitAccel(JoyControlStick::JoyStickDirections direction, bool state); // JoyControlStickAxes class double calculateXDiagonalDeadZone(int axisXValue, int axisYValue); // JoyControlStickAxes class double calculateYDiagonalDeadZone(int axisXValue, int axisYValue); // JoyControlStickAxes class virtual bool isDefault(); virtual void setDefaultStickName(QString tempname); virtual QString getDefaultStickName(); virtual void readConfig(QXmlStreamReader *xml); // JoyControlStickXml class virtual void writeConfig(QXmlStreamWriter *xml); // JoyControlStickXml class static const JoyMode DEFAULTMODE; protected: virtual void populateButtons(); void createDeskEvent(bool ignoresets = false); // JoyControlStickEvent class void determineStandardModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2); // JoyControlStickEvent class void determineEightWayModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2, JoyControlStickButton *&eventbutton3); // JoyControlStickEvent class void determineFourWayCardinalEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2); // JoyControlStickEvent class void determineFourWayDiagonalEvent(JoyControlStickButton *&eventbutton3); // JoyControlStickEvent class JoyControlStick::JoyStickDirections determineStandardModeDirection(); // JoyControlStickAxes class JoyControlStick::JoyStickDirections determineStandardModeDirection(int axisXValue, int axisYValue); // JoyControlStickAxes class JoyControlStick::JoyStickDirections determineEightWayModeDirection(); // JoyControlStickAxes class JoyControlStick::JoyStickDirections determineEightWayModeDirection(int axisXValue, int axisYValue); // JoyControlStickAxes class JoyControlStick::JoyStickDirections determineFourWayCardinalDirection(); // JoyControlStickAxes class JoyControlStick::JoyStickDirections determineFourWayCardinalDirection(int axisXValue, int axisYValue); // JoyControlStickAxes class JoyControlStick::JoyStickDirections determineFourWayDiagonalDirection(); // JoyControlStickAxes class JoyControlStick::JoyStickDirections determineFourWayDiagonalDirection(int axisXValue, int axisYValue); // JoyControlStickAxes class JoyControlStick::JoyStickDirections calculateStickDirection(); // JoyControlStickAxes class JoyControlStick::JoyStickDirections calculateStickDirection(int axisXValue, int axisYValue); // JoyControlStickAxes class void performButtonPress(JoyControlStickButton *eventbutton, JoyControlStickButton *&activebutton, bool ignoresets); void performButtonRelease(JoyControlStickButton *&eventbutton, bool ignoresets); void refreshButtons(); void deleteButtons(); void resetButtons(); double calculateXDistanceFromDeadZone(bool interpolate = false); // JoyControlStickAxes class double calculateXDistanceFromDeadZone(int axisXValue, int axisYValue, bool interpolate = false); // JoyControlStickAxes class double calculateYDistanceFromDeadZone(bool interpolate = false); // JoyControlStickAxes class double calculateYDistanceFromDeadZone(int axisXValue, int axisYValue, bool interpolate = false); // JoyControlStickAxes class int calculateCircleXValue(int axisXValue, int axisYValue); // JoyControlStickAxes class int calculateCircleYValue(int axisXValue, int axisYValue); // JoyControlStickAxes class double calculateEightWayDiagonalDistanceFromDeadZone(); // JoyControlStickAxes class double calculateEightWayDiagonalDistanceFromDeadZone(int axisXValue, int axisYValue); // JoyControlStickAxes class double calculateEightWayDiagonalDistance(int axisXValue, int axisYValue); // JoyControlStickAxes class QHash getApplicableButtons(); void clearPendingAxisEvents(); // JoyControlStickEvent class signals: void moved(int xaxis, int yaxis); // JoyControlStickAxes class void active(int xaxis, int yaxis); // JoyControlStickAxes class void released(int axis, int yaxis); // JoyControlStickAxes class void deadZoneChanged(int value); // JoyControlStickAxes class void diagonalRangeChanged(int value); // JoyControlStickAxes class void maxZoneChanged(int value); // JoyControlStickAxes class void circleAdjustChange(double circle); // JoyControlStickAxes class void stickDelayChanged(int value); void stickNameChanged(); void joyModeChanged(); void propertyUpdated(); public slots: void reset(); void setDeadZone(int value); // JoyControlStickAxes class void setMaxZone(int value); // JoyControlStickAxes class void setDiagonalRange(int value); // JoyControlStickAxes class void setStickName(QString tempName); void setButtonsSpringRelativeStatus(bool value); void setCircleAdjust(double circle); // JoyControlStickAxes class void setStickDelay(int value); void setButtonsEasingDuration(double value); void establishPropertyUpdatedConnection(); void disconnectPropertyUpdatedConnection(); private slots: void stickDirectionChangeEvent(); // JoyControlStickEvent class private: int originset; int deadZone; int diagonalRange; int maxZone; int index; int stickDelay; // unsigned int double circle; bool isActive; bool safezone; bool pendingStickEvent; bool calibrated; QString calibrationSummary; JoyAxis *axisX; JoyAxis *axisY; JoyControlStickButton *activeButton1; JoyControlStickButton *activeButton2; JoyControlStickButton *activeButton3; JoyStickDirections currentDirection; JoyMode currentMode; QString stickName; QString defaultStickName; QTimer directionDelayTimer; QHash buttons; JoyControlStickModifierButton *modifierButton; void populateStickBtns(); }; #endif // JOYCONTROLSTICK_H AntiMicroX-antimicrox-2888bf6/src/joycontrolstickbuttonpushbutton.cpp000066400000000000000000000121441377703515000264100ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickbuttonpushbutton.h" #include "joybuttoncontextmenu.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joybuttontypes/joycontrolstickmodifierbutton.h" #include "joycontrolstick.h" #include "messagehandler.h" #include #include #include JoyControlStickButtonPushButton::JoyControlStickButtonPushButton(JoyControlStickButton *button, bool displayNames, QWidget *parent) : FlashButtonWidget(displayNames, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->button = button; refreshLabel(); enableFlashes(); tryFlash(); this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &JoyControlStickButtonPushButton::customContextMenuRequested, this, &JoyControlStickButtonPushButton::showContextMenu); connect(button, &JoyControlStickButton::propertyUpdated, this, &JoyControlStickButtonPushButton::refreshLabel); connect(button, &JoyControlStickButton::activeZoneChanged, this, &JoyControlStickButtonPushButton::refreshLabel); connect(button->getStick()->getModifierButton(), &JoyControlStickModifierButton::activeZoneChanged, this, &JoyControlStickButtonPushButton::refreshLabel); } JoyControlStickButton *JoyControlStickButtonPushButton::getButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); return button; } void JoyControlStickButtonPushButton::setButton(JoyControlStickButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); disableFlashes(); if (this->button != nullptr) { disconnect(button, &JoyControlStickButton::propertyUpdated, this, &JoyControlStickButtonPushButton::refreshLabel); disconnect(this->button, &JoyControlStickButton::activeZoneChanged, this, &JoyControlStickButtonPushButton::refreshLabel); } this->button = button; refreshLabel(); enableFlashes(); connect(button, &JoyControlStickButton::propertyUpdated, this, &JoyControlStickButtonPushButton::refreshLabel); connect(button, &JoyControlStickButton::activeZoneChanged, this, &JoyControlStickButtonPushButton::refreshLabel, Qt::QueuedConnection); } void JoyControlStickButtonPushButton::disableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (button != nullptr) { disconnect(button, &JoyControlStickButton::clicked, this, &JoyControlStickButtonPushButton::flash); disconnect(button, &JoyControlStickButton::released, this, &JoyControlStickButtonPushButton::unflash); } this->unflash(); } void JoyControlStickButtonPushButton::enableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (button != nullptr) { connect(button, &JoyControlStickButton::clicked, this, &JoyControlStickButtonPushButton::flash, Qt::QueuedConnection); connect(button, &JoyControlStickButton::released, this, &JoyControlStickButtonPushButton::unflash, Qt::QueuedConnection); } } /** * @brief Generate the string that will be displayed on the button * @return Display string */ QString JoyControlStickButtonPushButton::generateLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (button != nullptr) { if (!button->getActionName().isEmpty() && ifDisplayNames()) { qDebug() << "Action name was not empty"; temp = button->getActionName().replace("&", "&&"); } else { qDebug() << "Action name was empty"; temp = button->getCalculatedActiveZoneSummary().replace("&", "&&"); } } qDebug() << "Here is name of action for pushed stick button: " << temp; return temp; } void JoyControlStickButtonPushButton::showContextMenu(const QPoint &point) { qInstallMessageHandler(MessageHandler::myMessageOutput); QPoint globalPos = this->mapToGlobal(point); JoyButtonContextMenu *contextMenu = new JoyButtonContextMenu(button, this); contextMenu->buildMenu(); contextMenu->popup(globalPos); } void JoyControlStickButtonPushButton::tryFlash() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (button->getButtonState()) { flash(); } } AntiMicroX-antimicrox-2888bf6/src/joycontrolstickbuttonpushbutton.h000066400000000000000000000032071377703515000260550ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKBUTTONPUSHBUTTON_H #define JOYCONTROLSTICKBUTTONPUSHBUTTON_H #include "flashbuttonwidget.h" class JoyControlStickButton; class QWidget; class JoyControlStickButtonPushButton : public FlashButtonWidget { Q_OBJECT Q_PROPERTY(bool isflashing READ isButtonFlashing) public: explicit JoyControlStickButtonPushButton(JoyControlStickButton *button, bool displayNames, QWidget *parent = nullptr); JoyControlStickButton *getButton(); void setButton(JoyControlStickButton *button); void tryFlash(); protected: virtual QString generateLabel() override; public slots: void disableFlashes() override; void enableFlashes() override; private slots: void showContextMenu(const QPoint &point); private: JoyControlStickButton *button; }; #endif // JOYCONTROLSTICKBUTTONPUSHBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joycontrolstickcontextmenu.cpp000066400000000000000000000565141377703515000253230ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickcontextmenu.h" #include "antkeymapper.h" #include "common.h" #include "inputdevice.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joycontrolstick.h" #include "messagehandler.h" #include "mousedialog/mousecontrolsticksettingsdialog.h" #include #include #include JoyControlStickContextMenu::JoyControlStickContextMenu(JoyControlStick *stick, QWidget *parent) : QMenu(parent) , helper(stick) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->stick = stick; getHelperLocal().moveToThread(stick->thread()); connect(this, &JoyControlStickContextMenu::aboutToHide, this, &JoyControlStickContextMenu::deleteLater); } void JoyControlStickContextMenu::buildMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); QActionGroup *presetGroup = new QActionGroup(this); int presetMode = 0; int currentPreset = getPresetIndex(); QAction *action = this->addAction(tr("Mouse (Normal)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Mouse (Inverted Horizontal)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Mouse (Inverted Vertical)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Mouse (Inverted Horizontal + Vertical)")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Arrows")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("Keys: W | A | S | D")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("NumPad")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); presetMode++; action = this->addAction(tr("None")); action->setCheckable(true); action->setChecked(currentPreset == presetMode + 1); action->setData(QVariant(presetMode)); connect(action, &QAction::triggered, this, [this, action] { setStickPreset(action); }); presetGroup->addAction(action); this->addSeparator(); QActionGroup *modesGroup = new QActionGroup(this); int mode = static_cast(JoyControlStick::StandardMode); action = this->addAction(tr("Standard")); action->setCheckable(true); action->setChecked(stick->getJoyMode() == JoyControlStick::StandardMode); action->setData(QVariant(mode)); connect(action, &QAction::triggered, this, [this, action] { setStickMode(action); }); modesGroup->addAction(action); action = this->addAction(tr("Eight Way")); action->setCheckable(true); action->setChecked(stick->getJoyMode() == JoyControlStick::EightWayMode); mode = static_cast(JoyControlStick::EightWayMode); action->setData(QVariant(mode)); connect(action, &QAction::triggered, this, [this, action] { setStickMode(action); }); modesGroup->addAction(action); action = this->addAction(tr("4 Way Cardinal")); action->setCheckable(true); action->setChecked(stick->getJoyMode() == JoyControlStick::FourWayCardinal); mode = static_cast(JoyControlStick::FourWayCardinal); action->setData(QVariant(mode)); connect(action, &QAction::triggered, this, [this, action] { setStickMode(action); }); modesGroup->addAction(action); action = this->addAction(tr("4 Way Diagonal")); action->setCheckable(true); action->setChecked(stick->getJoyMode() == JoyControlStick::FourWayDiagonal); mode = static_cast(JoyControlStick::FourWayDiagonal); action->setData(QVariant(mode)); connect(action, &QAction::triggered, this, [this, action] { setStickMode(action); }); modesGroup->addAction(action); this->addSeparator(); action = this->addAction(tr("Mouse Settings")); action->setCheckable(false); connect(action, &QAction::triggered, this, &JoyControlStickContextMenu::openMouseSettingsDialog); } void JoyControlStickContextMenu::setStickMode(QAction *action) { qInstallMessageHandler(MessageHandler::myMessageOutput); int item = action->data().toInt(); stick->setJoyMode(static_cast(item)); } void JoyControlStickContextMenu::setStickPreset(QAction *action) { qInstallMessageHandler(MessageHandler::myMessageOutput); int item = action->data().toInt(); JoyButtonSlot *upButtonSlot = nullptr; JoyButtonSlot *downButtonSlot = nullptr; JoyButtonSlot *leftButtonSlot = nullptr; JoyButtonSlot *rightButtonSlot = nullptr; JoyButtonSlot *upLeftButtonSlot = nullptr; JoyButtonSlot *upRightButtonSlot = nullptr; JoyButtonSlot *downLeftButtonSlot = nullptr; JoyButtonSlot *downRightButtonSlot = nullptr; switch (item) { case 0: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); stick->setJoyMode(JoyControlStick::StandardMode); stick->setDiagonalRange(65); PadderCommon::inputDaemonMutex.unlock(); break; } case 1: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); stick->setJoyMode(JoyControlStick::StandardMode); stick->setDiagonalRange(65); PadderCommon::inputDaemonMutex.unlock(); break; } case 2: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); stick->setJoyMode(JoyControlStick::StandardMode); stick->setDiagonalRange(65); PadderCommon::inputDaemonMutex.unlock(); break; } case 3: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); stick->setJoyMode(JoyControlStick::StandardMode); stick->setDiagonalRange(65); PadderCommon::inputDaemonMutex.unlock(); break; } case 4: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up), Qt::Key_Up, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down), Qt::Key_Down, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left), Qt::Key_Left, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right), Qt::Key_Right, JoyButtonSlot::JoyKeyboard, this); stick->setJoyMode(JoyControlStick::StandardMode); stick->setDiagonalRange(45); PadderCommon::inputDaemonMutex.unlock(); break; } case 5: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W), Qt::Key_W, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S), Qt::Key_S, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A), Qt::Key_A, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D), Qt::Key_D, JoyButtonSlot::JoyKeyboard, this); stick->setJoyMode(JoyControlStick::StandardMode); stick->setDiagonalRange(45); PadderCommon::inputDaemonMutex.unlock(); break; } case 6: { PadderCommon::inputDaemonMutex.lock(); if ((stick->getJoyMode() == JoyControlStick::StandardMode) || (stick->getJoyMode() == JoyControlStick::FourWayCardinal)) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); } else if (stick->getJoyMode() == JoyControlStick::EightWayMode) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } else if (stick->getJoyMode() == JoyControlStick::FourWayDiagonal) { upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } stick->setDiagonalRange(45); PadderCommon::inputDaemonMutex.unlock(); break; } case 7: { QMetaObject::invokeMethod(&helper, "clearButtonsSlotsEventReset"); QMetaObject::invokeMethod(stick, "setDiagonalRange", Q_ARG(int, 45)); break; } } QHash tempHash; tempHash.insert(JoyControlStick::StickUp, upButtonSlot); tempHash.insert(JoyControlStick::StickDown, downButtonSlot); tempHash.insert(JoyControlStick::StickLeft, leftButtonSlot); tempHash.insert(JoyControlStick::StickRight, rightButtonSlot); tempHash.insert(JoyControlStick::StickLeftUp, upLeftButtonSlot); tempHash.insert(JoyControlStick::StickRightUp, upRightButtonSlot); tempHash.insert(JoyControlStick::StickLeftDown, downLeftButtonSlot); tempHash.insert(JoyControlStick::StickRightDown, downRightButtonSlot); getHelperLocal().setPendingSlots(&tempHash); QMetaObject::invokeMethod(&helper, "setFromPendingSlots", Qt::BlockingQueuedConnection); } int JoyControlStickContextMenu::getPresetIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = 0; PadderCommon::inputDaemonMutex.lock(); JoyControlStickButton *upButton = stick->getDirectionButton(JoyControlStick::StickUp); QList *upslots = upButton->getAssignedSlots(); JoyControlStickButton *downButton = stick->getDirectionButton(JoyControlStick::StickDown); QList *downslots = downButton->getAssignedSlots(); JoyControlStickButton *leftButton = stick->getDirectionButton(JoyControlStick::StickLeft); QList *leftslots = leftButton->getAssignedSlots(); JoyControlStickButton *rightButton = stick->getDirectionButton(JoyControlStick::StickRight); QList *rightslots = rightButton->getAssignedSlots(); if ((upslots->length() == 1) && (downslots->length() == 1) && (leftslots->length() == 1) && (rightslots->length() == 1)) { JoyButtonSlot *upslot = upslots->at(0); JoyButtonSlot *downslot = downslots->at(0); JoyButtonSlot *leftslot = leftslots->at(0); JoyButtonSlot *rightslot = rightslots->at(0); if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { result = 1; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { result = 2; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { result = 3; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { result = 4; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right))) { result = 5; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D))) { result = 6; } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6))) { result = 7; } } else if ((upslots->length() == 0) && (downslots->length() == 0) && (leftslots->length() == 0) && (rightslots->length() == 0)) { result = 8; } PadderCommon::inputDaemonMutex.unlock(); return result; } void JoyControlStickContextMenu::openMouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); MouseControlStickSettingsDialog *dialog = new MouseControlStickSettingsDialog(stick, parentWidget()); dialog->show(); } JoyControlStickContextMenuHelper &JoyControlStickContextMenu::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/joycontrolstickcontextmenu.h000066400000000000000000000030261377703515000247560ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKCONTEXTMENU_H #define JOYCONTROLSTICKCONTEXTMENU_H #include "uihelpers/joycontrolstickcontextmenuhelper.h" #include class JoyControlStick; class QWidget; class JoyControlStickContextMenu : public QMenu { Q_OBJECT public: explicit JoyControlStickContextMenu(JoyControlStick *stick, QWidget *parent = nullptr); void buildMenu(); protected: int getPresetIndex(); private slots: void setStickPreset(QAction *action); void setStickMode(QAction *action); void openMouseSettingsDialog(); private: JoyControlStickContextMenuHelper &getHelperLocal(); JoyControlStick *stick; JoyControlStickContextMenuHelper helper; }; #endif // JOYCONTROLSTICKCONTEXTMENU_H AntiMicroX-antimicrox-2888bf6/src/joycontrolstickdirectionstype.h000066400000000000000000000023441377703515000254540ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKDIRECTIONSTYPE_H #define JOYCONTROLSTICKDIRECTIONSTYPE_H class JoyStickDirectionsType { public: enum JoyStickDirections { StickCentered = 0, StickUp = 1, StickRight = 3, StickDown = 5, StickLeft = 7, StickRightUp = 2, StickRightDown = 4, StickLeftUp = 8, StickLeftDown = 6 }; }; #endif // JOYCONTROLSTICKDIRECTIONSTYPE_H AntiMicroX-antimicrox-2888bf6/src/joycontrolstickeditdialog.cpp000066400000000000000000000745661377703515000250660ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickeditdialog.h" #include "ui_joycontrolstickeditdialog.h" #include "antkeymapper.h" #include "buttoneditdialog.h" #include "common.h" #include "event.h" #include "inputdevice.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joybuttontypes/joycontrolstickmodifierbutton.h" #include "joycontrolstick.h" #include "messagehandler.h" #include "mousedialog/mousecontrolsticksettingsdialog.h" #include "setjoystick.h" #include #include #include #include #include JoyControlStickEditDialog::JoyControlStickEditDialog(JoyControlStick *stick, bool keypadUnlocked, QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::JoyControlStickEditDialog) , helper(stick) { ui->setupUi(this); this->keypadUnlocked = keypadUnlocked; qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->stick = stick; getHelperLocal().moveToThread(stick->thread()); PadderCommon::inputDaemonMutex.lock(); updateWindowTitleStickName(); ui->deadZoneSlider->setValue(stick->getDeadZone()); ui->deadZoneSpinBox->setValue(stick->getDeadZone()); ui->maxZoneSlider->setValue(stick->getMaxZone()); ui->maxZoneSpinBox->setValue(stick->getMaxZone()); ui->diagonalRangeSlider->setValue(stick->getDiagonalRange()); ui->diagonalRangeSpinBox->setValue(stick->getDiagonalRange()); QString xCoorString = QString::number(stick->getXCoordinate()); if (stick->getCircleAdjust() > 0.0) { xCoorString.append(QString(" (%1)").arg(stick->getCircleXCoordinate())); } ui->xCoordinateLabel->setText(xCoorString); QString yCoorString = QString::number(stick->getYCoordinate()); if (stick->getCircleAdjust() > 0.0) { yCoorString.append(QString(" (%1)").arg(stick->getCircleYCoordinate())); } ui->yCoordinateLabel->setText(yCoorString); ui->distanceLabel->setText(QString::number(stick->getAbsoluteRawDistance())); ui->diagonalLabel->setText(QString::number(stick->calculateBearing())); switch (stick->getJoyMode()) { case JoyControlStick::StandardMode: { ui->joyModeComboBox->setCurrentIndex(0); break; } case JoyControlStick::EightWayMode: { ui->joyModeComboBox->setCurrentIndex(1); break; } case JoyControlStick::FourWayCardinal: { ui->joyModeComboBox->setCurrentIndex(2); ui->diagonalRangeSlider->setEnabled(false); ui->diagonalRangeSpinBox->setEnabled(false); break; } case JoyControlStick::FourWayDiagonal: { ui->joyModeComboBox->setCurrentIndex(3); ui->diagonalRangeSlider->setEnabled(false); ui->diagonalRangeSpinBox->setEnabled(false); break; } } ui->stickStatusBoxWidget->setStick(stick); selectCurrentPreset(); ui->stickNameLineEdit->setText(stick->getStickName()); double validDistance = stick->getDistanceFromDeadZone() * 100.0; ui->fromSafeZoneValueLabel->setText(QString::number(validDistance)); double circleValue = stick->getCircleAdjust(); ui->squareStickSlider->setValue(circleValue * 100); ui->squareStickSpinBox->setValue(circleValue * 100); int stickDelay = stick->getStickDelay(); ui->stickDelaySlider->setValue(stickDelay * .1); ui->stickDelayDoubleSpinBox->setValue(stickDelay * .001); ui->modifierPushButton->setText(stick->getModifierButton()->getSlotsSummary()); stick->getModifierButton()->establishPropertyUpdatedConnections(); update(); updateGeometry(); PadderCommon::inputDaemonMutex.unlock(); connect(ui->presetsComboBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyControlStickEditDialog::implementPresets); connect(ui->joyModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyControlStickEditDialog::implementModes); connect(ui->deadZoneSlider, &QSlider::valueChanged, ui->deadZoneSpinBox, &QSpinBox::setValue); connect(ui->maxZoneSlider, &QSlider::valueChanged, ui->maxZoneSpinBox, &QSpinBox::setValue); connect(ui->diagonalRangeSlider, &QSlider::valueChanged, ui->diagonalRangeSpinBox, &QSpinBox::setValue); connect(ui->squareStickSlider, &QSlider::valueChanged, ui->squareStickSpinBox, &QSpinBox::setValue); connect(ui->deadZoneSpinBox, static_cast(&QSpinBox::valueChanged), ui->deadZoneSlider, &QSlider::setValue); connect(ui->maxZoneSpinBox, static_cast(&QSpinBox::valueChanged), ui->maxZoneSlider, &QSlider::setValue); connect(ui->maxZoneSpinBox, static_cast(&QSpinBox::valueChanged), this, &JoyControlStickEditDialog::checkMaxZone); connect(ui->diagonalRangeSpinBox, static_cast(&QSpinBox::valueChanged), ui->diagonalRangeSlider, &QSlider::setValue); connect(ui->squareStickSpinBox, static_cast(&QSpinBox::valueChanged), ui->squareStickSlider, &QSlider::setValue); connect(ui->stickDelaySlider, &QSlider::valueChanged, &helper, &JoyControlStickEditDialogHelper::updateControlStickDelay); connect(ui->deadZoneSpinBox, static_cast(&QSpinBox::valueChanged), stick, &JoyControlStick::setDeadZone); connect(ui->diagonalRangeSpinBox, static_cast(&QSpinBox::valueChanged), stick, &JoyControlStick::setDiagonalRange); connect(ui->squareStickSpinBox, static_cast(&QSpinBox::valueChanged), this, &JoyControlStickEditDialog::changeCircleAdjust); connect(stick, &JoyControlStick::stickDelayChanged, this, &JoyControlStickEditDialog::updateStickDelaySpinBox); connect(ui->stickDelayDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &JoyControlStickEditDialog::updateStickDelaySlider); connect(stick, &JoyControlStick::moved, this, &JoyControlStickEditDialog::refreshStickStats); connect(ui->mouseSettingsPushButton, &QPushButton::clicked, this, &JoyControlStickEditDialog::openMouseSettingsDialog); connect(ui->stickNameLineEdit, &QLineEdit::textEdited, stick, &JoyControlStick::setStickName); connect(stick, &JoyControlStick::stickNameChanged, this, &JoyControlStickEditDialog::updateWindowTitleStickName); connect(ui->modifierPushButton, &QPushButton::clicked, this, &JoyControlStickEditDialog::openModifierEditDialog); connect(stick->getModifierButton(), &JoyControlStickModifierButton::slotsChanged, this, &JoyControlStickEditDialog::changeModifierSummary); } // for tests /*JoyControlStickEditDialog::JoyControlStickEditDialog(QWidget *parent) : QDialog(parent, Qt::Window), ui(new Ui::JoyControlStickEditDialog) { helper = new JoyControlStick(); }*/ JoyControlStickEditDialog::~JoyControlStickEditDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void JoyControlStickEditDialog::implementPresets(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *upButtonSlot = nullptr; JoyButtonSlot *downButtonSlot = nullptr; JoyButtonSlot *leftButtonSlot = nullptr; JoyButtonSlot *rightButtonSlot = nullptr; JoyButtonSlot *upLeftButtonSlot = nullptr; JoyButtonSlot *upRightButtonSlot = nullptr; JoyButtonSlot *downLeftButtonSlot = nullptr; JoyButtonSlot *downRightButtonSlot = nullptr; switch (index) { case 1: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); ui->diagonalRangeSlider->setValue(65); break; } case 2: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); ui->diagonalRangeSlider->setValue(65); break; } case 3: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); ui->diagonalRangeSlider->setValue(65); break; } case 4: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); downButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); leftButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); rightButtonSlot = new JoyButtonSlot(JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); ui->diagonalRangeSlider->setValue(65); break; } case 5: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up), Qt::Key_Up, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down), Qt::Key_Down, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left), Qt::Key_Left, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right), Qt::Key_Right, JoyButtonSlot::JoyKeyboard, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); ui->diagonalRangeSlider->setValue(45); break; } case 6: { PadderCommon::inputDaemonMutex.lock(); upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W), Qt::Key_W, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S), Qt::Key_S, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A), Qt::Key_A, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D), Qt::Key_D, JoyButtonSlot::JoyKeyboard, this); PadderCommon::inputDaemonMutex.unlock(); ui->joyModeComboBox->setCurrentIndex(0); ui->diagonalRangeSlider->setValue(45); break; } case 7: { PadderCommon::inputDaemonMutex.lock(); if ((ui->joyModeComboBox->currentIndex() == 0) || (ui->joyModeComboBox->currentIndex() == 2)) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); } else if (ui->joyModeComboBox->currentIndex() == 1) { upButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8), QtKeyMapperBase::AntKey_KP_8, JoyButtonSlot::JoyKeyboard, this); downButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2), QtKeyMapperBase::AntKey_KP_2, JoyButtonSlot::JoyKeyboard, this); leftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4), QtKeyMapperBase::AntKey_KP_4, JoyButtonSlot::JoyKeyboard, this); rightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6), QtKeyMapperBase::AntKey_KP_6, JoyButtonSlot::JoyKeyboard, this); upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } else if (ui->joyModeComboBox->currentIndex() == 3) { upLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_7), QtKeyMapperBase::AntKey_KP_7, JoyButtonSlot::JoyKeyboard, this); upRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_9), QtKeyMapperBase::AntKey_KP_9, JoyButtonSlot::JoyKeyboard, this); downLeftButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_1), QtKeyMapperBase::AntKey_KP_1, JoyButtonSlot::JoyKeyboard, this); downRightButtonSlot = new JoyButtonSlot(AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_3), QtKeyMapperBase::AntKey_KP_3, JoyButtonSlot::JoyKeyboard, this); } PadderCommon::inputDaemonMutex.unlock(); ui->diagonalRangeSlider->setValue(45); break; } case 0: case 8: { QMetaObject::invokeMethod(&helper, "clearButtonsSlotsEventReset", Qt::BlockingQueuedConnection); ui->diagonalRangeSlider->setValue(45); stick->getDirectionButton(JoyControlStick::StickUp)->buildActiveZoneSummaryString(); stick->getDirectionButton(JoyControlStick::StickDown)->buildActiveZoneSummaryString(); stick->getDirectionButton(JoyControlStick::StickLeft)->buildActiveZoneSummaryString(); stick->getDirectionButton(JoyControlStick::StickRight)->buildActiveZoneSummaryString(); break; } } QHash tempHash; tempHash.insert(JoyControlStick::StickUp, upButtonSlot); tempHash.insert(JoyControlStick::StickDown, downButtonSlot); tempHash.insert(JoyControlStick::StickLeft, leftButtonSlot); tempHash.insert(JoyControlStick::StickRight, rightButtonSlot); tempHash.insert(JoyControlStick::StickLeftUp, upLeftButtonSlot); tempHash.insert(JoyControlStick::StickRightUp, upRightButtonSlot); tempHash.insert(JoyControlStick::StickLeftDown, downLeftButtonSlot); tempHash.insert(JoyControlStick::StickRightDown, downRightButtonSlot); getHelperLocal().setPendingSlots(&tempHash); QMetaObject::invokeMethod(&helper, "setFromPendingSlots", Qt::BlockingQueuedConnection); } void JoyControlStickEditDialog::refreshStickStats(int x, int y) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(x); Q_UNUSED(y); PadderCommon::inputDaemonMutex.lock(); QString xCoorString = QString::number(stick->getXCoordinate()); if (stick->getCircleAdjust() > 0.0) { xCoorString.append(QString(" (%1)").arg(stick->getCircleXCoordinate())); } ui->xCoordinateLabel->setText(xCoorString); QString yCoorString = QString::number(stick->getYCoordinate()); if (stick->getCircleAdjust() > 0.0) { yCoorString.append(QString(" (%1)").arg(stick->getCircleYCoordinate())); } ui->yCoordinateLabel->setText(yCoorString); ui->distanceLabel->setText(QString::number(stick->getAbsoluteRawDistance())); ui->diagonalLabel->setText(QString::number(stick->calculateBearing())); double validDistance = stick->getDistanceFromDeadZone() * 100.0; ui->fromSafeZoneValueLabel->setText(QString::number(validDistance)); PadderCommon::inputDaemonMutex.unlock(); } void JoyControlStickEditDialog::checkMaxZone(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value > ui->deadZoneSpinBox->value()) { QMetaObject::invokeMethod(stick, "setMaxZone", Q_ARG(int, value)); } } void JoyControlStickEditDialog::implementModes(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); stick->releaseButtonEvents(); switch (index) { case 0: { stick->setJoyMode(JoyControlStick::StandardMode); ui->diagonalRangeSlider->setEnabled(true); ui->diagonalRangeSpinBox->setEnabled(true); break; } case 1: { stick->setJoyMode(JoyControlStick::EightWayMode); ui->diagonalRangeSlider->setEnabled(true); ui->diagonalRangeSpinBox->setEnabled(true); break; } case 2: { stick->setJoyMode(JoyControlStick::FourWayCardinal); ui->diagonalRangeSlider->setEnabled(false); ui->diagonalRangeSpinBox->setEnabled(false); break; } case 3: { stick->setJoyMode(JoyControlStick::FourWayDiagonal); ui->diagonalRangeSlider->setEnabled(false); ui->diagonalRangeSpinBox->setEnabled(false); break; } } PadderCommon::inputDaemonMutex.unlock(); } void JoyControlStickEditDialog::selectCurrentPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *upButton = stick->getDirectionButton(JoyControlStick::StickUp); QList *upslots = upButton->getAssignedSlots(); JoyControlStickButton *downButton = stick->getDirectionButton(JoyControlStick::StickDown); QList *downslots = downButton->getAssignedSlots(); JoyControlStickButton *leftButton = stick->getDirectionButton(JoyControlStick::StickLeft); QList *leftslots = leftButton->getAssignedSlots(); JoyControlStickButton *rightButton = stick->getDirectionButton(JoyControlStick::StickRight); QList *rightslots = rightButton->getAssignedSlots(); if ((upslots->length() == 1) && (downslots->length() == 1) && (leftslots->length() == 1) && (rightslots->length() == 1)) { JoyButtonSlot *upslot = upslots->at(0); JoyButtonSlot *downslot = downslots->at(0); JoyButtonSlot *leftslot = leftslots->at(0); JoyButtonSlot *rightslot = rightslots->at(0); if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { ui->presetsComboBox->setCurrentIndex(1); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseUp) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseDown) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { ui->presetsComboBox->setCurrentIndex(2); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseLeft) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseRight)) { ui->presetsComboBox->setCurrentIndex(3); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (upslot->getSlotCode() == JoyButtonSlot::MouseDown) && (downslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (downslot->getSlotCode() == JoyButtonSlot::MouseUp) && (leftslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (leftslot->getSlotCode() == JoyButtonSlot::MouseRight) && (rightslot->getSlotMode() == JoyButtonSlot::JoyMouseMovement) && (rightslot->getSlotCode() == JoyButtonSlot::MouseLeft)) { ui->presetsComboBox->setCurrentIndex(4); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Up)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Down)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Left)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Right))) { ui->presetsComboBox->setCurrentIndex(5); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_W)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_S)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_A)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_D))) { ui->presetsComboBox->setCurrentIndex(6); } else if ((upslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (upslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_8)) && (downslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (downslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_2)) && (leftslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (leftslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_4)) && (rightslot->getSlotMode() == JoyButtonSlot::JoyKeyboard) && (rightslot->getSlotCode() == AntKeyMapper::getInstance()->returnVirtualKey(QtKeyMapperBase::AntKey_KP_6))) { ui->presetsComboBox->setCurrentIndex(7); } } else if ((upslots->length() == 0) && (downslots->length() == 0) && (leftslots->length() == 0) && (rightslots->length() == 0)) { ui->presetsComboBox->setCurrentIndex(8); } } void JoyControlStickEditDialog::updateMouseMode(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::inputDaemonMutex.lock(); if (index == 1) { stick->setButtonsMouseMode(JoyButton::MouseCursor); } else if (index == 2) { stick->setButtonsMouseMode(JoyButton::MouseSpring); } PadderCommon::inputDaemonMutex.unlock(); } void JoyControlStickEditDialog::openMouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->mouseSettingsPushButton->setEnabled(false); MouseControlStickSettingsDialog *dialog = new MouseControlStickSettingsDialog(this->stick, this); dialog->show(); connect(this, SIGNAL(finished(int)), dialog, SLOT(close())); connect(dialog, SIGNAL(finished(int)), this, SLOT(enableMouseSettingButton())); } void JoyControlStickEditDialog::enableMouseSettingButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->mouseSettingsPushButton->setEnabled(true); } void JoyControlStickEditDialog::updateWindowTitleStickName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(tr("Set")).append(" "); if (!stick->getStickName().isEmpty()) { temp.append(stick->getPartialName(false, true)); } else { temp.append(stick->getPartialName()); } if (stick->getParentSet()->getIndex() != 0) { int setIndex = stick->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = stick->getParentSet()->getName(); if (!setName.isEmpty()) { temp.append(": ").append(setName); } temp.append("]"); } setWindowTitle(temp); } void JoyControlStickEditDialog::changeCircleAdjust(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QMetaObject::invokeMethod(stick, "setCircleAdjust", Q_ARG(double, value * 0.01)); } /** * @brief Update QDoubleSpinBox value based on updated stick delay value. * @param Delay value obtained from JoyControlStick. */ void JoyControlStickEditDialog::updateStickDelaySpinBox(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); double temp = value * 0.001; ui->stickDelayDoubleSpinBox->setValue(temp); } /** * @brief Update QSlider value based on value from QDoubleSpinBox. * @param Value from QDoubleSpinBox. */ void JoyControlStickEditDialog::updateStickDelaySlider(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int temp = value * 100; if (ui->stickDelaySlider->value() != temp) { ui->stickDelaySlider->setValue(temp); } } void JoyControlStickEditDialog::openModifierEditDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ButtonEditDialog *dialog = new ButtonEditDialog(stick->getModifierButton(), stick->getParentSet()->getInputDevice(), keypadUnlocked, this); dialog->show(); } void JoyControlStickEditDialog::changeModifierSummary() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->modifierPushButton->setText(stick->getModifierButton()->getSlotsSummary()); } JoyControlStickEditDialogHelper &JoyControlStickEditDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/joycontrolstickeditdialog.h000066400000000000000000000041511377703515000245120ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKEDITDIALOG_H #define JOYCONTROLSTICKEDITDIALOG_H #include "uihelpers/joycontrolstickeditdialoghelper.h" #include class JoyControlStick; class QWidget; namespace Ui { class JoyControlStickEditDialog; } class JoyControlStickEditDialog : public QDialog { Q_OBJECT public: explicit JoyControlStickEditDialog(JoyControlStick *stick, bool keypadUnlocked, QWidget *parent = nullptr); // JoyControlStickEditDialog(QWidget *parent = nullptr); ~JoyControlStickEditDialog(); protected: void selectCurrentPreset(); private: Ui::JoyControlStickEditDialog *ui; bool keypadUnlocked; JoyControlStickEditDialogHelper &getHelperLocal(); JoyControlStick *stick; JoyControlStickEditDialogHelper helper; private slots: void implementPresets(int index); void implementModes(int index); void refreshStickStats(int x, int y); void updateMouseMode(int index); void checkMaxZone(int value); void openMouseSettingsDialog(); void enableMouseSettingButton(); void updateWindowTitleStickName(); void changeCircleAdjust(int value); void updateStickDelaySpinBox(int value); void updateStickDelaySlider(double value); void openModifierEditDialog(); void changeModifierSummary(); }; #endif // JOYCONTROLSTICKEDITDIALOG_H AntiMicroX-antimicrox-2888bf6/src/joycontrolstickeditdialog.ui000066400000000000000000000641701377703515000247070ustar00rootroot00000000000000 JoyControlStickEditDialog 0 0 702 570 0 0 0 0 Dialog JoyControlStickButtonPushButton[isflashing="true"] { background-color: rgb(0, 0, 255); color: rgb(205, 197, 191); } true 20 0 0 200 200 16777215 16777215 0 0 200 200 Qt::Vertical QSizePolicy::Fixed 20 20 10 0 0 X: 0 0 0 0 0 Y: 0 0 0 0 0 Distance: 0 0 0 0 0 Bearing: 0 0 0 0 0 % Safe Zone: 0 0 0 Qt::Vertical QSizePolicy::Fixed 20 20 10 Presets: 282 0 Mouse (Normal) Mouse (Inverted Horizontal) Mouse (Inverted Vertical) Mouse (Inverted Horizontal + Vertical) Arrows Keys: W | A | S | D NumPad None Stick Mode: 282 0 Standard: 8 region stick with two direction buttons active when the stick is in a diagonal region. Eight Way: 8 region stick with each direction having its own dedicated button. Only one button is ever active at at time. Useful for rougelike games. 4 Way Cardinal: 4 region stick with regions corresponding to the cardinal directions of the stick. Useful for menus. 4 Way Diagonal: 4 region stick with each region corresponding to a diagonal zone of the stick. Standard Eight Way 4 Way Cardinal 4 Way Diagonal Qt::Vertical QSizePolicy::MinimumExpanding 20 20 6 Dead Zone: Dead zone value to use for an analog stick. 1 32737 100 1000 6000 Qt::Horizontal Dead zone value to use for an analog stick. 1 32737 8000 Max Zone: Value when an analog stick is considered moved 100%. 1 32737 100 1000 32000 Qt::Horizontal Value when an analog stick is considered moved 100%. 1 32737 32000 Diagonal Range: The area (in degrees) that each diagonal region occupies. 1 90 Qt::Horizontal The area (in degrees) that each diagonal region occupies. 1 90 90 Square Stick: Percentage to modify a square stick coordinates to confine values to a circle 0 100 1 10 0 0 Qt::Horizontal Percentage to modify a square stick coordinates to confine values to a circle % 0 100 1 0 Stick Delay: Time lapsed before a direction change is taken into effect. 0 100 1 10 0 0 Qt::Horizontal QSlider::TicksBelow 0 Time lapsed before a direction change is taken into effect. false s 2 1.000000000000000 0.010000000000000 0 Modifier: Edit button that is active while the stick is active. This button is useful for assigning zones with modifier keys that can be used to assign walk/run functionality to an analog stick. PushButton Qt::Vertical QSizePolicy::Fixed 20 20 10 6 Na&me: stickNameLineEdit Specify the name of an analog stick. Mouse Settings .. Qt::Horizontal Qt::Horizontal QDialogButtonBox::Close JoyControlStickStatusBox QWidget

joycontrolstickstatusbox.h
1 buttonBox accepted() JoyControlStickEditDialog accept() 248 254 157 274 buttonBox rejected() JoyControlStickEditDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/joycontrolstickpushbutton.cpp000066400000000000000000000071201377703515000251520ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickpushbutton.h" #include "joycontrolstick.h" #include "joycontrolstickcontextmenu.h" #include "messagehandler.h" #include JoyControlStickPushButton::JoyControlStickPushButton(JoyControlStick *stick, bool displayNames, QWidget *parent) : FlashButtonWidget(displayNames, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->stick = stick; refreshLabel(); tryFlash(); this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &JoyControlStickPushButton::customContextMenuRequested, this, &JoyControlStickPushButton::showContextMenu); connect(stick, &JoyControlStick::active, this, &JoyControlStickPushButton::flash, Qt::QueuedConnection); connect(stick, &JoyControlStick::released, this, &JoyControlStickPushButton::unflash, Qt::QueuedConnection); connect(stick, &JoyControlStick::stickNameChanged, this, &JoyControlStickPushButton::refreshLabel); } JoyControlStick *JoyControlStickPushButton::getStick() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick; } /** * @brief Generate the string that will be displayed on the button * @return Display string */ QString JoyControlStickPushButton::generateLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (!stick->getStickName().isEmpty() && ifDisplayNames()) { temp.append(stick->getPartialName(false, true)); } else { temp.append(stick->getPartialName(false)); } qDebug() << "Name of joy control stick push button: " << temp; return temp; } void JoyControlStickPushButton::disableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(stick, &JoyControlStick::active, this, &JoyControlStickPushButton::flash); disconnect(stick, &JoyControlStick::released, this, &JoyControlStickPushButton::unflash); this->unflash(); } void JoyControlStickPushButton::enableFlashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(stick, &JoyControlStick::active, this, &JoyControlStickPushButton::flash, Qt::QueuedConnection); connect(stick, &JoyControlStick::released, this, &JoyControlStickPushButton::unflash, Qt::QueuedConnection); } void JoyControlStickPushButton::showContextMenu(const QPoint &point) { qInstallMessageHandler(MessageHandler::myMessageOutput); QPoint globalPos = this->mapToGlobal(point); JoyControlStickContextMenu *contextMenu = new JoyControlStickContextMenu(stick, this); contextMenu->buildMenu(); contextMenu->popup(globalPos); } void JoyControlStickPushButton::tryFlash() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (stick->getCurrentDirection() != JoyControlStick::StickCentered) { flash(); } } AntiMicroX-antimicrox-2888bf6/src/joycontrolstickpushbutton.h000066400000000000000000000027531377703515000246260ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKPUSHBUTTON_H #define JOYCONTROLSTICKPUSHBUTTON_H #include "flashbuttonwidget.h" class JoyControlStick; class QWidget; class JoyControlStickPushButton : public FlashButtonWidget { Q_OBJECT public: explicit JoyControlStickPushButton(JoyControlStick *stick, bool displayNames, QWidget *parent = nullptr); JoyControlStick *getStick() const; void tryFlash(); protected: virtual QString generateLabel() override; public slots: void disableFlashes() override; void enableFlashes() override; private slots: void showContextMenu(const QPoint &point); private: JoyControlStick *stick; }; #endif // JOYCONTROLSTICKPUSHBUTTON_H AntiMicroX-antimicrox-2888bf6/src/joycontrolstickstatusbox.cpp000066400000000000000000000506541377703515000250050ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickstatusbox.h" #include "common.h" #include "globalvariables.h" #include "joyaxis.h" #include "joycontrolstick.h" #include "messagehandler.h" #include #include #include #include #include #include #include JoyControlStickStatusBox::JoyControlStickStatusBox(QWidget *parent) : QWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->stick = nullptr; } JoyControlStickStatusBox::JoyControlStickStatusBox(JoyControlStick *stick, QWidget *parent) : QWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->stick = stick; connect(stick, SIGNAL(deadZoneChanged(int)), this, SLOT(update())); connect(stick, SIGNAL(moved(int, int)), this, SLOT(update())); connect(stick, SIGNAL(diagonalRangeChanged(int)), this, SLOT(update())); connect(stick, SIGNAL(maxZoneChanged(int)), this, SLOT(update())); connect(stick, SIGNAL(joyModeChanged()), this, SLOT(update())); connect(stick, SIGNAL(circleAdjustChange(double)), this, SLOT(update())); } void JoyControlStickStatusBox::setStick(JoyControlStick *stick) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (stick != nullptr) { disconnect(stick, SIGNAL(deadZoneChanged(int)), this, nullptr); disconnect(stick, SIGNAL(moved(int, int)), this, nullptr); disconnect(stick, SIGNAL(diagonalRangeChanged(int)), this, nullptr); disconnect(stick, SIGNAL(maxZoneChanged(int)), this, nullptr); disconnect(stick, SIGNAL(joyModeChanged()), this, nullptr); } this->stick = stick; connect(stick, SIGNAL(deadZoneChanged(int)), this, SLOT(update())); connect(stick, SIGNAL(moved(int, int)), this, SLOT(update())); connect(stick, SIGNAL(diagonalRangeChanged(int)), this, SLOT(update())); connect(stick, SIGNAL(maxZoneChanged(int)), this, SLOT(update())); connect(stick, SIGNAL(joyModeChanged()), this, SLOT(update())); update(); } JoyControlStick *JoyControlStickStatusBox::getStick() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick; } int JoyControlStickStatusBox::heightForWidth(int width) const { qInstallMessageHandler(MessageHandler::myMessageOutput); return width; } QSize JoyControlStickStatusBox::sizeHint() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return QSize(-1, -1); } void JoyControlStickStatusBox::paintEvent(QPaintEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(event); PadderCommon::inputDaemonMutex.lock(); if ((stick->getJoyMode() == JoyControlStick::StandardMode) || (stick->getJoyMode() == JoyControlStick::EightWayMode)) { drawEightWayBox(); } else if (stick->getJoyMode() == JoyControlStick::FourWayCardinal) { drawFourWayCardinalBox(); } else if (stick->getJoyMode() == JoyControlStick::FourWayDiagonal) { drawFourWayDiagonalBox(); } PadderCommon::inputDaemonMutex.unlock(); } void JoyControlStickStatusBox::drawEightWayBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); QPainter paint(this); paint.setRenderHint(QPainter::Antialiasing, true); int side = qMin(width() - 2, height() - 2); QPixmap pix(side, side); pix.fill(Qt::transparent); QPainter painter(&pix); painter.setRenderHint(QPainter::Antialiasing, true); // Draw box outline QPen penny; penny.setColor(Qt::black); penny.setWidth(1); painter.setBrush(Qt::NoBrush); painter.drawRect(0, 0, side - 1, side - 1); painter.save(); painter.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); painter.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); // Draw diagonal zones QList anglesList = stick->getDiagonalZoneAngles(); penny.setWidth(0); penny.setColor(Qt::black); painter.setPen(penny); painter.setBrush(QBrush(Qt::green)); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, static_cast(anglesList.value(2)) * 16, stick->getDiagonalRange() * 16); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, static_cast(anglesList.value(4)) * 16, stick->getDiagonalRange() * 16); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, static_cast(anglesList.value(6)) * 16, stick->getDiagonalRange() * 16); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, static_cast(anglesList.value(8)) * 16, stick->getDiagonalRange() * 16); // Draw deadzone circle penny.setWidth(0); penny.setColor(Qt::blue); painter.setPen(penny); painter.setBrush(QBrush(Qt::red)); painter.drawEllipse(-stick->getDeadZone(), -stick->getDeadZone(), stick->getDeadZone() * 2, stick->getDeadZone() * 2); painter.restore(); painter.save(); penny.setWidth(0); penny.setColor(Qt::gray); painter.setPen(penny); painter.scale(side / 2.0, side / 2.0); painter.translate(1, 1); // Draw Y line painter.drawLine(0, -1, 0, 1); // Draw X line painter.drawLine(-1, 0, 1, 0); painter.restore(); painter.save(); painter.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); painter.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); penny.setWidth(0); painter.setBrush(QBrush(Qt::black)); penny.setColor(Qt::black); painter.setPen(penny); // Draw raw crosshair int linexstart = stick->getXCoordinate() - 1000; int lineystart = stick->getYCoordinate() - 1000; if (linexstart < GlobalVariables::JoyAxis::AXISMIN) { linexstart = GlobalVariables::JoyAxis::AXISMIN; } if (lineystart < GlobalVariables::JoyAxis::AXISMIN) { lineystart = GlobalVariables::JoyAxis::AXISMIN; } painter.drawRect(linexstart, lineystart, 2000, 2000); painter.setBrush(QBrush(Qt::darkBlue)); penny.setColor(Qt::darkBlue); painter.setPen(penny); // Draw adjusted crosshair linexstart = stick->getCircleXCoordinate() - 1000; lineystart = stick->getCircleYCoordinate() - 1000; if (linexstart < GlobalVariables::JoyAxis::AXISMIN) { linexstart = GlobalVariables::JoyAxis::AXISMIN; } if (lineystart < GlobalVariables::JoyAxis::AXISMIN) { lineystart = GlobalVariables::JoyAxis::AXISMIN; } painter.drawRect(linexstart, lineystart, 2000, 2000); painter.restore(); // Reset pen penny.setColor(Qt::black); painter.setPen(penny); // Draw primary pixmap painter.setCompositionMode(QPainter::CompositionMode_DestinationOver); painter.setPen(Qt::NoPen); painter.fillRect(0, 0, side, side, palette().window().color()); paint.drawPixmap(pix.rect(), pix); paint.save(); paint.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); paint.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); // Draw max zone and initial inner clear circle int maxzone = stick->getMaxZone(); int diffmaxzone = GlobalVariables::JoyAxis::AXISMAX - maxzone; paint.setOpacity(0.5); paint.setBrush(Qt::darkGreen); paint.drawEllipse(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2); paint.setCompositionMode(QPainter::CompositionMode_Clear); paint.setPen(Qt::NoPen); paint.drawEllipse(-GlobalVariables::JoyAxis::AXISMAX + diffmaxzone, -GlobalVariables::JoyAxis::AXISMAX + diffmaxzone, GlobalVariables::JoyAxis::AXISMAX * 2 - (diffmaxzone * 2), GlobalVariables::JoyAxis::AXISMAX * 2 - (diffmaxzone * 2)); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); paint.setOpacity(1.0); paint.restore(); // Re-draw pixmap so the inner circle will be transparent paint.setCompositionMode(QPainter::CompositionMode_DestinationOver); paint.drawPixmap(pix.rect(), pix); paint.setCompositionMode(QPainter::CompositionMode_SourceOver); } void JoyControlStickStatusBox::drawFourWayCardinalBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); QPainter paint(this); paint.setRenderHint(QPainter::Antialiasing, true); int side = qMin(width() - 2, height() - 2); QPixmap pix(side, side); pix.fill(Qt::transparent); QPainter painter(&pix); painter.setRenderHint(QPainter::Antialiasing, true); // Draw box outline QPen penny; penny.setColor(Qt::black); penny.setWidth(1); painter.setBrush(Qt::NoBrush); painter.drawRect(0, 0, side - 1, side - 1); painter.save(); painter.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); painter.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); // Draw diagonal zones QList anglesList = stick->getFourWayCardinalZoneAngles(); penny.setWidth(0); penny.setColor(Qt::black); painter.setPen(penny); painter.setOpacity(0.25); painter.setBrush(QBrush(Qt::black)); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, anglesList.value(1) * 16, 90 * 16); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, anglesList.value(3) * 16, 90 * 16); painter.setOpacity(1.0); // Draw deadzone circle penny.setWidth(0); penny.setColor(Qt::blue); painter.setPen(penny); painter.setBrush(QBrush(Qt::red)); painter.drawEllipse(-stick->getDeadZone(), -stick->getDeadZone(), stick->getDeadZone() * 2, stick->getDeadZone() * 2); painter.restore(); painter.save(); penny.setWidth(0); penny.setColor(Qt::black); painter.setPen(penny); painter.setOpacity(0.5); painter.scale(side / 2.0, side / 2.0); painter.translate(1, 1); // Draw Y line painter.drawLine(0, -1, 0, 1); // Draw X line painter.drawLine(-1, 0, 1, 0); painter.setOpacity(1.0); painter.restore(); painter.save(); painter.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); painter.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); penny.setWidth(0); painter.setBrush(QBrush(Qt::black)); penny.setColor(Qt::black); painter.setPen(penny); // Draw raw crosshair int linexstart = stick->getXCoordinate() - 1000; int lineystart = stick->getYCoordinate() - 1000; if (linexstart < GlobalVariables::JoyAxis::AXISMIN) { linexstart = GlobalVariables::JoyAxis::AXISMIN; } if (lineystart < GlobalVariables::JoyAxis::AXISMIN) { lineystart = GlobalVariables::JoyAxis::AXISMIN; } painter.drawRect(linexstart, lineystart, 2000, 2000); painter.setBrush(QBrush(Qt::darkBlue)); penny.setColor(Qt::darkBlue); painter.setPen(penny); // Draw adjusted crosshair linexstart = stick->getCircleXCoordinate() - 1000; lineystart = stick->getCircleYCoordinate() - 1000; if (linexstart < GlobalVariables::JoyAxis::AXISMIN) { linexstart = GlobalVariables::JoyAxis::AXISMIN; } if (lineystart < GlobalVariables::JoyAxis::AXISMIN) { lineystart = GlobalVariables::JoyAxis::AXISMIN; } painter.drawRect(linexstart, lineystart, 2000, 2000); painter.restore(); // Reset pen penny.setColor(Qt::black); painter.setPen(penny); // Draw primary pixmap painter.setCompositionMode(QPainter::CompositionMode_DestinationOver); painter.setPen(Qt::NoPen); painter.fillRect(0, 0, side, side, palette().window().color()); paint.drawPixmap(pix.rect(), pix); paint.save(); paint.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); paint.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); // Draw max zone and initial inner clear circle int maxzone = stick->getMaxZone(); int diffmaxzone = GlobalVariables::JoyAxis::AXISMAX - maxzone; paint.setOpacity(0.5); paint.setBrush(Qt::darkGreen); paint.drawEllipse(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2); paint.setCompositionMode(QPainter::CompositionMode_Clear); paint.setPen(Qt::NoPen); paint.drawEllipse(-GlobalVariables::JoyAxis::AXISMAX + diffmaxzone, -GlobalVariables::JoyAxis::AXISMAX + diffmaxzone, GlobalVariables::JoyAxis::AXISMAX * 2 - (diffmaxzone * 2), GlobalVariables::JoyAxis::AXISMAX * 2 - (diffmaxzone * 2)); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); paint.setOpacity(1.0); paint.restore(); // Re-draw pixmap so the inner circle will be transparent paint.setCompositionMode(QPainter::CompositionMode_DestinationOver); paint.drawPixmap(pix.rect(), pix); paint.setCompositionMode(QPainter::CompositionMode_SourceOver); } void JoyControlStickStatusBox::drawFourWayDiagonalBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); QPainter paint(this); paint.setRenderHint(QPainter::Antialiasing, true); int side = qMin(width() - 2, height() - 2); QPixmap pix(side, side); pix.fill(Qt::transparent); QPainter painter(&pix); painter.setRenderHint(QPainter::Antialiasing, true); // Draw box outline QPen penny; penny.setColor(Qt::black); penny.setWidth(1); painter.setBrush(Qt::NoBrush); painter.drawRect(0, 0, side - 1, side - 1); painter.save(); painter.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); painter.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); // Draw diagonal zones QList anglesList = stick->getFourWayDiagonalZoneAngles(); penny.setWidth(0); penny.setColor(Qt::black); painter.setPen(penny); painter.setBrush(QBrush(Qt::black)); painter.setOpacity(0.25); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, anglesList.value(1) * 16, 90 * 16); painter.drawPie(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2, anglesList.value(3) * 16, 90 * 16); painter.setOpacity(1.0); // Draw deadzone circle penny.setWidth(0); penny.setColor(Qt::blue); painter.setPen(penny); painter.setBrush(QBrush(Qt::red)); painter.drawEllipse(-stick->getDeadZone(), -stick->getDeadZone(), stick->getDeadZone() * 2, stick->getDeadZone() * 2); painter.restore(); painter.save(); penny.setWidth(0); penny.setColor(Qt::black); painter.setOpacity(0.5); painter.setPen(penny); painter.scale(side / 2.0, side / 2.0); painter.translate(1, 1); // Draw Y line painter.drawLine(0, -1, 0, 1); // Draw X line painter.drawLine(-1, 0, 1, 0); painter.setOpacity(1.0); painter.restore(); painter.save(); painter.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); painter.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); penny.setWidth(0); painter.setBrush(QBrush(Qt::black)); penny.setColor(Qt::black); painter.setPen(penny); // Draw raw crosshair int linexstart = stick->getXCoordinate() - 1000; int lineystart = stick->getYCoordinate() - 1000; if (linexstart < GlobalVariables::JoyAxis::AXISMIN) { linexstart = GlobalVariables::JoyAxis::AXISMIN; } if (lineystart < GlobalVariables::JoyAxis::AXISMIN) { lineystart = GlobalVariables::JoyAxis::AXISMIN; } painter.drawRect(linexstart, lineystart, 2000, 2000); painter.setBrush(QBrush(Qt::darkBlue)); penny.setColor(Qt::darkBlue); painter.setPen(penny); // Draw adjusted crosshair linexstart = stick->getCircleXCoordinate() - 1000; lineystart = stick->getCircleYCoordinate() - 1000; if (linexstart < GlobalVariables::JoyAxis::AXISMIN) { linexstart = GlobalVariables::JoyAxis::AXISMIN; } if (lineystart < GlobalVariables::JoyAxis::AXISMIN) { lineystart = GlobalVariables::JoyAxis::AXISMIN; } painter.drawRect(linexstart, lineystart, 2000, 2000); painter.restore(); // Reset pen penny.setColor(Qt::black); painter.setPen(penny); // Draw primary pixmap painter.setCompositionMode(QPainter::CompositionMode_DestinationOver); painter.setPen(Qt::NoPen); painter.fillRect(0, 0, side, side, palette().window().color()); paint.drawPixmap(pix.rect(), pix); paint.save(); paint.scale(side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0), side / static_cast(GlobalVariables::JoyAxis::AXISMAX * 2.0)); paint.translate(GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX); // Draw max zone and initial inner clear circle int maxzone = stick->getMaxZone(); int diffmaxzone = GlobalVariables::JoyAxis::AXISMAX - maxzone; paint.setOpacity(0.5); paint.setBrush(Qt::darkGreen); paint.drawEllipse(-GlobalVariables::JoyAxis::AXISMAX, -GlobalVariables::JoyAxis::AXISMAX, GlobalVariables::JoyAxis::AXISMAX * 2, GlobalVariables::JoyAxis::AXISMAX * 2); paint.setCompositionMode(QPainter::CompositionMode_Clear); paint.setPen(Qt::NoPen); paint.drawEllipse(-GlobalVariables::JoyAxis::AXISMAX + diffmaxzone, -GlobalVariables::JoyAxis::AXISMAX + diffmaxzone, GlobalVariables::JoyAxis::AXISMAX * 2 - (diffmaxzone * 2), GlobalVariables::JoyAxis::AXISMAX * 2 - (diffmaxzone * 2)); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); paint.setOpacity(1.0); paint.restore(); // Re-draw pixmap so the inner circle will be transparent paint.setCompositionMode(QPainter::CompositionMode_DestinationOver); paint.drawPixmap(pix.rect(), pix); paint.setCompositionMode(QPainter::CompositionMode_SourceOver); } AntiMicroX-antimicrox-2888bf6/src/joycontrolstickstatusbox.h000066400000000000000000000031051377703515000244370ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKSTATUSBOX_H #define JOYCONTROLSTICKSTATUSBOX_H #include #include class JoyControlStick; class QPaintEvent; class JoyControlStickStatusBox : public QWidget { Q_OBJECT public: explicit JoyControlStickStatusBox(QWidget *parent = nullptr); explicit JoyControlStickStatusBox(JoyControlStick *stick, QWidget *parent = nullptr); void setStick(JoyControlStick *stick); JoyControlStick *getStick() const; virtual int heightForWidth(int width) const; QSize sizeHint() const; protected: virtual void paintEvent(QPaintEvent *event); void drawEightWayBox(); void drawFourWayCardinalBox(); void drawFourWayDiagonalBox(); private: JoyControlStick *stick; }; #endif // JOYCONTROLSTICKSTATUSBOX_H AntiMicroX-antimicrox-2888bf6/src/joydpad.cpp000066400000000000000000001123701377703515000212140ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joydpad.h" #include "globalvariables.h" #include "inputdevice.h" #include "messagehandler.h" #include #include JoyDPad::JoyDPad(int index, int originset, SetJoystick *parentSet, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_index = index; buttons = QHash(); activeDiagonalButton = nullptr; prevDirection = JoyDPadButton::DpadCentered; pendingDirection = prevDirection; m_originset = originset; currentMode = StandardMode; m_parentSet = parentSet; this->dpadDelay = GlobalVariables::JoyDPad::DEFAULTDPADDELAY; populateButtons(); pendingEvent = false; pendingEventDirection = prevDirection; pendingIgnoreSets = false; directionDelayTimer.setSingleShot(true); connect(&directionDelayTimer, &QTimer::timeout, this, &JoyDPad::dpadDirectionChangeEvent); } JoyDPad::~JoyDPad() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); delete button; button = nullptr; } buttons.clear(); } JoyDPadButton *JoyDPad::getJoyButton(int index_local) { qInstallMessageHandler(MessageHandler::myMessageOutput); return buttons.value(index_local); } void JoyDPad::populateButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *button = new JoyDPadButton(JoyDPadButton::DpadUp, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadUp, button); button = new JoyDPadButton(JoyDPadButton::DpadDown, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadDown, button); button = new JoyDPadButton(JoyDPadButton::DpadRight, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadRight, button); button = new JoyDPadButton(JoyDPadButton::DpadLeft, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadLeft, button); button = new JoyDPadButton(JoyDPadButton::DpadLeftUp, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadLeftUp, button); button = new JoyDPadButton(JoyDPadButton::DpadRightUp, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadRightUp, button); button = new JoyDPadButton(JoyDPadButton::DpadRightDown, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadRightDown, button); button = new JoyDPadButton(JoyDPadButton::DpadLeftDown, m_originset, this, m_parentSet, this); buttons.insert(JoyDPadButton::DpadLeftDown, button); } QString JoyDPad::getName(bool fullForceFormat, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); if (!dpadName.isEmpty() && displayNames) { if (fullForceFormat) { label.append(tr("DPad")).append(" "); } label.append(dpadName); } else if (!defaultDPadName.isEmpty()) { if (fullForceFormat) { label.append(tr("DPad")).append(" "); } label.append(defaultDPadName); } else { label.append(tr("DPad")).append(" "); label.append(QString::number(getRealJoyNumber())); } return label; } int JoyDPad::getJoyNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index; } int JoyDPad::getIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index; } int JoyDPad::getRealJoyNumber() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index + 1; } QString JoyDPad::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::JoyDPad::xmlName; } void JoyDPad::queuePendingEvent(int value, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingEvent = true; pendingEventDirection = value; pendingIgnoreSets = ignoresets; } void JoyDPad::activatePendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (pendingEvent) { joyEvent(pendingEventDirection, pendingIgnoreSets); pendingEvent = false; pendingEventDirection = static_cast(JoyDPadButton::DpadCentered); pendingIgnoreSets = false; } } bool JoyDPad::hasPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); return pendingEvent; } void JoyDPad::clearPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingEvent = false; pendingEventDirection = static_cast(JoyDPadButton::DpadCentered); pendingIgnoreSets = false; } void JoyDPad::joyEvent(int value, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (value != static_cast(pendingDirection)) { if (value != static_cast(JoyDPadButton::DpadCentered)) { if (prevDirection == JoyDPadButton::DpadCentered) { emit active(value); } pendingDirection = static_cast(value); if (ignoresets || (dpadDelay == 0)) { if (directionDelayTimer.isActive()) { directionDelayTimer.stop(); } createDeskEvent(ignoresets); } else if (pendingDirection != prevDirection) { if (!directionDelayTimer.isActive()) { directionDelayTimer.start(dpadDelay); } } else { if (directionDelayTimer.isActive()) { directionDelayTimer.stop(); } } } else { emit released(value); pendingDirection = JoyDPadButton::DpadCentered; if (ignoresets || dpadDelay == 0) { if (directionDelayTimer.isActive()) { directionDelayTimer.stop(); } createDeskEvent(ignoresets); } else { if (!directionDelayTimer.isActive()) { directionDelayTimer.start(dpadDelay); } } } } } QHash *JoyDPad::getJoyButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &buttons; } int JoyDPad::getCurrentDirection() { qInstallMessageHandler(MessageHandler::myMessageOutput); return prevDirection; } void JoyDPad::setJoyMode(JoyMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); currentMode = mode; emit joyModeChanged(); emit propertyUpdated(); } JoyDPad::JoyMode JoyDPad::getJoyMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); return currentMode; } void JoyDPad::releaseButtonEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->joyEvent(false, true); } } QHash *JoyDPad::getButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &buttons; } bool JoyDPad::isDefault() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool value = true; value = value && (currentMode == StandardMode); value = value && (dpadDelay == GlobalVariables::JoyDPad::DEFAULTDPADDELAY); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); value = value && (button->isDefault()); } return value; } void JoyDPad::setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setMouseMode(mode); } } bool JoyDPad::hasSameButtonsMouseMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; JoyButton::JoyMouseMovementMode initialMode = JoyButton::MouseCursor; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); initialMode = button->getMouseMode(); } else { JoyDPadButton *button = iter.next().value(); JoyButton::JoyMouseMovementMode temp = button->getMouseMode(); if (temp != initialMode) { result = false; iter.toBack(); } } } return result; } JoyButton::JoyMouseMovementMode JoyDPad::getButtonsPresetMouseMode() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseMovementMode resultMode = JoyButton::MouseCursor; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); resultMode = button->getMouseMode(); } else { JoyDPadButton *button = iter.next().value(); JoyButton::JoyMouseMovementMode temp = button->getMouseMode(); if (temp != resultMode) { resultMode = JoyButton::MouseCursor; iter.toBack(); } } } return resultMode; } void JoyDPad::setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setMouseCurve(mouseCurve); } } bool JoyDPad::hasSameButtonsMouseCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; JoyButton::JoyMouseCurve initialCurve = JoyButton::LinearCurve; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); initialCurve = button->getMouseCurve(); } else { JoyDPadButton *button = iter.next().value(); JoyButton::JoyMouseCurve temp = button->getMouseCurve(); if (temp != initialCurve) { result = false; iter.toBack(); } } } return result; } JoyButton::JoyMouseCurve JoyDPad::getButtonsPresetMouseCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve resultCurve = JoyButton::LinearCurve; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); resultCurve = button->getMouseCurve(); } else { JoyDPadButton *button = iter.next().value(); JoyButton::JoyMouseCurve temp = button->getMouseCurve(); if (temp != resultCurve) { resultCurve = JoyButton::LinearCurve; iter.toBack(); } } } return resultCurve; } void JoyDPad::setButtonsSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setSpringWidth(value); } } void JoyDPad::setButtonsSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setSpringHeight(value); } } int JoyDPad::getButtonsPresetSpringWidth() { qInstallMessageHandler(MessageHandler::myMessageOutput); int presetSpringWidth = 0; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); presetSpringWidth = button->getSpringWidth(); } else { JoyDPadButton *button = iter.next().value(); int temp = button->getSpringWidth(); if (temp != presetSpringWidth) { presetSpringWidth = 0; iter.toBack(); } } } return presetSpringWidth; } int JoyDPad::getButtonsPresetSpringHeight() { qInstallMessageHandler(MessageHandler::myMessageOutput); int presetSpringHeight = 0; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); presetSpringHeight = button->getSpringHeight(); } else { JoyDPadButton *button = iter.next().value(); int temp = button->getSpringHeight(); if (temp != presetSpringHeight) { presetSpringHeight = 0; iter.toBack(); } } } return presetSpringHeight; } void JoyDPad::setButtonsSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setSensitivity(value); } } double JoyDPad::getButtonsPresetSensitivity() { qInstallMessageHandler(MessageHandler::myMessageOutput); double presetSensitivity = 1.0; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); presetSensitivity = button->getSensitivity(); } else { JoyDPadButton *button = iter.next().value(); double temp = button->getSensitivity(); if (!qFuzzyCompare(temp, presetSensitivity)) { presetSensitivity = 1.0; iter.toBack(); } } } return presetSensitivity; } QHash JoyDPad::getApplicableButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash; if ((currentMode == StandardMode) || (currentMode == EightWayMode) || (currentMode == FourWayCardinal)) { temphash.insert(JoyDPadButton::DpadUp, buttons.value(JoyDPadButton::DpadUp)); temphash.insert(JoyDPadButton::DpadDown, buttons.value(JoyDPadButton::DpadDown)); temphash.insert(JoyDPadButton::DpadLeft, buttons.value(JoyDPadButton::DpadLeft)); temphash.insert(JoyDPadButton::DpadRight, buttons.value(JoyDPadButton::DpadRight)); } if ((currentMode == EightWayMode) || (currentMode == FourWayDiagonal)) { temphash.insert(JoyDPadButton::DpadLeftUp, buttons.value(JoyDPadButton::DpadLeftUp)); temphash.insert(JoyDPadButton::DpadRightUp, buttons.value(JoyDPadButton::DpadRightUp)); temphash.insert(JoyDPadButton::DpadRightDown, buttons.value(JoyDPadButton::DpadRightDown)); temphash.insert(JoyDPadButton::DpadLeftDown, buttons.value(JoyDPadButton::DpadLeftDown)); } return temphash; } void JoyDPad::setDPadName(QString tempName) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((tempName.length() <= 20) && (tempName != dpadName)) { dpadName = tempName; emit dpadNameChanged(); emit propertyUpdated(); } } const QString JoyDPad::getDpadName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return dpadName; } const QString JoyDPad::getDefaultDpadName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return defaultDPadName; } void JoyDPad::setButtonsWheelSpeedX(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setWheelSpeed(value, 'X'); } } void JoyDPad::setButtonsWheelSpeedY(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setWheelSpeed(value, 'Y'); } } void JoyDPad::setDefaultDPadName(QString tempname) { qInstallMessageHandler(MessageHandler::myMessageOutput); defaultDPadName = tempname; emit dpadNameChanged(); } QString JoyDPad::getDefaultDPadName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return defaultDPadName; } SetJoystick *JoyDPad::getParentSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_parentSet; } void JoyDPad::establishPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(this, &JoyDPad::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); } void JoyDPad::disconnectPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(this, &JoyDPad::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); } bool JoyDPad::hasSlotsAssigned() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool hasSlots = false; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); if (button != nullptr) { if (button->getAssignedSlots()->count() > 0) { hasSlots = true; iter.toBack(); } } } return hasSlots; } void JoyDPad::setButtonsSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setSpringRelativeStatus(value); } } bool JoyDPad::isRelativeSpring() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool relative = false; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); relative = button->isRelativeSpring(); } else { JoyDPadButton *button = iter.next().value(); bool temp = button->isRelativeSpring(); if (temp != relative) { relative = false; iter.toBack(); } } } return relative; } void JoyDPad::copyAssignments(JoyDPad *destDPad) { qInstallMessageHandler(MessageHandler::myMessageOutput); destDPad->activeDiagonalButton = activeDiagonalButton; destDPad->prevDirection = prevDirection; destDPad->currentMode = currentMode; destDPad->dpadDelay = dpadDelay; QHashIterator iter(destDPad->buttons); while (iter.hasNext()) { JoyDPadButton *destButton = iter.next().value(); if (destButton != nullptr) { JoyDPadButton *sourceButton = buttons.value(destButton->getDirection()); if (sourceButton != nullptr) { sourceButton->copyAssignments(destButton); } } } if (!destDPad->isDefault()) { emit propertyUpdated(); } } void JoyDPad::createDeskEvent(bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *curButton = nullptr; JoyDPadButton *prevButton = nullptr; JoyDPadButton::JoyDPadDirections value = pendingDirection; if (pendingDirection != prevDirection) { if (activeDiagonalButton != nullptr) { activeDiagonalButton->joyEvent(false, ignoresets); activeDiagonalButton = nullptr; } else { if (currentMode == StandardMode) { if ((prevDirection & JoyDPadButton::DpadUp) && (!(value & JoyDPadButton::DpadUp))) { prevButton = buttons.value(JoyDPadButton::DpadUp); prevButton->joyEvent(false, ignoresets); } if ((prevDirection & JoyDPadButton::DpadDown) && (!(value & JoyDPadButton::DpadDown))) { prevButton = buttons.value(JoyDPadButton::DpadDown); prevButton->joyEvent(false, ignoresets); } if ((prevDirection & JoyDPadButton::DpadLeft) && (!(value & JoyDPadButton::DpadLeft))) { prevButton = buttons.value(JoyDPadButton::DpadLeft); prevButton->joyEvent(false, ignoresets); } if ((prevDirection & JoyDPadButton::DpadRight) && (!(value & JoyDPadButton::DpadRight))) { prevButton = buttons.value(JoyDPadButton::DpadRight); prevButton->joyEvent(false, ignoresets); } } else if ((currentMode == EightWayMode) && prevDirection) { prevButton = buttons.value(prevDirection); prevButton->joyEvent(false, ignoresets); } else if ((currentMode == FourWayCardinal) && (static_cast(prevDirection) != 0)) { if (((prevDirection == JoyDPadButton::DpadUp) || (prevDirection == JoyDPadButton::DpadRightUp)) && ((value != JoyDPadButton::DpadUp) && (value != JoyDPadButton::DpadRightUp))) { prevButton = buttons.value(JoyDPadButton::DpadUp); } else if (((prevDirection == JoyDPadButton::DpadDown) || (prevDirection == JoyDPadButton::DpadLeftDown)) && ((value != JoyDPadButton::DpadDown) && (value != JoyDPadButton::DpadLeftDown))) { prevButton = buttons.value(JoyDPadButton::DpadDown); } else if (((prevDirection == JoyDPadButton::DpadLeft) || (prevDirection == JoyDPadButton::DpadLeftUp)) && ((value != JoyDPadButton::DpadLeft) && (value != JoyDPadButton::DpadLeftUp))) { prevButton = buttons.value(JoyDPadButton::DpadLeft); } else if (((prevDirection == JoyDPadButton::DpadRight) || (prevDirection == JoyDPadButton::DpadRightDown)) && ((value != JoyDPadButton::DpadRight) && (value != JoyDPadButton::DpadRightDown))) { prevButton = buttons.value(JoyDPadButton::DpadRight); } if (prevButton != nullptr) { prevButton->joyEvent(false, ignoresets); } } else if ((currentMode == FourWayDiagonal) && (static_cast(prevDirection) != 0)) { prevButton = buttons.value(prevDirection); prevButton->joyEvent(false, ignoresets); } } switch (currentMode) { case StandardMode: { if ((value & JoyDPadButton::DpadUp) && (!(prevDirection & JoyDPadButton::DpadUp))) { curButton = buttons.value(JoyDPadButton::DpadUp); curButton->joyEvent(true, ignoresets); } if ((value & JoyDPadButton::DpadDown) && (!(prevDirection & JoyDPadButton::DpadDown))) { curButton = buttons.value(JoyDPadButton::DpadDown); curButton->joyEvent(true, ignoresets); } if ((value & JoyDPadButton::DpadLeft) && (!(prevDirection & JoyDPadButton::DpadLeft))) { curButton = buttons.value(JoyDPadButton::DpadLeft); curButton->joyEvent(true, ignoresets); } if ((value & JoyDPadButton::DpadRight) && (!(prevDirection & JoyDPadButton::DpadRight))) { curButton = buttons.value(JoyDPadButton::DpadRight); curButton->joyEvent(true, ignoresets); } break; } case EightWayMode: { switch (value) { case JoyDPadButton::DpadLeftUp: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadLeftUp); activeDiagonalButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadRightUp: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadRightUp); activeDiagonalButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadRightDown: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadRightDown); activeDiagonalButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadLeftDown: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadLeftDown); activeDiagonalButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadUp: { curButton = buttons.value(JoyDPadButton::DpadUp); curButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadDown: { curButton = buttons.value(JoyDPadButton::DpadDown); curButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadLeft: { curButton = buttons.value(JoyDPadButton::DpadLeft); curButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadRight: { curButton = buttons.value(JoyDPadButton::DpadRight); curButton->joyEvent(true, ignoresets); break; } default: break; } break; } case FourWayCardinal: { if ((value == JoyDPadButton::DpadUp) || (value == JoyDPadButton::DpadRightUp)) { curButton = buttons.value(JoyDPadButton::DpadUp); curButton->joyEvent(true, ignoresets); } else if ((value == JoyDPadButton::DpadDown) || (value == JoyDPadButton::DpadLeftDown)) { curButton = buttons.value(JoyDPadButton::DpadDown); curButton->joyEvent(true, ignoresets); } else if ((value == JoyDPadButton::DpadLeft) || (value == JoyDPadButton::DpadLeftUp)) { curButton = buttons.value(JoyDPadButton::DpadLeft); curButton->joyEvent(true, ignoresets); } else if ((value == JoyDPadButton::DpadRight) || (value == JoyDPadButton::DpadRightDown)) { curButton = buttons.value(JoyDPadButton::DpadRight); curButton->joyEvent(true, ignoresets); } break; } case FourWayDiagonal: { switch (value) { case JoyDPadButton::DpadLeftUp: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadLeftUp); activeDiagonalButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadRightUp: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadRightUp); activeDiagonalButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadRightDown: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadRightDown); activeDiagonalButton->joyEvent(true, ignoresets); break; } case JoyDPadButton::DpadLeftDown: { activeDiagonalButton = buttons.value(JoyDPadButton::DpadLeftDown); activeDiagonalButton->joyEvent(true, ignoresets); break; } default: break; } break; } } prevDirection = pendingDirection; } } void JoyDPad::dpadDirectionChangeEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); createDeskEvent(); } void JoyDPad::setDPadDelay(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (((value >= 10) && (value <= 1000)) || (value == 0)) { this->dpadDelay = value; emit dpadDelayChanged(value); emit propertyUpdated(); } } int JoyDPad::getDPadDelay() { qInstallMessageHandler(MessageHandler::myMessageOutput); return dpadDelay; } void JoyDPad::setButtonsEasingDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setEasingDuration(value); } } double JoyDPad::getButtonsEasingDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); double result = GlobalVariables::JoyButton::DEFAULTEASINGDURATION; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); result = button->getEasingDuration(); } else { JoyDPadButton *button = iter.next().value(); double temp = button->getEasingDuration(); if (!qFuzzyCompare(temp, result)) { result = GlobalVariables::JoyButton::DEFAULTEASINGDURATION; iter.toBack(); } } } return result; } void JoyDPad::setButtonsSpringDeadCircleMultiplier(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setSpringDeadCircleMultiplier(value); } } int JoyDPad::getButtonsSpringDeadCircleMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); result = button->getSpringDeadCircleMultiplier(); } else { JoyDPadButton *button = iter.next().value(); int temp = button->getSpringDeadCircleMultiplier(); if (temp != result) { result = GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS; iter.toBack(); } } } return result; } void JoyDPad::setButtonsExtraAccelerationCurve(JoyButton::JoyExtraAccelerationCurve curve) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setExtraAccelerationCurve(curve); } } JoyButton::JoyExtraAccelerationCurve JoyDPad::getButtonsExtraAccelerationCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve result = JoyButton::LinearAccelCurve; QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { if (!iter.hasPrevious()) { JoyDPadButton *button = iter.next().value(); result = button->getExtraAccelerationCurve(); } else { JoyDPadButton *button = iter.next().value(); JoyButton::JoyExtraAccelerationCurve temp = button->getExtraAccelerationCurve(); if (temp != result) { result = JoyButton::LinearAccelCurve; iter.toBack(); } } } return result; } QHash JoyDPad::getDirectionButtons(JoyDPadButton::JoyDPadDirections direction) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash; switch (currentMode) { case StandardMode: { if (direction & JoyDPadButton::DpadUp) { temphash.insert(JoyDPadButton::DpadUp, buttons.value(JoyDPadButton::DpadUp)); } if (direction & JoyDPadButton::DpadDown) { temphash.insert(JoyDPadButton::DpadDown, buttons.value(JoyDPadButton::DpadDown)); } if (direction & JoyDPadButton::DpadLeft) { temphash.insert(JoyDPadButton::DpadLeft, buttons.value(JoyDPadButton::DpadLeft)); } if (direction & JoyDPadButton::DpadRight) { temphash.insert(JoyDPadButton::DpadRight, buttons.value(JoyDPadButton::DpadRight)); } break; } case EightWayMode: { if (direction != JoyDPadButton::DpadCentered) { temphash.insert(direction, buttons.value(direction)); } break; } case FourWayCardinal: { if ((direction == JoyDPadButton::DpadUp) || (direction == JoyDPadButton::DpadDown) || (direction == JoyDPadButton::DpadLeft) || (direction == JoyDPadButton::DpadRight)) { temphash.insert(direction, buttons.value(direction)); } break; } case FourWayDiagonal: { if ((direction == JoyDPadButton::DpadRightUp) || (direction == JoyDPadButton::DpadRightDown) || (direction == JoyDPadButton::DpadLeftDown) || (direction == JoyDPadButton::DpadLeftUp)) { temphash.insert(direction, buttons.value(direction)); } break; } } return temphash; } void JoyDPad::setDirButtonsUpdateInitAccel(JoyDPadButton::JoyDPadDirections direction, bool state) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash apphash = getDirectionButtons(direction); QHashIterator iter(apphash); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); if (button != nullptr) { button->setUpdateInitAccel(state); } } } void JoyDPad::copyLastDistanceValues(JoyDPad *srcDPad) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash apphash = srcDPad->getApplicableButtons(); QHashIterator iter(apphash); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); if ((button != nullptr) && button->getButtonState()) { this->buttons.value(iter.key())->copyLastAccelerationDistance(button); this->buttons.value(iter.key())->copyLastMouseDistanceFromDeadZone(button); } } } void JoyDPad::eventReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash temphash = getApplicableButtons(); QHashIterator iter(temphash); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->eventReset(); } } AntiMicroX-antimicrox-2888bf6/src/joydpad.h000066400000000000000000000116271377703515000206640ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYDPAD_H #define JOYDPAD_H #include "joybuttontypes/joydpadbutton.h" class JoyDPad : public QObject { Q_OBJECT public: explicit JoyDPad(int index, int originset, SetJoystick *parentSet, QObject *parent = 0); ~JoyDPad(); enum JoyMode { StandardMode = 0, EightWayMode, FourWayCardinal, FourWayDiagonal }; JoyDPadButton *getJoyButton(int index_local); QHash *getJoyButtons(); int getCurrentDirection(); int getJoyNumber(); int getIndex(); int getRealJoyNumber(); virtual QString getName(bool fullForceFormat = false, bool displayNames = false); void joyEvent(int value, bool ignoresets = false); // JoyDPadEvent class void queuePendingEvent(int value, bool ignoresets = false); // JoyDPadEvent class void activatePendingEvent(); // JoyDPadEvent class bool hasPendingEvent(); // JoyDPadEvent class void clearPendingEvent(); // JoyDPadEvent class void setJoyMode(JoyMode mode); JoyMode getJoyMode(); void releaseButtonEvents(); // JoyDPadEvent class void setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode); bool hasSameButtonsMouseMode(); JoyButton::JoyMouseMovementMode getButtonsPresetMouseMode(); void setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve); bool hasSameButtonsMouseCurve(); JoyButton::JoyMouseCurve getButtonsPresetMouseCurve(); void setButtonsSpringWidth(int value); int getButtonsPresetSpringWidth(); void setButtonsSpringHeight(int value); int getButtonsPresetSpringHeight(); void setButtonsSensitivity(double value); double getButtonsPresetSensitivity(); void setButtonsWheelSpeedX(int value); void setButtonsWheelSpeedY(int value); const QString getDpadName(); const QString getDefaultDpadName(); virtual bool isDefault(); QHash *getButtons(); virtual QString getXmlName(); // JoyDPadXml class virtual void setDefaultDPadName(QString tempname); virtual QString getDefaultDPadName(); SetJoystick *getParentSet(); bool hasSlotsAssigned(); bool isRelativeSpring(); void copyAssignments(JoyDPad *destDPad); int getDPadDelay(); double getButtonsEasingDuration(); void setButtonsSpringDeadCircleMultiplier(int value); int getButtonsSpringDeadCircleMultiplier(); void setButtonsExtraAccelerationCurve(JoyButton::JoyExtraAccelerationCurve curve); JoyButton::JoyExtraAccelerationCurve getButtonsExtraAccelerationCurve(); QHash getDirectionButtons(JoyDPadButton::JoyDPadDirections direction); void setDirButtonsUpdateInitAccel(JoyDPadButton::JoyDPadDirections direction, bool state); void copyLastDistanceValues(JoyDPad *srcDPad); virtual void eventReset(); // JoyDPadEvent class signals: void active(int value); void released(int value); void dpadNameChanged(); void dpadDelayChanged(int value); void joyModeChanged(); void propertyUpdated(); public slots: void setDPadName(QString tempName); void setButtonsSpringRelativeStatus(bool value); void setDPadDelay(int value); void setButtonsEasingDuration(double value); void establishPropertyUpdatedConnection(); void disconnectPropertyUpdatedConnection(); private slots: void dpadDirectionChangeEvent(); protected: void populateButtons(); void createDeskEvent(bool ignoresets = false); // JoyDPadEvent class QHash getApplicableButtons(); private: QHash buttons; JoyDPadButton::JoyDPadDirections prevDirection; JoyDPadButton::JoyDPadDirections pendingDirection; JoyDPadButton *activeDiagonalButton; QString dpadName; QString defaultDPadName; SetJoystick *m_parentSet; QTimer directionDelayTimer; JoyMode currentMode; int m_index; int m_originset; int dpadDelay; // unsigned int pendingEventDirection; bool pendingEvent; bool pendingIgnoreSets; }; #endif // JOYDPAD_H AntiMicroX-antimicrox-2888bf6/src/joydpadbuttonwidget.cpp000066400000000000000000000034141377703515000236520ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joydpadbuttonwidget.h" #include "joybutton.h" #include "messagehandler.h" #include #include JoyDPadButtonWidget::JoyDPadButtonWidget(JoyButton *button, bool displayNames, QWidget *parent) : JoyButtonWidget(button, displayNames, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Ensure that JoyDPadButtonWidget::generateLabel is called. refreshLabel(); } /** * @brief Generate the string that will be displayed on the button * @return Display string */ QString JoyDPadButtonWidget::generateLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (!getJoyButton()->getActionName().isEmpty() && ifDisplayNames()) { temp = getJoyButton()->getActionName(); } else { temp = getJoyButton()->getCalculatedActiveZoneSummary(); } temp.replace("&", "&&"); qDebug() << "Name of joy dpad button is: " << temp; return temp; } AntiMicroX-antimicrox-2888bf6/src/joydpadbuttonwidget.h000066400000000000000000000023001377703515000233100ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYDPADBUTTONWIDGET_H #define JOYDPADBUTTONWIDGET_H #include "joybuttonwidget.h" class JoyButton; class QWidget; class JoyDPadButtonWidget : public JoyButtonWidget { Q_OBJECT public: explicit JoyDPadButtonWidget(JoyButton *button, bool displayNames, QWidget *parent = nullptr); protected: virtual QString generateLabel() override; }; #endif // JOYDPADBUTTONWIDGET_H AntiMicroX-antimicrox-2888bf6/src/joykeyrepeathelper.cpp000066400000000000000000000040011377703515000234640ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joykeyrepeathelper.h" #include "event.h" #include "joybuttonslot.h" JoyKeyRepeatHelper::JoyKeyRepeatHelper(QObject *parent) : QObject(parent) { lastActiveKey = 0; keyRepeatTimer.setParent(this); connect(&keyRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKeysEvent())); } QTimer *JoyKeyRepeatHelper::getRepeatTimer() { return &keyRepeatTimer; } void JoyKeyRepeatHelper::repeatKeysEvent() { if (lastActiveKey) { JoyButtonSlot *slot = lastActiveKey; // Send another key press to fake a key repeat sendevent(slot); keyRepeatTimer.start(keyRepeatRate); } else { keyRepeatTimer.stop(); } } void JoyKeyRepeatHelper::setLastActiveKey(JoyButtonSlot *slot) { lastActiveKey = slot; } JoyButtonSlot *JoyKeyRepeatHelper::getLastActiveKey() { return lastActiveKey; } /*void JoyKeyRepeatHelper::setKeyRepeatDelay(unsigned int repeatDelay) { if (repeatDelay > 0) { keyRepeatDelay = repeatDelay; } } unsigned int JoyKeyRepeatHelper::getKeyRepeatDelay() { return keyRepeatDelay; } */ void JoyKeyRepeatHelper::setKeyRepeatRate(int repeatRate) { if (repeatRate > 0) { keyRepeatRate = repeatRate; } } int JoyKeyRepeatHelper::getKeyRepeatRate() { return keyRepeatRate; } AntiMicroX-antimicrox-2888bf6/src/joykeyrepeathelper.h000066400000000000000000000026641377703515000231460ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYKEYREPEATHELPER_H #define JOYKEYREPEATHELPER_H #include #include class JoyButtonSlot; class JoyKeyRepeatHelper : public QObject { Q_OBJECT public: explicit JoyKeyRepeatHelper(QObject *parent = nullptr); QTimer *getRepeatTimer(); void setLastActiveKey(JoyButtonSlot *slot); JoyButtonSlot *getLastActiveKey(); void setKeyRepeatRate(int repeatRate); int getKeyRepeatRate(); private slots: void repeatKeysEvent(); protected: QTimer keyRepeatTimer; JoyButtonSlot *lastActiveKey; int keyRepeatDelay; int keyRepeatRate; }; #endif // JOYKEYREPEATHELPER_H AntiMicroX-antimicrox-2888bf6/src/joystick.cpp000066400000000000000000000116241377703515000214210ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joystick.h" #include "antimicrosettings.h" #include "globalvariables.h" #include "messagehandler.h" #include #include #include #include #include Joystick::Joystick(SDL_Joystick *joyhandle, int deviceIndex, AntiMicroSettings *settings, QObject *parent) : InputDevice(joyhandle, deviceIndex, settings, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_joyhandle = joyhandle; controller = SDL_GameControllerOpen(deviceIndex); joystickID = SDL_JoystickInstanceID(joyhandle); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { SetJoystick *setstick = new SetJoystick(this, i, this); getJoystick_sets().insert(i, setstick); enableSetConnections(setstick); } } QString Joystick::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::Joystick::xmlName; } QString Joystick::getName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return QString(tr("Joystick")).append(" ").append(QString::number(getRealJoyNumber())); } QString Joystick::getSDLName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (m_joyhandle != nullptr) { temp = SDL_JoystickName(m_joyhandle); } return temp; } QString Joystick::getGUIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); SDL_JoystickGUID tempGUID = SDL_JoystickGetGUID(m_joyhandle); char guidString[65] = {'0'}; SDL_JoystickGetGUIDString(tempGUID, guidString, sizeof(guidString)); temp = QString(guidString); // Not available on SDL 1.2. Return empty string in that case. return temp; } QString Joystick::getVendorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { Uint16 tempVendor = SDL_GameControllerGetVendor(controller); char buffer[50]; sprintf(buffer, "%u", tempVendor); temp = QString(buffer); } return temp; } QString Joystick::getProductIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { Uint16 tempProduct = SDL_GameControllerGetProduct(controller); char buffer[50]; sprintf(buffer, "%u", tempProduct); temp = QString(buffer); } return temp; } QString Joystick::getProductVersion() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (controller != nullptr) { Uint16 tempProductVersion = SDL_GameControllerGetProductVersion(controller); char buffer[50]; sprintf(buffer, "%u", tempProductVersion); temp = QString(buffer); } return temp; } QString Joystick::getUniqueIDString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return (getGUIDString() + getVendorString() + getProductIDString()); } void Joystick::closeSDLDevice() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((m_joyhandle != nullptr) && SDL_JoystickGetAttached(m_joyhandle)) { SDL_JoystickClose(m_joyhandle); } } int Joystick::getNumberRawButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); int numbuttons = SDL_JoystickNumButtons(m_joyhandle); return numbuttons; } int Joystick::getNumberRawAxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); int numaxes = SDL_JoystickNumAxes(m_joyhandle); return numaxes; } int Joystick::getNumberRawHats() { qInstallMessageHandler(MessageHandler::myMessageOutput); int numhats = SDL_JoystickNumHats(m_joyhandle); return numhats; } void Joystick::setCounterUniques(int counter) { counterUniques = counter; } SDL_JoystickID Joystick::getSDLJoystickID() { qInstallMessageHandler(MessageHandler::myMessageOutput); return joystickID; } SDL_Joystick *Joystick::getJoyhandle() const { return m_joyhandle; } AntiMicroX-antimicrox-2888bf6/src/joystick.h000066400000000000000000000040001377703515000210540ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYSTICK_H #define JOYSTICK_H #include "inputdevice.h" #include class AntiMicroSettings; class Joystick : public InputDevice { Q_OBJECT public: explicit Joystick(SDL_Joystick *joyhandle, int deviceIndex, AntiMicroSettings *settings, QObject *parent = 0); virtual QString getName() override; virtual QString getSDLName() override; virtual QString getGUIDString() override; // GUID available on SDL 2. virtual QString getUniqueIDString() override; virtual QString getVendorString() override; virtual QString getProductIDString() override; virtual QString getProductVersion() override; virtual void closeSDLDevice() override; virtual SDL_JoystickID getSDLJoystickID() override; virtual int getNumberRawButtons() override; virtual int getNumberRawAxes() override; virtual int getNumberRawHats() override; void setCounterUniques(int counter) override; SDL_Joystick *getJoyhandle() const; virtual QString getXmlName() override; private: SDL_Joystick *m_joyhandle; SDL_GameController *controller; SDL_JoystickID joystickID; int counterUniques; }; Q_DECLARE_METATYPE(Joystick *) #endif // JOYSTICK_H AntiMicroX-antimicrox-2888bf6/src/joystickstatuswindow.cpp000066400000000000000000000173171377703515000241220ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joystickstatuswindow.h" #include "ui_joystickstatuswindow.h" #include "common.h" #include "globalvariables.h" #include "inputdevice.h" #include "joybuttonstatusbox.h" #include "joybuttontypes/joydpadbutton.h" #include "joydpad.h" #include "messagehandler.h" #include #include #include #include #include #include #include #include JoystickStatusWindow::JoystickStatusWindow(InputDevice *joystick, QWidget *parent) : QDialog(parent) , ui(new Ui::JoystickStatusWindow) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->joystick = joystick; PadderCommon::inputDaemonMutex.lock(); setWindowTitle(tr("%1 (#%2) Properties").arg(joystick->getSDLName()).arg(joystick->getRealJoyNumber())); SDL_JoystickPowerLevel powerLevel = SDL_JoystickCurrentPowerLevel(joystick->getJoyHandle()); switch (powerLevel) { case SDL_JOYSTICK_POWER_EMPTY: ui->batteryValueLabel->setText("Empty"); break; case SDL_JOYSTICK_POWER_LOW: ui->batteryValueLabel->setText("Low"); break; case SDL_JOYSTICK_POWER_MEDIUM: ui->batteryValueLabel->setText("Medium"); break; case SDL_JOYSTICK_POWER_FULL: ui->batteryValueLabel->setText("Full"); break; default: ui->batteryLabel->hide(); ui->batteryValueLabel->hide(); break; } ui->joystickNameLabel->setText(joystick->getSDLName()); ui->joystickNumberLabel->setText(QString::number(joystick->getRealJoyNumber())); ui->joystickAxesLabel->setText(QString::number(joystick->getNumberRawAxes())); ui->joystickButtonsLabel->setText(QString::number(joystick->getNumberRawButtons())); ui->joystickHatsLabel->setText(QString::number(joystick->getNumberRawHats())); joystick->getActiveSetJoystick()->setIgnoreEventState(true); joystick->getActiveSetJoystick()->release(); joystick->resetButtonDownCount(); QVBoxLayout *axesBox = new QVBoxLayout(); axesBox->setSpacing(4); for (int i = 0; i < joystick->getNumberAxes(); i++) { JoyAxis *axis = joystick->getActiveSetJoystick()->getJoyAxis(i); if (axis != nullptr) { QHBoxLayout *hbox = new QHBoxLayout(); QLabel *axisLabel = new QLabel(); axisLabel->setText(tr("Axis %1").arg(axis->getRealJoyIndex())); QProgressBar *axisBar = new QProgressBar(); axisBar->setMinimum(GlobalVariables::JoyAxis::AXISMIN); axisBar->setMaximum(GlobalVariables::JoyAxis::AXISMAX); axisBar->setFormat("%v"); axisBar->setValue(axis->getCurrentRawValue()); hbox->addWidget(axisLabel); hbox->addWidget(axisBar); hbox->addSpacing(10); axesBox->addLayout(hbox); connect(axis, &JoyAxis::moved, axisBar, &QProgressBar::setValue); } } ui->axesScrollArea->setLayout(axesBox); QGridLayout *buttonsGrid = new QGridLayout(); buttonsGrid->setHorizontalSpacing(10); buttonsGrid->setVerticalSpacing(10); int currentRow = 0; int currentColumn = 0; for (int i = 0; i < joystick->getNumberButtons(); i++) { JoyButton *button = joystick->getActiveSetJoystick()->getJoyButton(i); if (button != nullptr) { JoyButtonStatusBox *statusbox = new JoyButtonStatusBox(button); statusbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); buttonsGrid->addWidget(statusbox, currentRow, currentColumn); currentColumn++; if (currentColumn >= 6) { currentRow++; currentColumn = 0; } } } ui->buttonsScrollArea->setLayout(buttonsGrid); QVBoxLayout *hatsBox = new QVBoxLayout(); hatsBox->setSpacing(4); for (int i = 0; i < joystick->getNumberHats(); i++) { JoyDPad *dpad = joystick->getActiveSetJoystick()->getJoyDPad(i); if (dpad != nullptr) { QHBoxLayout *hbox = new QHBoxLayout(); QLabel *dpadLabel = new QLabel(); dpadLabel->setText(tr("Hat %1").arg(dpad->getRealJoyNumber())); QProgressBar *dpadBar = new QProgressBar(); dpadBar->setMinimum(JoyDPadButton::DpadCentered); dpadBar->setMaximum(JoyDPadButton::DpadLeftDown); dpadBar->setFormat("%v"); dpadBar->setValue(dpad->getCurrentDirection()); hbox->addWidget(dpadLabel); hbox->addWidget(dpadBar); hbox->addSpacing(10); hatsBox->addLayout(hbox); connect(dpad, &JoyDPad::active, dpadBar, &QProgressBar::setValue); connect(dpad, &JoyDPad::released, dpadBar, &QProgressBar::setValue); } } hatsBox->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::Preferred, QSizePolicy::Fixed)); if (ui->hatsGroupBox->layout()) { delete ui->hatsGroupBox->layout(); } ui->hatsGroupBox->setLayout(hatsBox); // QString guidString = joystick->getGUIDString(); // if (!guidString.isEmpty()) // { // ui->guidHeaderLabel->show(); // ui->guidLabel->setText(guidString); // ui->guidLabel->show(); // } // else // { // ui->guidHeaderLabel->hide(); // ui->guidLabel->hide(); // } QString uniqueString = joystick->getUniqueIDString(); if (!uniqueString.isEmpty()) { ui->guidHeaderLabel->show(); ui->guidLabel->setText(uniqueString); ui->guidLabel->show(); } else { ui->guidHeaderLabel->hide(); ui->guidLabel->hide(); } QString usingGameController = tr("No"); if (joystick->isGameController()) { usingGameController = tr("Yes"); } ui->sdlGameControllerLabel->setText(usingGameController); PadderCommon::inputDaemonMutex.unlock(); connect(joystick, &InputDevice::destroyed, this, &JoystickStatusWindow::obliterate); connect(this, &JoystickStatusWindow::finished, this, &JoystickStatusWindow::restoreButtonStates); } JoystickStatusWindow::~JoystickStatusWindow() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void JoystickStatusWindow::restoreButtonStates(int code) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (code == QDialogButtonBox::AcceptRole) { PadderCommon::inputDaemonMutex.lock(); joystick->getActiveSetJoystick()->setIgnoreEventState(false); joystick->getActiveSetJoystick()->release(); PadderCommon::inputDaemonMutex.unlock(); } } void JoystickStatusWindow::obliterate() { qInstallMessageHandler(MessageHandler::myMessageOutput); this->done(QDialogButtonBox::DestructiveRole); } InputDevice *JoystickStatusWindow::getJoystick() const { return joystick; } AntiMicroX-antimicrox-2888bf6/src/joystickstatuswindow.h000066400000000000000000000025671377703515000235700ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYSTICKSTATUSWINDOW_H #define JOYSTICKSTATUSWINDOW_H #include class InputDevice; class QWidget; namespace Ui { class JoystickStatusWindow; } class JoystickStatusWindow : public QDialog { Q_OBJECT public: explicit JoystickStatusWindow(InputDevice *joystick, QWidget *parent = nullptr); ~JoystickStatusWindow(); InputDevice *getJoystick() const; private: Ui::JoystickStatusWindow *ui; InputDevice *joystick; private slots: void restoreButtonStates(int code); void obliterate(); }; #endif // JOYSTICKSTATUSWINDOW_H AntiMicroX-antimicrox-2888bf6/src/joystickstatuswindow.ui000066400000000000000000000346601377703515000237550ustar00rootroot00000000000000 JoystickStatusWindow Qt::ApplicationModal 0 0 580 480 580 440 Properties JoyButtonStatusBox { border: 1px solid rgb(0, 0, 0); } JoyButtonStatusBox[isflashing="true"] { background-color: rgb(0, 0, 255); color: rgb(205, 197, 191); } true 200 0 Details 75 true Name: %1 10 75 true Number: %1 10 75 true Axes: %1 10 75 true Buttons: %1 10 75 true Hats: %1 10 0 0 0 0 0 20 75 true Battery: 0 14 Unknown true 75 true GUID: %1 true 10 Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse true 75 true Game Controller: %1 true 10 Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse Axes 4 4 4 4 QFrame::NoFrame QFrame::Sunken 1 true 0 0 346 120 Qt::Vertical QSizePolicy::Fixed 20 10 Buttons 4 4 4 4 false QFrame::NoFrame true 0 0 346 120 Qt::Vertical QSizePolicy::Fixed 20 10 Hats 4 4 4 14 Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() JoystickStatusWindow accept() 248 254 157 274 buttonBox rejected() JoystickStatusWindow reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/joytabwidget.cpp000066400000000000000000002561431377703515000222650ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joytabwidget.h" #include "advancestickassignmentdialog.h" #include "antimicrosettings.h" #include "axiseditdialog.h" #include "buttoneditdialog.h" #include "common.h" #include "dpadpushbuttongroup.h" #include "extraprofilesettingsdialog.h" #include "globalvariables.h" #include "inputdevice.h" #include "joyaxiswidget.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joybuttontypes/joydpadbutton.h" #include "joybuttonwidget.h" #include "joycontrolstick.h" #include "joydpad.h" #include "joystick.h" #include "messagehandler.h" #include "quicksetdialog.h" #include "setnamesdialog.h" #include "stickpushbuttongroup.h" #include "vdpad.h" #include "xmlconfigreader.h" #include "xmlconfigwriter.h" #include "gamecontroller/gamecontroller.h" #include "gamecontrollermappingdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include bool JoyTabWidget::changedNotSaved = false; JoyTabWidget::JoyTabWidget(InputDevice *joystick, AntiMicroSettings *settings, QWidget *parent) : QWidget(parent) , tabHelper(joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_joystick = joystick; m_settings = settings; tabHelper.moveToThread(joystick->thread()); comboBoxIndex = 0; hideEmptyButtons = false; verticalLayout = new QVBoxLayout(this); verticalLayout->setContentsMargins(4, 4, 4, 4); configHorizontalLayout = new QHBoxLayout(); configBox = new QComboBox(this); configBox->addItem(tr(""), ""); QStringList themesPaths = QIcon::themeSearchPaths(); for (int i = 0; i < themesPaths.count(); i++) { qDebug() << "themePath: " << themesPaths.at(i); } configBox->setObjectName(QString::fromUtf8("configBox")); configBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); configHorizontalLayout->addWidget(configBox); spacer1 = new QSpacerItem(30, 20, QSizePolicy::Fixed, QSizePolicy::Fixed); configHorizontalLayout->addItem(spacer1); removeButton = new QPushButton(tr("Remove"), this); removeButton->setObjectName(QString::fromUtf8("removeButton")); removeButton->setToolTip(tr("Remove configuration from recent list.")); removeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); removeButton->setIcon(PadderCommon::loadIcon("user-trash", ":/icons/actions/edit_clear_list.png")); configHorizontalLayout->addWidget(removeButton); loadButton = new QPushButton(tr("Load"), this); loadButton->setObjectName(QString::fromUtf8("loadButton")); loadButton->setToolTip(tr("Load configuration file.")); loadButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); loadButton->setIcon(PadderCommon::loadIcon("document-open", ":/icons/actions/document_open.png")); configHorizontalLayout->addWidget(loadButton); saveButton = new QPushButton(tr("Save"), this); saveButton->setObjectName(QString::fromUtf8("saveButton")); saveButton->setToolTip(tr("Save changes to configuration file.")); saveButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); saveButton->setIcon(PadderCommon::loadIcon("document-save", ":/icons/actions/document_save.png")); configHorizontalLayout->addWidget(saveButton); saveAsButton = new QPushButton(tr("Save As"), this); saveAsButton->setObjectName(QString::fromUtf8("saveAsButton")); saveAsButton->setToolTip(tr("Save changes to a new configuration file.")); saveAsButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); saveAsButton->setIcon(PadderCommon::loadIcon("document-save-as", ":/icons/actions/document_save_as.png")); configHorizontalLayout->addWidget(saveAsButton); verticalLayout->addLayout(configHorizontalLayout); verticalLayout->setStretchFactor(configHorizontalLayout, 1); spacer2 = new QSpacerItem(20, 5, QSizePolicy::Fixed, QSizePolicy::Fixed); verticalLayout->addItem(spacer2); verticalSpacer_2 = new QSpacerItem(20, 5, QSizePolicy::Minimum, QSizePolicy::Fixed); verticalLayout->addItem(verticalSpacer_2); stackedWidget_2 = new QStackedWidget(this); stackedWidget_2->setObjectName(QString::fromUtf8("stackedWidget_2")); page = new QWidget(); page->setObjectName(QString::fromUtf8("page")); QVBoxLayout *tempVBoxLayout = new QVBoxLayout(page); QScrollArea *scrollArea = new QScrollArea(); scrollArea->setObjectName(QString::fromUtf8("scrollArea1")); QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); scrollArea->setSizePolicy(sizePolicy); scrollArea->setWidgetResizable(true); QWidget *scrollAreaWidgetContents1 = new QWidget(); scrollAreaWidgetContents1->setObjectName(QString::fromUtf8("scrollAreaWidgetContents1")); gridLayout = new QGridLayout(scrollAreaWidgetContents1); gridLayout->setSpacing(4); gridLayout->setObjectName(QString::fromUtf8("gridLayout")); scrollArea->setWidget(scrollAreaWidgetContents1); tempVBoxLayout->addWidget(scrollArea); stackedWidget_2->addWidget(page); page_2 = new QWidget(); page_2->setObjectName(QString::fromUtf8("page_2")); tempVBoxLayout = new QVBoxLayout(page_2); QScrollArea *scrollArea2 = new QScrollArea(); scrollArea2->setObjectName(QString::fromUtf8("scrollArea2")); scrollArea2->setSizePolicy(sizePolicy); scrollArea2->setWidgetResizable(true); QWidget *scrollAreaWidgetContents2 = new QWidget(); scrollAreaWidgetContents2->setObjectName(QString::fromUtf8("scrollAreaWidgetContents2")); gridLayout2 = new QGridLayout(scrollAreaWidgetContents2); gridLayout2->setSpacing(4); gridLayout2->setObjectName(QString::fromUtf8("gridLayout2")); scrollArea2->setWidget(scrollAreaWidgetContents2); tempVBoxLayout->addWidget(scrollArea2); stackedWidget_2->addWidget(page_2); page_3 = new QWidget(); page_3->setObjectName(QString::fromUtf8("page_3")); tempVBoxLayout = new QVBoxLayout(page_3); QScrollArea *scrollArea3 = new QScrollArea(); scrollArea3->setObjectName(QString::fromUtf8("scrollArea3")); scrollArea3->setSizePolicy(sizePolicy); scrollArea3->setWidgetResizable(true); QWidget *scrollAreaWidgetContents3 = new QWidget(); scrollAreaWidgetContents3->setObjectName(QString::fromUtf8("scrollAreaWidgetContents3")); gridLayout3 = new QGridLayout(scrollAreaWidgetContents3); gridLayout3->setSpacing(4); gridLayout3->setObjectName(QString::fromUtf8("gridLayout3")); scrollArea3->setWidget(scrollAreaWidgetContents3); tempVBoxLayout->addWidget(scrollArea3); stackedWidget_2->addWidget(page_3); page_4 = new QWidget(); page_4->setObjectName(QString::fromUtf8("page_4")); tempVBoxLayout = new QVBoxLayout(page_4); QScrollArea *scrollArea4 = new QScrollArea(); scrollArea4->setObjectName(QString::fromUtf8("scrollArea4")); scrollArea4->setSizePolicy(sizePolicy); scrollArea4->setWidgetResizable(true); QWidget *scrollAreaWidgetContents4 = new QWidget(); scrollAreaWidgetContents4->setObjectName(QString::fromUtf8("scrollAreaWidgetContents4")); gridLayout4 = new QGridLayout(scrollAreaWidgetContents4); gridLayout4->setSpacing(4); gridLayout4->setObjectName(QString::fromUtf8("gridLayout4")); scrollArea4->setWidget(scrollAreaWidgetContents4); tempVBoxLayout->addWidget(scrollArea4); stackedWidget_2->addWidget(page_4); page_5 = new QWidget(); page_5->setObjectName(QString::fromUtf8("page_5")); tempVBoxLayout = new QVBoxLayout(page_5); QScrollArea *scrollArea5 = new QScrollArea(); scrollArea5->setObjectName(QString::fromUtf8("scrollArea5")); scrollArea5->setSizePolicy(sizePolicy); scrollArea5->setWidgetResizable(true); QWidget *scrollAreaWidgetContents5 = new QWidget(); scrollAreaWidgetContents5->setObjectName(QString::fromUtf8("scrollAreaWidgetContents5")); gridLayout5 = new QGridLayout(scrollAreaWidgetContents5); gridLayout5->setSpacing(4); gridLayout5->setObjectName(QString::fromUtf8("gridLayout5")); scrollArea5->setWidget(scrollAreaWidgetContents5); tempVBoxLayout->addWidget(scrollArea5); stackedWidget_2->addWidget(page_5); page_6 = new QWidget(); page_6->setObjectName(QString::fromUtf8("page_6")); tempVBoxLayout = new QVBoxLayout(page_6); QScrollArea *scrollArea6 = new QScrollArea(); scrollArea6->setObjectName(QString::fromUtf8("scrollArea6")); scrollArea6->setSizePolicy(sizePolicy); scrollArea6->setWidgetResizable(true); QWidget *scrollAreaWidgetContents6 = new QWidget(); scrollAreaWidgetContents6->setObjectName(QString::fromUtf8("scrollAreaWidgetContents6")); gridLayout6 = new QGridLayout(scrollAreaWidgetContents6); gridLayout6->setSpacing(4); gridLayout6->setObjectName(QString::fromUtf8("gridLayout6")); scrollArea6->setWidget(scrollAreaWidgetContents6); tempVBoxLayout->addWidget(scrollArea6); stackedWidget_2->addWidget(page_6); page_7 = new QWidget(); page_7->setObjectName(QString::fromUtf8("page_7")); tempVBoxLayout = new QVBoxLayout(page_7); QScrollArea *scrollArea7 = new QScrollArea(); scrollArea7->setObjectName(QString::fromUtf8("scrollArea7")); scrollArea7->setSizePolicy(sizePolicy); scrollArea7->setWidgetResizable(true); QWidget *scrollAreaWidgetContents7 = new QWidget(); scrollAreaWidgetContents7->setObjectName(QString::fromUtf8("scrollAreaWidgetContents7")); gridLayout7 = new QGridLayout(scrollAreaWidgetContents7); gridLayout7->setSpacing(4); gridLayout7->setObjectName(QString::fromUtf8("gridLayout7")); scrollArea7->setWidget(scrollAreaWidgetContents7); tempVBoxLayout->addWidget(scrollArea7); stackedWidget_2->addWidget(page_7); page_8 = new QWidget(); page_8->setObjectName(QString::fromUtf8("page_8")); tempVBoxLayout = new QVBoxLayout(page_8); QScrollArea *scrollArea8 = new QScrollArea(); scrollArea8->setObjectName(QString::fromUtf8("scrollArea8")); scrollArea8->setSizePolicy(sizePolicy); scrollArea8->setWidgetResizable(true); QWidget *scrollAreaWidgetContents8 = new QWidget(); scrollAreaWidgetContents8->setObjectName(QString::fromUtf8("scrollAreaWidgetContents8")); gridLayout8 = new QGridLayout(scrollAreaWidgetContents8); gridLayout8->setSpacing(4); gridLayout8->setObjectName(QString::fromUtf8("gridLayout8")); scrollArea8->setWidget(scrollAreaWidgetContents8); tempVBoxLayout->addWidget(scrollArea8); stackedWidget_2->addWidget(page_8); verticalLayout->addWidget(stackedWidget_2); verticalSpacer_3 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Fixed); verticalLayout->addItem(verticalSpacer_3); horizontalLayout_2 = new QHBoxLayout(); horizontalLayout_2->setSpacing(6); horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2")); setsMenuButton = new QPushButton(tr("Sets"), this); QMenu *setMenu = new QMenu(setsMenuButton); copySetMenu = new QMenu(tr("Copy from Set"), setMenu); QAction *setSettingsAction = new QAction(tr("Settings"), setMenu); connect(setSettingsAction, &QAction::triggered, this, &JoyTabWidget::showSetNamesDialog); setMenu->addAction(setSettingsAction); setMenu->addMenu(copySetMenu); setMenu->addSeparator(); refreshCopySetActions(); setAction1 = new QAction(tr("Set 1"), setMenu); connect(setAction1, &QAction::triggered, this, &JoyTabWidget::changeSetOne); setMenu->addAction(setAction1); setAction2 = new QAction(tr("Set 2"), setMenu); connect(setAction2, &QAction::triggered, this, &JoyTabWidget::changeSetTwo); setMenu->addAction(setAction2); setAction3 = new QAction(tr("Set 3"), setMenu); connect(setAction3, &QAction::triggered, this, &JoyTabWidget::changeSetThree); setMenu->addAction(setAction3); setAction4 = new QAction(tr("Set 4"), setMenu); connect(setAction4, &QAction::triggered, this, &JoyTabWidget::changeSetFour); setMenu->addAction(setAction4); setAction5 = new QAction(tr("Set 5"), setMenu); connect(setAction5, &QAction::triggered, this, &JoyTabWidget::changeSetFive); setMenu->addAction(setAction5); setAction6 = new QAction(tr("Set 6"), setMenu); connect(setAction6, &QAction::triggered, this, &JoyTabWidget::changeSetSix); setMenu->addAction(setAction6); setAction7 = new QAction(tr("Set 7"), setMenu); connect(setAction7, &QAction::triggered, this, &JoyTabWidget::changeSetSeven); setMenu->addAction(setAction7); setAction8 = new QAction(tr("Set 8"), setMenu); connect(setAction8, &QAction::triggered, this, &JoyTabWidget::changeSetEight); setMenu->addAction(setAction8); setsMenuButton->setMenu(setMenu); horizontalLayout_2->addWidget(setsMenuButton); setPushButton1 = new QPushButton("1", this); setPushButton1->setObjectName(QString::fromUtf8("setPushButton1")); setPushButton1->setProperty("setActive", true); horizontalLayout_2->addWidget(setPushButton1); setPushButton2 = new QPushButton("2", this); setPushButton2->setObjectName(QString::fromUtf8("setPushButton2")); setPushButton2->setProperty("setActive", false); horizontalLayout_2->addWidget(setPushButton2); setPushButton3 = new QPushButton("3", this); setPushButton3->setObjectName(QString::fromUtf8("setPushButton3")); setPushButton3->setProperty("setActive", false); horizontalLayout_2->addWidget(setPushButton3); setPushButton4 = new QPushButton("4", this); setPushButton4->setObjectName(QString::fromUtf8("setPushButton4")); setPushButton4->setProperty("setActive", false); horizontalLayout_2->addWidget(setPushButton4); setPushButton5 = new QPushButton("5", this); setPushButton5->setObjectName(QString::fromUtf8("setPushButton5")); setPushButton5->setProperty("setActive", false); horizontalLayout_2->addWidget(setPushButton5); setPushButton6 = new QPushButton("6", this); setPushButton6->setObjectName(QString::fromUtf8("setPushButton6")); setPushButton6->setProperty("setActive", false); horizontalLayout_2->addWidget(setPushButton6); setPushButton7 = new QPushButton("7", this); setPushButton7->setObjectName(QString::fromUtf8("setPushButton7")); setPushButton7->setProperty("setActive", false); horizontalLayout_2->addWidget(setPushButton7); setPushButton8 = new QPushButton("8", this); setPushButton8->setObjectName(QString::fromUtf8("setPushButton8")); setPushButton8->setProperty("setActive", false); horizontalLayout_2->addWidget(setPushButton8); refreshSetButtons(); verticalLayout->addLayout(horizontalLayout_2); spacer3 = new QSpacerItem(20, 5, QSizePolicy::Fixed, QSizePolicy::Fixed); verticalLayout->addItem(spacer3); horizontalLayout_3 = new QHBoxLayout(); horizontalLayout_3->setSpacing(6); horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3")); stickAssignPushButton = new QPushButton(tr("Stick/Pad Assign"), this); stickAssignPushButton->setObjectName(QString::fromUtf8("stickAssignPushButton")); QIcon icon7( QIcon::fromTheme(QString::fromUtf8("games_config_options"), QIcon(":/icons/actions/games_config_options.png"))); stickAssignPushButton->setIcon(icon7); horizontalLayout_3->addWidget(stickAssignPushButton); gameControllerMappingPushButton = new QPushButton(tr("Controller Mapping"), this); gameControllerMappingPushButton->setObjectName(QString::fromUtf8("gameControllerMappingPushButton")); gameControllerMappingPushButton->setIcon( QIcon::fromTheme(QString::fromUtf8("games_config_options"), QIcon(":/icons/actions/games_config_options.png"))); gameControllerMappingPushButton->setEnabled(false); gameControllerMappingPushButton->setVisible(false); horizontalLayout_3->addWidget(gameControllerMappingPushButton); quickSetPushButton = new QPushButton(tr("Quick Set"), this); quickSetPushButton->setObjectName(QString::fromUtf8("quickSetPushButton")); horizontalLayout_3->addWidget(quickSetPushButton); QSpacerItem *horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout_3->addItem(horizontalSpacer_2); namesPushButton = new QPushButton(tr("Names"), this); namesPushButton->setObjectName(QString::fromUtf8("namesPushButton")); namesPushButton->setToolTip(tr("Toggle button name displaying.")); namesPushButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); namesPushButton->setIcon(QIcon::fromTheme(QString::fromUtf8("text_field"), QIcon(":/icons/actions/text_field.png"))); horizontalLayout_3->addWidget(namesPushButton); delayButton = new QPushButton(tr("Pref"), this); delayButton->setObjectName(QString::fromUtf8("delayButton")); delayButton->setToolTip(tr("Change global profile settings.")); delayButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); horizontalLayout_3->addWidget(delayButton); resetButton = new QPushButton(tr("Reset"), this); resetButton->setObjectName(QString::fromUtf8("resetButton")); resetButton->setToolTip(tr("Revert changes to the configuration. Reload configuration file.")); resetButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); resetButton->setIcon(PadderCommon::loadIcon("document-revert", ":/icons/actions/document_revert.png")); horizontalLayout_3->addWidget(resetButton); verticalLayout->addLayout(horizontalLayout_3); displayingNames = false; stickAssignPushButton->setEnabled(false); stickAssignPushButton->setVisible(false); gameControllerMappingPushButton->setEnabled(true); gameControllerMappingPushButton->setVisible(true); checkHideEmptyOption(); connect(loadButton, &QPushButton::clicked, this, &JoyTabWidget::openConfigFileDialog); connect(saveButton, &QPushButton::clicked, this, &JoyTabWidget::saveConfigFile); connect(resetButton, &QPushButton::clicked, this, &JoyTabWidget::resetJoystick); connect(namesPushButton, &QPushButton::clicked, this, &JoyTabWidget::toggleNames); connect(saveAsButton, &QPushButton::clicked, this, &JoyTabWidget::saveAsConfig); connect(delayButton, &QPushButton::clicked, this, &JoyTabWidget::showKeyDelayDialog); connect(removeButton, &QPushButton::clicked, this, &JoyTabWidget::removeConfig); connect(setPushButton1, &QPushButton::clicked, this, &JoyTabWidget::changeSetOne); connect(setPushButton2, &QPushButton::clicked, this, &JoyTabWidget::changeSetTwo); connect(setPushButton3, &QPushButton::clicked, this, &JoyTabWidget::changeSetThree); connect(setPushButton4, &QPushButton::clicked, this, &JoyTabWidget::changeSetFour); connect(setPushButton5, &QPushButton::clicked, this, &JoyTabWidget::changeSetFive); connect(setPushButton6, &QPushButton::clicked, this, &JoyTabWidget::changeSetSix); connect(setPushButton7, &QPushButton::clicked, this, &JoyTabWidget::changeSetSeven); connect(setPushButton8, &QPushButton::clicked, this, &JoyTabWidget::changeSetEight); connect(stickAssignPushButton, &QPushButton::clicked, this, &JoyTabWidget::showStickAssignmentDialog); connect(gameControllerMappingPushButton, &QPushButton::clicked, this, &JoyTabWidget::openGameControllerMappingWindow); connect(quickSetPushButton, &QPushButton::clicked, this, &JoyTabWidget::showQuickSetDialog); connect(this, &JoyTabWidget::joystickConfigChanged, this, &JoyTabWidget::refreshSetButtons); connect(this, &JoyTabWidget::joystickConfigChanged, this, &JoyTabWidget::refreshCopySetActions); connect(joystick, &InputDevice::profileUpdated, this, &JoyTabWidget::displayProfileEditNotification); connect(joystick, &InputDevice::requestProfileLoad, this, &JoyTabWidget::loadConfigFile, Qt::QueuedConnection); reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); } bool JoyTabWidget::isKeypadUnlocked() { if (m_settings == nullptr) return false; return m_settings->value("AttachNumKeypad", false).toBool(); } void JoyTabWidget::openConfigFileDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); m_settings->getLock()->lock(); int numberRecentProfiles = m_settings->value("NumberRecentProfiles", DEFAULTNUMBERPROFILES).toInt(); QString lookupDir = PadderCommon::preferredProfileDir(m_settings); QString filename = QFileDialog::getOpenFileName(this, tr("Open Config"), lookupDir, tr("Config Files (*.amgp *.xml)")); m_settings->getLock()->unlock(); if (!filename.isNull() && !filename.isEmpty()) { QFileInfo fileinfo(filename); int searchIndex = configBox->findData(fileinfo.absoluteFilePath()); if (searchIndex == -1) { if ((numberRecentProfiles > 0) && (configBox->count() == (numberRecentProfiles + 1))) { configBox->removeItem(numberRecentProfiles); } configBox->insertItem(1, PadderCommon::getProfileName(fileinfo), fileinfo.absoluteFilePath()); configBox->setCurrentIndex(1); saveDeviceSettings(); emit joystickConfigChanged(m_joystick->getJoyNumber()); } else { configBox->setCurrentIndex(searchIndex); saveDeviceSettings(); emit joystickConfigChanged(m_joystick->getJoyNumber()); } QString outputFilename = fileinfo.absoluteDir().absolutePath(); m_settings->getLock()->lock(); m_settings->setValue("LastProfileDir", outputFilename); m_settings->sync(); m_settings->getLock()->unlock(); } } /** * @brief Create and render all push buttons corresponding to joystick * controls for all sets. */ void JoyTabWidget::fillButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); m_joystick->establishPropertyUpdatedConnection(); connect(m_joystick, &InputDevice::setChangeActivated, this, &JoyTabWidget::changeCurrentSet, Qt::QueuedConnection); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { SetJoystick *currentSet = m_joystick->getSetJoystick(i); fillSetButtons(currentSet); } refreshCopySetActions(); } void JoyTabWidget::showButtonDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonWidget *buttonWidget = qobject_cast(sender()); // static_cast JoyButton *button = buttonWidget->getJoyButton(); for (auto eachAssigned : *button->getAssignedSlots()) { qDebug() << "eachAssigned slot mode: " << eachAssigned->getSlotMode(); if (eachAssigned->getSlotMode() == 15) { qDebug() << "text data is: " << eachAssigned->getTextData(); } } ButtonEditDialog *dialog = new ButtonEditDialog(button, m_joystick, isKeypadUnlocked(), this); dialog->show(); } void JoyTabWidget::showAxisDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisWidget *axisWidget = qobject_cast(sender()); // static_cast JoyAxis *axis = axisWidget->getAxis(); axisDialog = new AxisEditDialog(axis, isKeypadUnlocked(), this); axisDialog->show(); } void JoyTabWidget::saveConfigFile() { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = configBox->currentIndex(); m_settings->getLock()->lock(); int numberRecentProfiles = m_settings->value("NumberRecentProfiles", DEFAULTNUMBERPROFILES).toInt(); QString filename = QString(); if (index == 0) { QString lookupDir = PadderCommon::preferredProfileDir(m_settings); m_settings->getLock()->unlock(); QString tempfilename = QFileDialog::getSaveFileName(this, tr("Save Config"), lookupDir, tr("Config File (*.%1.amgp)").arg(m_joystick->getXmlName())); if (!tempfilename.isEmpty()) { filename = tempfilename; QFileInfo fileinfo(filename); QString deviceTypeName = m_joystick->getXmlName(); QString fileSuffix = deviceTypeName.append(".amgp"); if ((fileinfo.suffix() != "xml") && (fileinfo.suffix() != "amgp")) { filename = filename.append(".").append(fileSuffix); } } } else { m_settings->getLock()->unlock(); filename = configBox->itemData(index).toString(); } if (!filename.isEmpty()) { QFileInfo fileinfo(filename); QMetaObject::invokeMethod(&tabHelper, "writeConfigFile", Qt::BlockingQueuedConnection, Q_ARG(QString, fileinfo.absoluteFilePath())); XMLConfigWriter *writer = tabHelper.getWriter(); if (writer->hasError() && this->window()->isEnabled()) { QMessageBox msg; msg.setStandardButtons(QMessageBox::Close); msg.setText(writer->getErrorString()); msg.setModal(true); msg.exec(); } else if (writer->hasError() && !this->window()->isEnabled()) { QTextStream error(stderr); error << writer->getErrorString() << endl; } else { int existingIndex = configBox->findData(fileinfo.absoluteFilePath()); if (existingIndex == -1) { if ((numberRecentProfiles > 0) && (configBox->count() == (numberRecentProfiles + 1))) { configBox->removeItem(numberRecentProfiles); } m_joystick->revertProfileEdited(); QString tempProfileName = PadderCommon::getProfileName(fileinfo); if (!m_joystick->getProfileName().isEmpty()) { oldProfileName = m_joystick->getProfileName(); tempProfileName = oldProfileName; } disconnectCheckUnsavedEvent(); disconnectMainComboBoxEvents(); configBox->insertItem(1, tempProfileName, fileinfo.absoluteFilePath()); reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); configBox->setCurrentIndex(1); saveDeviceSettings(true); emit joystickConfigChanged(m_joystick->getJoyNumber()); } else { m_joystick->revertProfileEdited(); if (!m_joystick->getProfileName().isEmpty()) { oldProfileName = m_joystick->getProfileName(); } configBox->setItemIcon(existingIndex, QIcon()); saveDeviceSettings(true); emit joystickConfigChanged(m_joystick->getJoyNumber()); } } } } void JoyTabWidget::resetJoystick() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msg; msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msg.setText(tr("Do you really want to reset buttons settings for joystick?")); int result = msg.exec(); if (result == QMessageBox::Yes) { int currentIndex = configBox->currentIndex(); if (currentIndex != 0) { removeCurrentButtons(); QMetaObject::invokeMethod(&tabHelper, "reInitDevice", Qt::BlockingQueuedConnection); fillButtons(); refreshSetButtons(); refreshCopySetActions(); XMLConfigReader *reader = tabHelper.getReader(); if (!reader->hasError()) { configBox->setItemIcon(currentIndex, QIcon()); QString tempProfileName = QString(); if (!m_joystick->getProfileName().isEmpty()) { tempProfileName = m_joystick->getProfileName(); configBox->setItemText(currentIndex, tempProfileName); } else { tempProfileName = oldProfileName; configBox->setItemText(currentIndex, oldProfileName); } oldProfileName = tempProfileName; } else if (reader->hasError() && this->window()->isEnabled()) { QMessageBox msg; msg.setStandardButtons(QMessageBox::Close); msg.setText(reader->getErrorString()); msg.setModal(true); msg.exec(); } else if (reader->hasError() && !this->window()->isEnabled()) { QTextStream error(stderr); error << reader->getErrorString() << endl; } displayProfileEditNotification(); } else { configBox->setItemText(0, tr("")); configBox->setItemIcon(0, QIcon()); removeCurrentButtons(); QMetaObject::invokeMethod(&tabHelper, "reInitDevice", Qt::BlockingQueuedConnection); fillButtons(); refreshSetButtons(); refreshCopySetActions(); } } } void JoyTabWidget::saveAsConfig() { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = configBox->currentIndex(); m_settings->getLock()->lock(); int numberRecentProfiles = m_settings->value("NumberRecentProfiles", DEFAULTNUMBERPROFILES).toInt(); QString filename = QString(); if (index == 0) { QString lookupDir = PadderCommon::preferredProfileDir(m_settings); m_settings->getLock()->unlock(); QString tempfilename = QFileDialog::getSaveFileName(this, tr("Save Config"), lookupDir, tr("Config File (*.%1.amgp)").arg(m_joystick->getXmlName())); if (!tempfilename.isEmpty()) { filename = tempfilename; } } else { m_settings->getLock()->unlock(); QString configPath = configBox->itemData(index).toString(); QFileInfo temp(configPath); QString tempfilename = QFileDialog::getSaveFileName(this, tr("Save Config"), temp.absoluteDir().absolutePath(), tr("Config File (*.%1.amgp)").arg(m_joystick->getXmlName())); if (!tempfilename.isEmpty()) { filename = tempfilename; } } if (!filename.isEmpty()) { QFileInfo fileinfo(filename); QString deviceTypeName = m_joystick->getXmlName(); QString fileSuffix = deviceTypeName.append(".amgp"); if ((fileinfo.suffix() != "xml") && (fileinfo.suffix() != "amgp")) { filename = filename.append(".").append(fileSuffix); } fileinfo.setFile(filename); QMetaObject::invokeMethod(&tabHelper, "writeConfigFile", Qt::BlockingQueuedConnection, Q_ARG(QString, fileinfo.absoluteFilePath())); XMLConfigWriter *writer = tabHelper.getWriter(); if (writer->hasError() && this->window()->isEnabled()) { QMessageBox msg; msg.setStandardButtons(QMessageBox::Close); msg.setText(writer->getErrorString()); msg.setModal(true); msg.exec(); } else if (writer->hasError() && !this->window()->isEnabled()) { QTextStream error(stderr); error << writer->getErrorString() << endl; } else { int existingIndex = configBox->findData(fileinfo.absoluteFilePath()); if (existingIndex == -1) { disconnectCheckUnsavedEvent(); disconnectMainComboBoxEvents(); if ((numberRecentProfiles > 0) && (configBox->count() == (numberRecentProfiles + 1))) { configBox->removeItem(numberRecentProfiles); } m_joystick->revertProfileEdited(); QString tempProfileName = PadderCommon::getProfileName(fileinfo); if (!m_joystick->getProfileName().isEmpty()) { oldProfileName = m_joystick->getProfileName(); tempProfileName = oldProfileName; } configBox->insertItem(1, tempProfileName, fileinfo.absoluteFilePath()); reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); configBox->setCurrentIndex(1); saveDeviceSettings(true); emit joystickConfigChanged(m_joystick->getJoyNumber()); } else { m_joystick->revertProfileEdited(); if (!m_joystick->getProfileName().isEmpty()) { oldProfileName = m_joystick->getProfileName(); } configBox->setItemIcon(existingIndex, QIcon()); saveDeviceSettings(true); emit joystickConfigChanged(m_joystick->getJoyNumber()); } } } } void JoyTabWidget::changeJoyConfig(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(m_joystick, &InputDevice::profileUpdated, this, &JoyTabWidget::displayProfileEditNotification); QString filename = QString(); if (index > 0) { filename = configBox->itemData(index).toString(); } if (!filename.isEmpty()) { removeCurrentButtons(); emit forceTabUnflash(this); qDebug() << "SDL Current Powerl Level: " << SDL_JoystickCurrentPowerLevel(m_joystick->getJoyHandle()) << "\n"; if (SDL_JoystickCurrentPowerLevel(m_joystick->getJoyHandle()) == SDL_JOYSTICK_POWER_WIRED || SDL_JoystickCurrentPowerLevel(m_joystick->getJoyHandle()) == SDL_JOYSTICK_POWER_UNKNOWN) { QMetaObject::invokeMethod(&tabHelper, "readConfigFile", Qt::BlockingQueuedConnection, Q_ARG(QString, filename)); } else { tabHelper.readConfigFile(filename); } fillButtons(); refreshSetButtons(); refreshCopySetActions(); configBox->setItemText(0, tr("")); XMLConfigReader *reader = tabHelper.getReader(); if (!reader->hasError()) { QString profileName = QString(); if (!m_joystick->getProfileName().isEmpty()) { profileName = m_joystick->getProfileName(); oldProfileName = profileName; } else { QFileInfo profile(filename); oldProfileName = PadderCommon::getProfileName(profile); profileName = oldProfileName; } configBox->setItemText(index, profileName); } else if (reader->hasError() && this->window()->isEnabled()) { QMessageBox msg; msg.setStandardButtons(QMessageBox::Close); msg.setText(reader->getErrorString()); msg.setModal(true); msg.exec(); } else if (reader->hasError() && !this->window()->isEnabled()) { QTextStream error(stderr); error << reader->getErrorString() << endl; } } else if (index == 0) { removeCurrentButtons(); emit forceTabUnflash(this); QMetaObject::invokeMethod(&tabHelper, "reInitDevice", Qt::BlockingQueuedConnection); fillButtons(); refreshSetButtons(); refreshCopySetActions(); configBox->setItemText(0, tr("")); oldProfileName = ""; } comboBoxIndex = index; connect(m_joystick, &InputDevice::profileUpdated, this, &JoyTabWidget::displayProfileEditNotification); } void JoyTabWidget::saveSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString filename = ""; QString lastfile = ""; m_settings->getLock()->lock(); int index = configBox->currentIndex(); int currentjoy = 1; QString identifier = m_joystick->getStringIdentifier(); QString controlEntryPrefix = QString("Controller%1").arg(identifier); QString controlEntryString = QString("Controller%1ConfigFile%2").arg(identifier); QString controlEntryLastSelected = QString("Controller%1LastSelected").arg(identifier); QString controlEntryProfileName = QString("Controller%1ProfileName%2").arg(m_joystick->getStringIdentifier()); // Remove current settings for a controller QStringList tempkeys = m_settings->allKeys(); QStringListIterator iter(tempkeys); while (iter.hasNext()) { QString tempstring = iter.next(); if (!identifier.isEmpty() && tempstring.startsWith(controlEntryPrefix)) { m_settings->remove(tempstring); } } // Output currently selected profile as first profile on the list if (index != 0) { filename = lastfile = configBox->itemData(index).toString(); QString profileText = configBox->itemText(index); if (!identifier.isEmpty()) { QFileInfo profileBaseFile(filename); QString outputFilename = filename; m_settings->setValue(controlEntryString.arg(currentjoy), outputFilename); if (PadderCommon::getProfileName(profileBaseFile) != profileText) { m_settings->setValue(controlEntryProfileName.arg(currentjoy), profileText); } } currentjoy++; } else { lastfile = ""; } // Write the remaining profile locations to the settings file for (int i = 1; i < configBox->count(); i++) { if (i != index) { filename = configBox->itemData(i).toString(); QString profileText = configBox->itemText(i); if (!identifier.isEmpty()) { QFileInfo profileBaseFile(filename); QString outputFilename = filename; m_settings->setValue(controlEntryString.arg(currentjoy), outputFilename); if (PadderCommon::getProfileName(profileBaseFile) != profileText) { m_settings->setValue(controlEntryProfileName.arg(currentjoy), profileText); } } currentjoy++; } } if (!identifier.isEmpty()) { QFileInfo profileBaseFile(lastfile); QString outputFilename = lastfile; m_settings->setValue(controlEntryLastSelected, outputFilename); } m_settings->getLock()->unlock(); } void JoyTabWidget::loadSettings(bool forceRefresh) { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::changeJoyConfig); m_settings->getLock()->lock(); if (configBox->count() > 1) { configBox->clear(); configBox->addItem(tr(""), ""); configBox->setCurrentIndex(-1); } else if (forceRefresh) { configBox->setCurrentIndex(-1); } int shouldisplaynames = m_settings->value("DisplayNames", "0").toInt(); if (shouldisplaynames == 1) { changeNameDisplay(shouldisplaynames); } int numberRecentProfiles = m_settings->value("NumberRecentProfiles", DEFAULTNUMBERPROFILES).toInt(); bool autoOpenLastProfile = m_settings->value("AutoOpenLastProfile", true).toBool(); m_settings->beginGroup("Controllers"); convToUniqueIDControllerGroupSett(m_settings, QString("Controller%1LastSelected").arg(m_joystick->getGUIDString()), QString("Controller%1LastSelected").arg(m_joystick->getUniqueIDString())); QString controlEntryString = QString("Controller%1ConfigFile%2").arg(m_joystick->getStringIdentifier()); QString controlEntryLastSelected = QString("Controller%1LastSelected").arg(m_joystick->getStringIdentifier()); QString controlEntryProfileName = QString("Controller%1ProfileName%2").arg(m_joystick->getStringIdentifier()); bool finished = false; for (int i = 1; !finished; i++) { QString tempfilepath = QString(); if (!m_joystick->getStringIdentifier().isEmpty()) { convToUniqueIDControllerGroupSett( m_settings, QString("Controller%1ConfigFile%2").arg(m_joystick->getGUIDString()).arg(i), QString("Controller%1ConfigFile%2").arg(m_joystick->getUniqueIDString()).arg(i)); tempfilepath = m_settings->value(controlEntryString.arg(i), "").toString(); } if (!tempfilepath.isEmpty()) { QFileInfo fileInfo(tempfilepath); if (fileInfo.exists() && (configBox->findData(fileInfo.absoluteFilePath()) == -1)) { convToUniqueIDControllerGroupSett( m_settings, QString("Controller%1ProfileName%2").arg(m_joystick->getGUIDString()).arg(i), QString("Controller%1ProfileName%2").arg(m_joystick->getUniqueIDString()).arg(i)); QString profileName = m_settings->value(controlEntryProfileName.arg(i), "").toString(); profileName = !profileName.isEmpty() ? profileName : PadderCommon::getProfileName(fileInfo); configBox->addItem(profileName, fileInfo.absoluteFilePath()); } } else { finished = true; } if ((numberRecentProfiles > 0) && (i == numberRecentProfiles)) { finished = true; } } connect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::changeJoyConfig, Qt::QueuedConnection); QString lastfile = QString(); if (!m_joystick->getStringIdentifier().isEmpty() && autoOpenLastProfile) { lastfile = m_settings->value(controlEntryLastSelected, "").toString(); } m_settings->endGroup(); m_settings->getLock()->unlock(); if (!lastfile.isEmpty()) { QString lastFileAbsolute = lastfile; int lastindex = configBox->findData(lastFileAbsolute); if (lastindex > 0) { configBox->setCurrentIndex(lastindex); emit joystickConfigChanged(m_joystick->getJoyNumber()); } else if (configBox->currentIndex() != 0) { configBox->setCurrentIndex(0); emit joystickConfigChanged(m_joystick->getJoyNumber()); } } else if (configBox->currentIndex() != 0) { configBox->setCurrentIndex(0); emit joystickConfigChanged(m_joystick->getJoyNumber()); } } QHash *JoyTabWidget::recentConfigs() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash *temp = new QHash(); for (int i = 1; i < configBox->count(); i++) { QString current = configBox->itemText(i); temp->insert(i, current); } return temp; } void JoyTabWidget::setCurrentConfig(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Allow 0 to select new/'null' config and therefore disable any mapping if ((index >= 0) && (index < configBox->count())) { configBox->setCurrentIndex(index); } } int JoyTabWidget::getCurrentConfigIndex() { qInstallMessageHandler(MessageHandler::myMessageOutput); return configBox->currentIndex(); } QString JoyTabWidget::getCurrentConfigName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return configBox->currentText(); } QString JoyTabWidget::getConfigName(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); return configBox->itemText(index); } void JoyTabWidget::changeCurrentSet(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); int currentPage = stackedWidget_2->currentIndex(); QPushButton *oldSetButton = nullptr; QPushButton *activeSetButton = nullptr; switch (currentPage) { case 0: oldSetButton = setPushButton1; break; case 1: oldSetButton = setPushButton2; break; case 2: oldSetButton = setPushButton3; break; case 3: oldSetButton = setPushButton4; break; case 4: oldSetButton = setPushButton5; break; case 5: oldSetButton = setPushButton6; break; case 6: oldSetButton = setPushButton7; break; case 7: oldSetButton = setPushButton8; break; default: break; } if (oldSetButton != nullptr) { oldSetButton->setProperty("setActive", false); oldSetButton->style()->unpolish(oldSetButton); oldSetButton->style()->polish(oldSetButton); } m_joystick->setActiveSetNumber(index); stackedWidget_2->setCurrentIndex(index); switch (index) { case 0: activeSetButton = setPushButton1; break; case 1: activeSetButton = setPushButton2; break; case 2: activeSetButton = setPushButton3; break; case 3: activeSetButton = setPushButton4; break; case 4: activeSetButton = setPushButton5; break; case 5: activeSetButton = setPushButton6; break; case 6: activeSetButton = setPushButton7; break; case 7: activeSetButton = setPushButton8; break; default: break; } if (activeSetButton != nullptr) { activeSetButton->setProperty("setActive", true); activeSetButton->style()->unpolish(activeSetButton); activeSetButton->style()->polish(activeSetButton); } } void JoyTabWidget::changeSetOne() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(0); } void JoyTabWidget::changeSetTwo() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(1); } void JoyTabWidget::changeSetThree() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(2); } void JoyTabWidget::changeSetFour() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(3); } void JoyTabWidget::changeSetFive() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(4); } void JoyTabWidget::changeSetSix() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(5); } void JoyTabWidget::changeSetSeven() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(6); } void JoyTabWidget::changeSetEight() { qInstallMessageHandler(MessageHandler::myMessageOutput); changeCurrentSet(7); } void JoyTabWidget::showStickAssignmentDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); Joystick *temp = qobject_cast(m_joystick); // static_cast AdvanceStickAssignmentDialog *dialog = new AdvanceStickAssignmentDialog(temp, this); connect(dialog, &AdvanceStickAssignmentDialog::finished, this, &JoyTabWidget::refreshButtons); dialog->show(); } void JoyTabWidget::loadConfigFile(QString fileLocation) { qInstallMessageHandler(MessageHandler::myMessageOutput); checkForUnsavedProfile(-1); if (!m_joystick->isDeviceEdited()) { int numberRecentProfiles = m_settings->value("NumberRecentProfiles", DEFAULTNUMBERPROFILES).toInt(); QFileInfo fileinfo(fileLocation); if (fileinfo.exists() && ((fileinfo.suffix() == "xml") || (fileinfo.suffix() == "amgp"))) { int searchIndex = configBox->findData(fileinfo.absoluteFilePath()); if (searchIndex == -1) { disconnectCheckUnsavedEvent(); disconnectMainComboBoxEvents(); if ((numberRecentProfiles > 0) && (configBox->count() == (numberRecentProfiles + 1))) { configBox->removeItem(numberRecentProfiles - 1); // configBox->removeItem(5); } configBox->insertItem(1, PadderCommon::getProfileName(fileinfo), fileinfo.absoluteFilePath()); reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); configBox->setCurrentIndex(1); emit joystickConfigChanged(m_joystick->getJoyNumber()); } else if (searchIndex != configBox->currentIndex()) { configBox->setCurrentIndex(searchIndex); emit joystickConfigChanged(m_joystick->getJoyNumber()); } } } } void JoyTabWidget::showQuickSetDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ButtonEditDialog *dialog = new ButtonEditDialog(m_joystick, isKeypadUnlocked(), this); connect(dialog, &ButtonEditDialog::finished, this, &JoyTabWidget::refreshButtons); dialog->show(); } void JoyTabWidget::showKeyDelayDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); ExtraProfileSettingsDialog *dialog = new ExtraProfileSettingsDialog(m_joystick, this); dialog->show(); } void JoyTabWidget::showSetNamesDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetNamesDialog *dialog = new SetNamesDialog(m_joystick, this); connect(dialog, &SetNamesDialog::accepted, this, &JoyTabWidget::refreshSetButtons); connect(dialog, &SetNamesDialog::accepted, this, &JoyTabWidget::refreshCopySetActions); dialog->show(); } void JoyTabWidget::removeCurrentButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); m_joystick->disconnectPropertyUpdatedConnection(); disconnect(m_joystick, &InputDevice::setChangeActivated, this, &JoyTabWidget::changeCurrentSet); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { SetJoystick *currentSet = m_joystick->getSetJoystick(i); removeSetButtons(currentSet); } } InputDevice *JoyTabWidget::getJoystick() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_joystick; } void JoyTabWidget::removeConfig() { qInstallMessageHandler(MessageHandler::myMessageOutput); int currentIndex = configBox->currentIndex(); if (currentIndex > 0) { configBox->removeItem(currentIndex); saveDeviceSettings(true); emit joystickConfigChanged(m_joystick->getJoyNumber()); } } void JoyTabWidget::toggleNames() { qInstallMessageHandler(MessageHandler::myMessageOutput); displayingNames = !displayingNames; namesPushButton->setProperty("isDisplayingNames", displayingNames); namesPushButton->style()->unpolish(namesPushButton); namesPushButton->style()->polish(namesPushButton); emit namesDisplayChanged(displayingNames); } void JoyTabWidget::unloadConfig() { qInstallMessageHandler(MessageHandler::myMessageOutput); configBox->setCurrentIndex(0); } void JoyTabWidget::saveDeviceSettings(bool sync) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_settings->getLock()->lock(); m_settings->beginGroup("Controllers"); m_settings->getLock()->unlock(); saveSettings(); m_settings->getLock()->lock(); m_settings->endGroup(); if (sync) m_settings->sync(); m_settings->getLock()->unlock(); } void JoyTabWidget::loadDeviceSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); // m_settings->beginGroup("Controllers"); loadSettings(); // m_settings->endGroup(); } bool JoyTabWidget::isDisplayingNames() { qInstallMessageHandler(MessageHandler::myMessageOutput); return displayingNames; } void JoyTabWidget::changeNameDisplay(bool displayNames) { displayingNames = displayNames; namesPushButton->setProperty("isDisplayingNames", displayingNames); namesPushButton->style()->unpolish(namesPushButton); namesPushButton->style()->polish(namesPushButton); } void JoyTabWidget::refreshSetButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { QPushButton *tempSetButton = nullptr; QAction *tempSetAction = nullptr; SetJoystick *tempSet = m_joystick->getSetJoystick(i); switch (i) { case 0: tempSetButton = setPushButton1; tempSetAction = setAction1; break; case 1: tempSetButton = setPushButton2; tempSetAction = setAction2; break; case 2: tempSetButton = setPushButton3; tempSetAction = setAction3; break; case 3: tempSetButton = setPushButton4; tempSetAction = setAction4; break; case 4: tempSetButton = setPushButton5; tempSetAction = setAction5; break; case 5: tempSetButton = setPushButton6; tempSetAction = setAction6; break; case 6: tempSetButton = setPushButton7; tempSetAction = setAction7; break; case 7: tempSetButton = setPushButton8; tempSetAction = setAction8; break; default: break; } if (!tempSet->getName().isEmpty()) { QString tempName = tempSet->getName(); QString tempNameEscaped = tempName; tempNameEscaped.replace("&", "&&"); tempSetButton->setText(tempNameEscaped); tempSetButton->setToolTip(tempName); tempSetAction->setText(tr("Set").append(" %1: %2").arg(i + 1).arg(tempNameEscaped)); } else { tempSetButton->setText(QString::number(i + 1)); tempSetButton->setToolTip(""); tempSetAction->setText(tr("Set").append(" %1").arg(i + 1)); } } } void JoyTabWidget::displayProfileEditNotification() { qInstallMessageHandler(MessageHandler::myMessageOutput); int currentIndex = configBox->currentIndex(); configBox->setItemIcon(currentIndex, PadderCommon::loadIcon("document-save-as", ":/icons/actions/document_save_as.png")); changedNotSaved = true; } void JoyTabWidget::removeProfileEditNotification() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < configBox->count(); i++) { if (!configBox->itemIcon(i).isNull()) { configBox->setItemIcon(i, QIcon()); } } changedNotSaved = false; } void JoyTabWidget::retranslateUi() { qInstallMessageHandler(MessageHandler::myMessageOutput); removeButton->setText(tr("Remove")); removeButton->setToolTip(tr("Remove configuration from recent list.")); loadButton->setText(tr("Load")); loadButton->setToolTip(tr("Load configuration file.")); saveButton->setText(tr("Save")); saveButton->setToolTip(tr("Save changes to configuration file.")); saveAsButton->setText(tr("Save As")); saveAsButton->setToolTip(tr("Save changes to a new configuration file.")); setsMenuButton->setText(tr("Sets")); setAction1->setText(tr("Set 1")); setAction2->setText(tr("Set 2")); setAction3->setText(tr("Set 3")); setAction4->setText(tr("Set 4")); setAction5->setText(tr("Set 5")); setAction6->setText(tr("Set 6")); setAction7->setText(tr("Set 7")); setAction8->setText(tr("Set 8")); refreshSetButtons(); refreshCopySetActions(); gameControllerMappingPushButton->setText(tr("Controller Mapping")); stickAssignPushButton->setText(tr("Stick/Pad Assign")); quickSetPushButton->setText(tr("Quick Set")); resetButton->setText(tr("Reset")); namesPushButton->setText(tr("Names")); namesPushButton->setToolTip(tr("Toggle button name displaying.")); delayButton->setText(tr("Pref")); delayButton->setToolTip(tr("Change global profile settings.")); resetButton->setText(tr("Reset")); resetButton->setToolTip(tr("Revert changes to the configuration. Reload configuration file.")); refreshButtons(); } void JoyTabWidget::checkForUnsavedProfile(int newindex) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_joystick->isDeviceEdited()) { disconnectCheckUnsavedEvent(); disconnectMainComboBoxEvents(); if (configBox->currentIndex() != comboBoxIndex) { configBox->setCurrentIndex(comboBoxIndex); } QMessageBox msg; msg.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); msg.setWindowTitle(tr("Save Profile Changes?")); if (comboBoxIndex == 0) { msg.setText(tr( "Changes to the new profile have not been saved. Would you like to save or discard the current profile?")); } else { msg.setText(tr("Changes to the profile \"%1\" have not been saved. Would you like to save or discard changes to " "the current profile?") .arg(configBox->currentText())); } int status = msg.exec(); switch (status) { case QMessageBox::Save: { saveConfigFile(); reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); if (newindex > -1) { configBox->setCurrentIndex(newindex); } break; } case QMessageBox::Discard: { m_joystick->revertProfileEdited(); configBox->setItemText(comboBoxIndex, oldProfileName); reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); if (newindex > -1) { configBox->setCurrentIndex(newindex); } break; } case QMessageBox::Cancel: { reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); break; } } } } bool JoyTabWidget::discardUnsavedProfileChanges() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool discarded = true; if (m_joystick->isDeviceEdited()) { disconnectCheckUnsavedEvent(); QMessageBox msg; msg.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); msg.setWindowTitle(tr("Save Profile Changes?")); int currentIndex = configBox->currentIndex(); if (currentIndex == 0) { msg.setText(tr( "Changes to the new profile have not been saved. Would you like to save or discard the current profile?")); } else { msg.setText(tr("Changes to the profile \"%1\" have not been saved. Would you like to save or discard changes to " "the current profile?") .arg(configBox->currentText())); } int status = msg.exec(); switch (status) { case QMessageBox::Save: { saveConfigFile(); if ((currentIndex == 0) && (currentIndex == configBox->currentIndex())) { discarded = false; } break; } case QMessageBox::Discard: { m_joystick->revertProfileEdited(); configBox->setItemText(currentIndex, oldProfileName); resetJoystick(); break; } case QMessageBox::Cancel: { discarded = false; break; } } disconnectMainComboBoxEvents(); reconnectCheckUnsavedEvent(); reconnectMainComboBoxEvents(); } return discarded; } bool JoyTabWidget::changesNotSaved() { return changedNotSaved; } void JoyTabWidget::disconnectMainComboBoxEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::changeJoyConfig); disconnect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::removeProfileEditNotification); disconnect(m_joystick, &InputDevice::profileNameEdited, this, &JoyTabWidget::editCurrentProfileItemText); } void JoyTabWidget::reconnectMainComboBoxEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::changeJoyConfig, Qt::QueuedConnection); connect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::removeProfileEditNotification, Qt::QueuedConnection); connect(m_joystick, &InputDevice::profileNameEdited, this, &JoyTabWidget::editCurrentProfileItemText); } void JoyTabWidget::disconnectCheckUnsavedEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::checkForUnsavedProfile); } void JoyTabWidget::reconnectCheckUnsavedEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(configBox, static_cast(&QComboBox::currentIndexChanged), this, &JoyTabWidget::checkForUnsavedProfile); } void JoyTabWidget::refreshButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); removeCurrentButtons(); fillButtons(); } void JoyTabWidget::checkStickDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *button = qobject_cast(sender()); // static_cast JoyControlStick *stick = button->getStick(); if ((stick != nullptr) && stick->hasSlotsAssigned()) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } void JoyTabWidget::checkDPadButtonDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *button = qobject_cast(sender()); // static_cast JoyDPad *dpad = button->getDPad(); if ((dpad != nullptr) && dpad->hasSlotsAssigned()) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } void JoyTabWidget::checkAxisButtonDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *button = qobject_cast(sender()); // static_cast if (button->getAssignedSlots()->count() > 0) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } // IT CAN BE HERE void JoyTabWidget::checkButtonDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = qobject_cast(sender()); // static_cast if (button->getAssignedSlots()->count() > 0) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } void JoyTabWidget::checkStickEmptyDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); StickPushButtonGroup *group = qobject_cast(sender()); // static_cast JoyControlStick *stick = group->getStick(); // JoyControlStickButton *button = static_cast(sender()); // JoyControlStick *stick = button->getStick(); if ((stick != nullptr) && !stick->hasSlotsAssigned()) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } void JoyTabWidget::checkDPadButtonEmptyDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); DPadPushButtonGroup *group = qobject_cast(sender()); // static_cast JoyDPad *dpad = group->getDPad(); // JoyDPadButton *button = static_cast(sender()); // JoyDPad *dpad = button->getDPad(); if ((dpad != nullptr) && !dpad->hasSlotsAssigned()) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } void JoyTabWidget::checkAxisButtonEmptyDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *button = qobject_cast(sender()); // static_cast if (button->getAssignedSlots()->count() == 0) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } void JoyTabWidget::checkButtonEmptyDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = qobject_cast(sender()); // static_cast if (button->getAssignedSlots()->count() == 0) { SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); removeSetButtons(currentSet); fillSetButtons(currentSet); } } void JoyTabWidget::checkHideEmptyOption() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool currentHideEmptyButtons = m_settings->value("HideEmptyButtons", false).toBool(); if (currentHideEmptyButtons != hideEmptyButtons) { hideEmptyButtons = currentHideEmptyButtons; refreshButtons(); } } void JoyTabWidget::fillSetButtons(SetJoystick *set) { qInstallMessageHandler(MessageHandler::myMessageOutput); int row = 0; int column = 0; // QWidget *child = 0; QGridLayout *current_layout = nullptr; switch (set->getIndex()) { case 0: { current_layout = gridLayout; break; } case 1: { current_layout = gridLayout2; break; } case 2: { current_layout = gridLayout3; break; } case 3: { current_layout = gridLayout4; break; } case 4: { current_layout = gridLayout5; break; } case 5: { current_layout = gridLayout6; break; } case 6: { current_layout = gridLayout7; break; } case 7: { current_layout = gridLayout8; break; } default: break; } SetJoystick *currentSet = set; currentSet->establishPropertyUpdatedConnection(); QGridLayout *stickGrid = nullptr; QGroupBox *stickGroup = nullptr; int stickGridColumn = 0; int stickGridRow = 0; for (int j = 0; j < m_joystick->getNumberSticks(); j++) { JoyControlStick *stick = currentSet->getJoyStick(j); stick->establishPropertyUpdatedConnection(); QHash *stickButtons = stick->getButtons(); if (!hideEmptyButtons || stick->hasSlotsAssigned()) { if (stickGroup == nullptr) { stickGroup = new QGroupBox(tr("Sticks"), this); } if (stickGrid == nullptr) { stickGrid = new QGridLayout(); stickGridColumn = 0; stickGridRow = 0; } QWidget *groupContainer = new QWidget(stickGroup); StickPushButtonGroup *stickButtonGroup = new StickPushButtonGroup(stick, isKeypadUnlocked(), displayingNames, groupContainer); if (hideEmptyButtons) { connect(stickButtonGroup, &StickPushButtonGroup::buttonSlotChanged, this, &JoyTabWidget::checkStickEmptyDisplay); } connect(namesPushButton, &QPushButton::clicked, stickButtonGroup, &StickPushButtonGroup::toggleNameDisplay); if (stickGridColumn > 1) { stickGridColumn = 0; stickGridRow++; } groupContainer->setLayout(stickButtonGroup); stickGrid->addWidget(groupContainer, stickGridRow, stickGridColumn); stickGridColumn++; } else { QHashIterator tempiter(*stickButtons); while (tempiter.hasNext()) { JoyControlStickButton *button = tempiter.next().value(); button->establishPropertyUpdatedConnections(); connect(button, &JoyControlStickButton::slotsChanged, this, &JoyTabWidget::checkStickDisplay); } } } if (stickGroup != nullptr) { QSpacerItem *tempspacer = new QSpacerItem(10, 4, QSizePolicy::Minimum, QSizePolicy::Fixed); QVBoxLayout *tempvbox = new QVBoxLayout; tempvbox->addLayout(stickGrid); tempvbox->addItem(tempspacer); stickGroup->setLayout(tempvbox); current_layout->addWidget(stickGroup, row, column, 1, 2, Qt::AlignTop); row++; } column = 0; QGridLayout *hatGrid = nullptr; QGroupBox *hatGroup = nullptr; int hatGridColumn = 0; int hatGridRow = 0; for (int j = 0; j < m_joystick->getNumberHats(); j++) { JoyDPad *dpad = currentSet->getJoyDPad(j); dpad->establishPropertyUpdatedConnection(); QHash *buttons = dpad->getJoyButtons(); if (!hideEmptyButtons || dpad->hasSlotsAssigned()) { if (hatGroup == nullptr) { hatGroup = new QGroupBox(tr("DPads"), this); } if (hatGrid == nullptr) { hatGrid = new QGridLayout(); hatGridColumn = 0; hatGridRow = 0; } QWidget *groupContainer = new QWidget(hatGroup); DPadPushButtonGroup *dpadButtonGroup = new DPadPushButtonGroup(dpad, isKeypadUnlocked(), displayingNames, groupContainer); if (hideEmptyButtons) { connect(dpadButtonGroup, &DPadPushButtonGroup::buttonSlotChanged, this, &JoyTabWidget::checkDPadButtonEmptyDisplay); } connect(namesPushButton, &QPushButton::clicked, dpadButtonGroup, &DPadPushButtonGroup::toggleNameDisplay); if (hatGridColumn > 1) { hatGridColumn = 0; hatGridRow++; } groupContainer->setLayout(dpadButtonGroup); hatGrid->addWidget(groupContainer, hatGridRow, hatGridColumn); hatGridColumn++; } else { QHashIterator tempiter(*buttons); while (tempiter.hasNext()) { JoyDPadButton *button = tempiter.next().value(); button->establishPropertyUpdatedConnections(); connect(button, &JoyDPadButton::slotsChanged, this, &JoyTabWidget::checkDPadButtonDisplay); } } } for (int j = 0; j < m_joystick->getNumberVDPads(); j++) { VDPad *vdpad = currentSet->getVDPad(j); vdpad->establishPropertyUpdatedConnection(); QHash *buttons = vdpad->getButtons(); if (!hideEmptyButtons || vdpad->hasSlotsAssigned()) { if (hatGroup == nullptr) { hatGroup = new QGroupBox(tr("DPads"), this); } if (hatGrid == nullptr) { hatGrid = new QGridLayout(); hatGridColumn = 0; hatGridRow = 0; } QWidget *groupContainer = new QWidget(hatGroup); DPadPushButtonGroup *dpadButtonGroup = new DPadPushButtonGroup(vdpad, isKeypadUnlocked(), displayingNames, groupContainer); if (hideEmptyButtons) { connect(dpadButtonGroup, &DPadPushButtonGroup::buttonSlotChanged, this, &JoyTabWidget::checkDPadButtonEmptyDisplay); } connect(namesPushButton, &QPushButton::clicked, dpadButtonGroup, &DPadPushButtonGroup::toggleNameDisplay); if (hatGridColumn > 1) { hatGridColumn = 0; hatGridRow++; } groupContainer->setLayout(dpadButtonGroup); hatGrid->addWidget(groupContainer, hatGridRow, hatGridColumn); hatGridColumn++; } else { QHashIterator tempiter(*buttons); while (tempiter.hasNext()) { JoyDPadButton *button = tempiter.next().value(); button->establishPropertyUpdatedConnections(); connect(button, &JoyDPadButton::slotsChanged, this, &JoyTabWidget::checkDPadButtonDisplay); } } } if (hatGroup != nullptr) { QSpacerItem *tempspacer = new QSpacerItem(10, 4, QSizePolicy::Minimum, QSizePolicy::Fixed); QVBoxLayout *tempvbox = new QVBoxLayout; tempvbox->addLayout(hatGrid); tempvbox->addItem(tempspacer); hatGroup->setLayout(tempvbox); current_layout->addWidget(hatGroup, row, column, 1, 2, Qt::AlignTop); row++; } column = 0; for (int j = 0; j < m_joystick->getNumberAxes(); j++) { JoyAxis *axis = currentSet->getJoyAxis(j); if (!axis->isPartControlStick() && axis->hasControlOfButtons()) { JoyAxisButton *paxisbutton = axis->getPAxisButton(); JoyAxisButton *naxisbutton = axis->getNAxisButton(); if (!hideEmptyButtons || ((paxisbutton->getAssignedSlots()->count() > 0) || (naxisbutton->getAssignedSlots()->count() > 0))) { JoyAxisWidget *axisWidget = new JoyAxisWidget(axis, displayingNames, this); axisWidget->setText(axis->getName()); axisWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); axisWidget->setMinimumSize(200, 24); connect(axisWidget, &JoyAxisWidget::clicked, this, &JoyTabWidget::showAxisDialog); connect(namesPushButton, &QPushButton::clicked, axisWidget, &JoyAxisWidget::toggleNameDisplay); if (hideEmptyButtons) { connect(paxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonEmptyDisplay); connect(naxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonEmptyDisplay); } if (column > 1) { column = 0; row++; } current_layout->addWidget(axisWidget, row, column); column++; } else { paxisbutton->establishPropertyUpdatedConnections(); naxisbutton->establishPropertyUpdatedConnections(); connect(paxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonDisplay); connect(naxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonDisplay); } } } for (int j = 0; j < m_joystick->getNumberButtons(); j++) { JoyButton *button = currentSet->getJoyButton(j); if ((button != nullptr) && !button->isPartVDPad()) { button->establishPropertyUpdatedConnections(); if (!hideEmptyButtons || (button->getAssignedSlots()->count() > 0)) { qDebug() << "Button in joytabwidget " << button->getName() << " has " << button->getAssignedSlots()->count() << " assignments"; for (auto it : *button->getAssignedSlots()) { qDebug() << "slotMode: " << it->getSlotMode(); if (it->getSlotMode() == 15) { for (auto it2 : *it->getMixSlots()) { qDebug() << "mixslot: " << it2->getSlotString(); } } } JoyButtonWidget *buttonWidget = new JoyButtonWidget(button, displayingNames, this); buttonWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); buttonWidget->setText(buttonWidget->text()); buttonWidget->setMinimumSize(200, 24); connect(buttonWidget, &JoyButtonWidget::clicked, this, &JoyTabWidget::showButtonDialog); connect(namesPushButton, &QPushButton::clicked, buttonWidget, &JoyButtonWidget::toggleNameDisplay); if (hideEmptyButtons) { connect(button, &JoyButton::slotsChanged, this, &JoyTabWidget::checkButtonEmptyDisplay); } if (column > 1) { column = 0; row++; } current_layout->addWidget(buttonWidget, row, column); column++; } else { button->establishPropertyUpdatedConnections(); connect(button, &JoyButton::slotsChanged, this, &JoyTabWidget::checkButtonDisplay); } } } if (current_layout->count() == 0) { QLabel *newlabel = new QLabel(tr("No buttons have been assigned. Please use Quick Set to assign keys\nto buttons or " "disable hiding empty buttons.")); current_layout->addWidget(newlabel, 0, 0, Qt::AlignCenter); } } void JoyTabWidget::removeSetButtons(SetJoystick *set) { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentSet = set; currentSet->disconnectPropertyUpdatedConnection(); QLayoutItem *child = nullptr; QGridLayout *current_layout = nullptr; switch (currentSet->getIndex()) { case 0: { current_layout = gridLayout; break; } case 1: { current_layout = gridLayout2; break; } case 2: { current_layout = gridLayout3; break; } case 3: { current_layout = gridLayout4; break; } case 4: { current_layout = gridLayout5; break; } case 5: { current_layout = gridLayout6; break; } case 6: { current_layout = gridLayout7; break; } case 7: { current_layout = gridLayout8; break; } default: { break; } } while (current_layout && ((child = current_layout->takeAt(0)) != nullptr)) { current_layout->removeWidget(child->widget()); delete child->widget(); delete child; child = nullptr; } for (int j = 0; j < m_joystick->getNumberSticks(); j++) { JoyControlStick *stick = currentSet->getJoyStick(j); stick->disconnectPropertyUpdatedConnection(); QHash *stickButtons = stick->getButtons(); QHashIterator tempiter(*stickButtons); while (tempiter.hasNext()) { JoyControlStickButton *button = tempiter.next().value(); button->disconnectPropertyUpdatedConnections(); disconnect(button, &JoyControlStickButton::slotsChanged, this, &JoyTabWidget::checkStickDisplay); disconnect(button, &JoyControlStickButton::slotsChanged, this, &JoyTabWidget::checkStickEmptyDisplay); } } for (int j = 0; j < m_joystick->getNumberHats(); j++) { JoyDPad *dpad = currentSet->getJoyDPad(j); dpad->establishPropertyUpdatedConnection(); QHash *buttons = dpad->getJoyButtons(); QHashIterator tempiter(*buttons); while (tempiter.hasNext()) { JoyDPadButton *button = tempiter.next().value(); button->disconnectPropertyUpdatedConnections(); disconnect(button, &JoyDPadButton::slotsChanged, this, &JoyTabWidget::checkDPadButtonDisplay); disconnect(button, &JoyDPadButton::slotsChanged, this, &JoyTabWidget::checkDPadButtonEmptyDisplay); } } for (int j = 0; j < m_joystick->getNumberVDPads(); j++) { VDPad *vdpad = currentSet->getVDPad(j); vdpad->establishPropertyUpdatedConnection(); QHash *buttons = vdpad->getButtons(); QHashIterator tempiter(*buttons); while (tempiter.hasNext()) { JoyDPadButton *button = tempiter.next().value(); button->disconnectPropertyUpdatedConnections(); disconnect(button, &JoyDPadButton::slotsChanged, this, &JoyTabWidget::checkDPadButtonDisplay); disconnect(button, &JoyDPadButton::slotsChanged, this, &JoyTabWidget::checkDPadButtonEmptyDisplay); } } for (int j = 0; j < m_joystick->getNumberAxes(); j++) { JoyAxis *axis = currentSet->getJoyAxis(j); if (!axis->isPartControlStick() && axis->hasControlOfButtons()) { JoyAxisButton *paxisbutton = axis->getPAxisButton(); JoyAxisButton *naxisbutton = axis->getNAxisButton(); paxisbutton->disconnectPropertyUpdatedConnections(); naxisbutton->disconnectPropertyUpdatedConnections(); disconnect(paxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonDisplay); disconnect(naxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonDisplay); disconnect(paxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonEmptyDisplay); disconnect(naxisbutton, &JoyAxisButton::slotsChanged, this, &JoyTabWidget::checkAxisButtonEmptyDisplay); } } for (int j = 0; j < m_joystick->getNumberButtons(); j++) { JoyButton *button = currentSet->getJoyButton(j); if ((button != nullptr) && !button->isPartVDPad()) { button->disconnectPropertyUpdatedConnections(); disconnect(button, &JoyButton::slotsChanged, this, &JoyTabWidget::checkButtonDisplay); disconnect(button, &JoyButton::slotsChanged, this, &JoyTabWidget::checkButtonEmptyDisplay); } } } void JoyTabWidget::editCurrentProfileItemText(QString text) { qInstallMessageHandler(MessageHandler::myMessageOutput); int currentIndex = configBox->currentIndex(); if (currentIndex >= 0) { if (!text.isEmpty()) { configBox->setItemText(currentIndex, text); } else if (currentIndex == 0) { configBox->setItemText(currentIndex, tr("")); } else if (currentIndex > 0) { QFileInfo profileName(configBox->itemData(currentIndex).toString()); configBox->setItemText(currentIndex, PadderCommon::getProfileName(profileName)); } } } void JoyTabWidget::refreshCopySetActions() { qInstallMessageHandler(MessageHandler::myMessageOutput); copySetMenu->clear(); for (int i = 0; i < GlobalVariables::InputDevice::NUMBER_JOYSETS; i++) { SetJoystick *tempSet = m_joystick->getSetJoystick(i); QAction *newaction = nullptr; if (!tempSet->getName().isEmpty()) { QString tempName = tempSet->getName(); QString tempNameEscaped = tempName; tempNameEscaped.replace("&", "&&"); newaction = new QAction(tr("Set %1: %2").arg(i + 1).arg(tempNameEscaped), copySetMenu); } else { newaction = new QAction(tr("Set %1").arg(i + 1), copySetMenu); } newaction->setData(i); connect(newaction, &QAction::triggered, this, &JoyTabWidget::performSetCopy); copySetMenu->addAction(newaction); } connect(copySetMenu, &QMenu::aboutToShow, this, &JoyTabWidget::disableCopyCurrentSet); } void JoyTabWidget::performSetCopy() { qInstallMessageHandler(MessageHandler::myMessageOutput); QAction *action = qobject_cast(sender()); // static_cast int sourceSetIndex = action->data().toInt(); SetJoystick *sourceSet = m_joystick->getSetJoystick(sourceSetIndex); QString sourceName = QString(); if (!sourceSet->getName().isEmpty()) { QString tempNameEscaped = sourceSet->getName(); tempNameEscaped.replace("&", "&&"); sourceName = tr("Set %1: %2").arg(sourceSetIndex + 1).arg(tempNameEscaped); } else { sourceName = tr("Set %1").arg(sourceSetIndex + 1); } SetJoystick *destSet = m_joystick->getActiveSetJoystick(); if ((sourceSet != nullptr) && (destSet != nullptr)) { QMessageBox msgBox; msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setWindowTitle(tr("Copy Set Assignments")); msgBox.setText(tr("Are you sure you want to copy the assignments and device properties from %1?").arg(sourceName)); int status = msgBox.exec(); if (status == QMessageBox::Yes) { PadderCommon::lockInputDevices(); removeSetButtons(destSet); QMetaObject::invokeMethod(sourceSet, "copyAssignments", Qt::BlockingQueuedConnection, Q_ARG(SetJoystick *, destSet)); // sourceSet->copyAssignments(destSet); fillSetButtons(destSet); PadderCommon::unlockInputDevices(); } } } void JoyTabWidget::disableCopyCurrentSet() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *activeSet = m_joystick->getActiveSetJoystick(); QMenu *menu = qobject_cast(sender()); // static_cast QList actions = menu->actions(); QListIterator iter(actions); while (iter.hasNext()) { QAction *action = iter.next(); if (action->data().toInt() == activeSet->getIndex()) { action->setEnabled(false); } else { action->setEnabled(true); } } } void JoyTabWidget::openGameControllerMappingWindow() { qInstallMessageHandler(MessageHandler::myMessageOutput); GameControllerMappingDialog *dialog = new GameControllerMappingDialog(m_joystick, m_settings, this); dialog->show(); connect(dialog, &GameControllerMappingDialog::mappingUpdate, this, &JoyTabWidget::propogateMappingUpdate); } void JoyTabWidget::propogateMappingUpdate(QString mapping, InputDevice *device) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit mappingUpdated(mapping, device); } void JoyTabWidget::refreshHelperThread() { qInstallMessageHandler(MessageHandler::myMessageOutput); tabHelper.moveToThread(m_joystick->thread()); } void JoyTabWidget::changeEvent(QEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (event->type() == QEvent::LanguageChange) { retranslateUi(); } QWidget::changeEvent(event); } void JoyTabWidget::convToUniqueIDControllerGroupSett(QSettings *sett, QString guidControllerSett, QString uniqueControllerSett) { if (sett->contains(guidControllerSett)) { sett->setValue(uniqueControllerSett, sett->value(guidControllerSett)); sett->remove(guidControllerSett); } } AntiMicroX-antimicrox-2888bf6/src/joytabwidget.h000066400000000000000000000161441377703515000217250ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYTABWIDGET_H #define JOYTABWIDGET_H #include #include "uihelpers/joytabwidgethelper.h" class InputDevice; class AntiMicroSettings; class QEvent; class SetJoystick; class QVBoxLayout; class QHBoxLayout; class QGridLayout; class QPushButton; class QComboBox; class QSpacerItem; class AxisEditDialog; class QAction; class QMenu; class QStackedWidget; class QSettings; class JoyTabWidget : public QWidget { Q_OBJECT public: explicit JoyTabWidget(InputDevice *joystick, AntiMicroSettings *settings, QWidget *parent = nullptr); void saveSettings(); // JoyTabSettings class void loadSettings(bool forceRefresh = false); // JoyTabSettings class void setCurrentConfig(int index); // JoyTabSettings class void unloadConfig(); // JoyTabSettings class void checkHideEmptyOption(); void refreshHelperThread(); void convToUniqueIDControllerGroupSett(QSettings *sett, QString guidControllerSett, QString uniqueControllerSett); bool isDisplayingNames(); bool discardUnsavedProfileChanges(); bool static changesNotSaved(); int getCurrentConfigIndex(); // JoyTabSettings class QHash *recentConfigs(); // JoyTabSettings class QString getCurrentConfigName(); // JoyTabSettings class QString getConfigName(int index); InputDevice *getJoystick(); protected: virtual void changeEvent(QEvent *event); void removeCurrentButtons(); void retranslateUi(); void disconnectMainComboBoxEvents(); void reconnectMainComboBoxEvents(); void disconnectCheckUnsavedEvent(); void reconnectCheckUnsavedEvent(); void fillSetButtons(SetJoystick *set); // JoyTabWidgetSets class void removeSetButtons(SetJoystick *set); // JoyTabWidgetSets class bool isKeypadUnlocked(); static const int DEFAULTNUMBERPROFILES = 5; signals: void joystickConfigChanged(int index); // JoyTabSettings class void joystickAxisRefreshLabels(int axisIndex); void namesDisplayChanged(bool status); void forceTabUnflash(JoyTabWidget *tabWidget); void mappingUpdated(QString mapping, InputDevice *device); public slots: void openConfigFileDialog(); // JoyTabSettings class void fillButtons(); // JoyTabWidgetSets class void saveDeviceSettings(bool sync = false); // JoyTabSettings class void loadDeviceSettings(); // JoyTabSettings class void changeNameDisplay(bool displayNames); void changeCurrentSet(int index); // JoyTabWidgetSets class void loadConfigFile(QString fileLocation); // JoyTabSettings class void refreshButtons(); private slots: void saveConfigFile(); // JoyTabSettings class void resetJoystick(); void saveAsConfig(); // JoyTabSettings class void removeConfig(); // JoyTabSettings class void changeJoyConfig(int index); // JoyTabSettings class void showAxisDialog(); void showButtonDialog(); void showStickAssignmentDialog(); void showQuickSetDialog(); void showKeyDelayDialog(); void showSetNamesDialog(); // JoyTabWidgetSets class void toggleNames(); void changeSetOne(); // JoyTabWidgetSets class void changeSetTwo(); // JoyTabWidgetSets class void changeSetThree(); // JoyTabWidgetSets class void changeSetFour(); // JoyTabWidgetSets class void changeSetFive(); // JoyTabWidgetSets class void changeSetSix(); // JoyTabWidgetSets class void changeSetSeven(); // JoyTabWidgetSets class void changeSetEight(); // JoyTabWidgetSets class void displayProfileEditNotification(); void removeProfileEditNotification(); void checkForUnsavedProfile(int newindex = -1); void checkStickDisplay(); void checkDPadButtonDisplay(); void checkAxisButtonDisplay(); void checkButtonDisplay(); void checkStickEmptyDisplay(); void checkDPadButtonEmptyDisplay(); void checkAxisButtonEmptyDisplay(); void checkButtonEmptyDisplay(); void editCurrentProfileItemText(QString text); void refreshCopySetActions(); // JoyTabWidgetSets class void performSetCopy(); // JoyTabWidgetSets class void disableCopyCurrentSet(); // JoyTabWidgetSets class void refreshSetButtons(); // JoyTabWidgetSets class void openGameControllerMappingWindow(); void propogateMappingUpdate(QString mapping, InputDevice *device); private: QVBoxLayout *verticalLayout; QHBoxLayout *configHorizontalLayout; QPushButton *removeButton; QPushButton *loadButton; QPushButton *saveButton; QPushButton *resetButton; QPushButton *namesPushButton; QPushButton *saveAsButton; QPushButton *delayButton; QComboBox *configBox; QGridLayout *gridLayout; QGridLayout *gridLayout2; QGridLayout *gridLayout3; QGridLayout *gridLayout4; QGridLayout *gridLayout5; QGridLayout *gridLayout6; QGridLayout *gridLayout7; QGridLayout *gridLayout8; QSpacerItem *spacer1; QSpacerItem *spacer2; QSpacerItem *spacer3; AxisEditDialog *axisDialog; QPushButton *setPushButton1; QPushButton *setPushButton2; QPushButton *setPushButton3; QPushButton *setPushButton4; QPushButton *setPushButton5; QPushButton *setPushButton6; QPushButton *setPushButton7; QPushButton *setPushButton8; QPushButton *setsMenuButton; QAction *setAction1; QAction *setAction2; QAction *setAction3; QAction *setAction4; QAction *setAction5; QAction *setAction6; QAction *setAction7; QAction *setAction8; QMenu *copySetMenu; QHBoxLayout *horizontalLayout_2; QHBoxLayout *horizontalLayout_3; QPushButton *stickAssignPushButton; QPushButton *quickSetPushButton; QPushButton *gameControllerMappingPushButton; QSpacerItem *verticalSpacer_2; QStackedWidget *stackedWidget_2; QWidget *page; QWidget *page_2; QWidget *page_3; QWidget *page_4; QWidget *page_5; QWidget *page_6; QWidget *page_7; QWidget *page_8; QPushButton *pushButton; QSpacerItem *verticalSpacer_3; InputDevice *m_joystick; bool displayingNames; static bool changedNotSaved; AntiMicroSettings *m_settings; int comboBoxIndex; bool hideEmptyButtons; QString oldProfileName; JoyTabWidgetHelper tabHelper; }; #endif // JOYTABWIDGET_H AntiMicroX-antimicrox-2888bf6/src/joytabwidgetcontainer.cpp000066400000000000000000000100251377703515000241530ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joytabwidgetcontainer.h" #include "joystick.h" #include "joytabwidget.h" #include "messagehandler.h" #include #include #include JoyTabWidgetContainer::JoyTabWidgetContainer(QWidget *parent) : QTabWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } int JoyTabWidgetContainer::addTab(QWidget *widget, const QString &string) { qInstallMessageHandler(MessageHandler::myMessageOutput); return QTabWidget::addTab(widget, string); } int JoyTabWidgetContainer::addTab(JoyTabWidget *widget, const QString &string) { qInstallMessageHandler(MessageHandler::myMessageOutput); InputDevice *joystick = widget->getJoystick(); if (joystick != nullptr) { enableFlashes(joystick); connect(widget, &JoyTabWidget::forceTabUnflash, this, &JoyTabWidgetContainer::unflashTab); } return QTabWidget::addTab(widget, string); } void JoyTabWidgetContainer::flash(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; for (int i = 0; (i < tabBar()->count()) && !found; i++) { JoyTabWidget *tab = qobject_cast(widget(i)); // static_cast if ((tab != nullptr) && (tab->getJoystick() == joystick)) { tabBar()->setTabTextColor(i, Qt::red); found = true; } } } void JoyTabWidgetContainer::unflash(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; for (int i = 0; (i < tabBar()->count()) && !found; i++) { JoyTabWidget *tab = qobject_cast(widget(i)); // static_cast if ((tab != nullptr) && (tab->getJoystick() == joystick)) { tabBar()->setTabTextColor(i, Qt::black); found = true; } } } void JoyTabWidgetContainer::unflashTab(JoyTabWidget *tabWidget) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; for (int i = 0; (i < tabBar()->count()) && !found; i++) { JoyTabWidget *tab = qobject_cast(widget(i)); // static_cast if (tab == tabWidget) { tabBar()->setTabTextColor(i, Qt::black); } } } void JoyTabWidgetContainer::unflashAll() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < tabBar()->count(); i++) { JoyTabWidget *tab = qobject_cast(widget(i)); // static_cast if (tab != nullptr) { tabBar()->setTabTextColor(i, Qt::black); } } } void JoyTabWidgetContainer::disableFlashes(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); unflashAll(); disconnect(joystick, &InputDevice::clicked, this, nullptr); disconnect(joystick, &InputDevice::released, this, nullptr); } void JoyTabWidgetContainer::enableFlashes(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); connect( joystick, &InputDevice::clicked, this, [this, joystick] { flash(joystick); }, Qt::QueuedConnection); connect( joystick, &InputDevice::released, this, [this, joystick] { unflash(joystick); }, Qt::QueuedConnection); } AntiMicroX-antimicrox-2888bf6/src/joytabwidgetcontainer.h000066400000000000000000000027771377703515000236370ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYTABWIDGETCONTAINER_H #define JOYTABWIDGETCONTAINER_H #include class QWidget; class JoyTabWidget; class InputDevice; class JoyTabWidgetContainer : public QTabWidget { Q_OBJECT public: explicit JoyTabWidgetContainer(QWidget *parent = nullptr); int addTab(QWidget *widget, const QString &string); int addTab(JoyTabWidget *widget, const QString &string); public slots: void disableFlashes(InputDevice *joystick); void enableFlashes(InputDevice *joystick); private slots: void flash(InputDevice *joystick); void unflash(InputDevice *joystick); void unflashAll(); void unflashTab(JoyTabWidget *tabWidget); }; #endif // JOYTABWIDGETCONTAINER_H AntiMicroX-antimicrox-2888bf6/src/keyboard/000077500000000000000000000000001377703515000206525ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/keyboard/virtualkeyboardmousewidget.cpp000066400000000000000000001301151377703515000270430ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "virtualkeyboardmousewidget.h" #include "antkeymapper.h" #include "buttoneditdialog.h" #include "event.h" #include "messagehandler.h" #include "mousedialog/mousebuttonsettingsdialog.h" #include "qtkeymapperbase.h" #include "quicksetdialog.h" #include "virtualkeypushbutton.h" #include "virtualmousepushbutton.h" #include #ifdef WITH_X11 #include "x11extras.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include QHash VirtualKeyboardMouseWidget::topRowKeys = QHash(); VirtualKeyboardMouseWidget::VirtualKeyboardMouseWidget(InputDevice *joystick, ButtonEditDialogHelper *helper, bool isNumKeypad, QuickSetDialog *quickSetDialog, JoyButton *button, QWidget *parent) : QTabWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_isNumKeypad = isNumKeypad; this->joystick = joystick; this->helper = helper; this->withoutQuickSetDialog = (button != nullptr); lastPressedBtn = button; currentQuickDialog = quickSetDialog; keyboardTab = new QWidget(this); mouseTab = new QWidget(this); noneButton = createNoneKey(); populateTopRowKeys(); this->addTab(keyboardTab, tr("Keyboard")); this->addTab(mouseTab, tr("Mouse")); this->setTabPosition(QTabWidget::South); setupVirtualKeyboardLayout(); setupMouseControlLayout(); establishVirtualKeyboardSingleSignalConnections(); establishVirtualMouseSignalConnections(); QTimer::singleShot(0, this, SLOT(setButtonFontSizes())); connect(mouseSettingsPushButton, &QPushButton::clicked, this, &VirtualKeyboardMouseWidget::openMouseSettingsDialog); } VirtualKeyboardMouseWidget::VirtualKeyboardMouseWidget(bool isNumKeypad, QWidget *parent) : QTabWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_isNumKeypad = isNumKeypad; keyboardTab = new QWidget(this); mouseTab = new QWidget(this); noneButton = createNoneKey(); withoutQuickSetDialog = false; lastPressedBtn = nullptr; populateTopRowKeys(); this->addTab(keyboardTab, tr("Keyboard")); this->addTab(mouseTab, tr("Mouse")); this->setTabPosition(QTabWidget::South); setupVirtualKeyboardLayout(); setupMouseControlLayout(); establishVirtualKeyboardSingleSignalConnections(); establishVirtualMouseSignalConnections(); QTimer::singleShot(0, this, SLOT(setButtonFontSizes())); } /*bool VirtualKeyboardMouseWidget::is_numlock_activated() { #if defined(WITH_X11) Display *dpy = XOpenDisplay(X11Extras::getInstance()->getEnvVariable("DISPLAY")); XKeyboardState x; XGetKeyboardControl(dpy, &x); XCloseDisplay(dpy); return x.led_mask & 2; #endif return false; } bool VirtualKeyboardMouseWidget::isLaptop() { int secs, pct; if (SDL_GetPowerInfo(&secs, &pct) == SDL_POWERSTATE_UNKNOWN) return false; else return true; }*/ void VirtualKeyboardMouseWidget::setupVirtualKeyboardLayout() { qInstallMessageHandler(MessageHandler::myMessageOutput); QVBoxLayout *finalVBoxLayout = new QVBoxLayout(keyboardTab); QVBoxLayout *tempMainKeyLayout = setupMainKeyboardLayout(); QVBoxLayout *tempAuxKeyLayout = new QVBoxLayout(); QVBoxLayout *tempNumKeyPadLayout = new QVBoxLayout(); if (m_isNumKeypad) { tempNumKeyPadLayout = setupKeyboardNumPadLayout(); } else { QPushButton *othersKeysButton = createOtherKeysMenu(); tempNumKeyPadLayout->addWidget(noneButton); tempNumKeyPadLayout->addWidget(othersKeysButton); tempNumKeyPadLayout->addSpacerItem(new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding)); } QHBoxLayout *tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->addLayout(tempMainKeyLayout); if (m_isNumKeypad) { tempAuxKeyLayout = setupAuxKeyboardLayout(); tempHBoxLayout->addLayout(tempAuxKeyLayout); } else { delete tempAuxKeyLayout; } tempHBoxLayout->addLayout(tempNumKeyPadLayout); finalVBoxLayout->addLayout(tempHBoxLayout); } QVBoxLayout *VirtualKeyboardMouseWidget::setupMainKeyboardLayout() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHBoxLayout *tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); QVBoxLayout *tempVBoxLayout = new QVBoxLayout(); tempVBoxLayout->setSpacing(0); QVBoxLayout *finalVBoxLayout = new QVBoxLayout(); if (!m_isNumKeypad) finalVBoxLayout->setSpacing(0); tempHBoxLayout->addWidget(createNewKey("Escape")); if (m_isNumKeypad) tempHBoxLayout->addSpacerItem(new QSpacerItem(70, 10, QSizePolicy::Expanding)); tempHBoxLayout->addWidget(createNewKey("F1")); tempHBoxLayout->addWidget(createNewKey("F2")); tempHBoxLayout->addWidget(createNewKey("F3")); tempHBoxLayout->addWidget(createNewKey("F4")); if (m_isNumKeypad) tempHBoxLayout->addSpacerItem(new QSpacerItem(70, 10, QSizePolicy::Expanding)); tempHBoxLayout->addWidget(createNewKey("F5")); tempHBoxLayout->addWidget(createNewKey("F6")); tempHBoxLayout->addWidget(createNewKey("F7")); tempHBoxLayout->addWidget(createNewKey("F8")); if (m_isNumKeypad) tempHBoxLayout->addSpacerItem(new QSpacerItem(70, 10, QSizePolicy::Expanding)); tempHBoxLayout->addWidget(createNewKey("F9")); tempHBoxLayout->addWidget(createNewKey("F10")); tempHBoxLayout->addWidget(createNewKey("F11")); tempHBoxLayout->addWidget(createNewKey("F12")); if (!m_isNumKeypad) { tempHBoxLayout->addWidget(createNewKey("Print")); tempHBoxLayout->addWidget(createNewKey("Pause")); tempHBoxLayout->addWidget(createNewKey("Delete")); } finalVBoxLayout->addLayout(tempHBoxLayout); if (m_isNumKeypad) finalVBoxLayout->addSpacerItem(new QSpacerItem(20, 35, QSizePolicy::Minimum, QSizePolicy::Fixed)); tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); tempHBoxLayout->addWidget(createNewKey("grave")); for (int i = 1; i <= 9; i++) { tempHBoxLayout->addWidget(createNewKey(QString::number(i))); } tempHBoxLayout->addWidget(createNewKey("0")); tempHBoxLayout->addWidget(createNewKey("minus")); tempHBoxLayout->addWidget(createNewKey("equal")); tempHBoxLayout->addWidget(createNewKey("BackSpace")); if (!m_isNumKeypad) { tempHBoxLayout->addWidget(createNewKey("Home")); } tempVBoxLayout->addLayout(tempHBoxLayout); QVBoxLayout *tempMiddleVLayout = new QVBoxLayout(); tempMiddleVLayout->setSpacing(0); QHBoxLayout *tempMiddleHLayout = new QHBoxLayout(); tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->addWidget(createNewKey("Tab")); if (m_isNumKeypad) tempHBoxLayout->addSpacerItem(new QSpacerItem(10, 30, QSizePolicy::Fixed)); tempHBoxLayout->addWidget(createNewKey("q")); tempHBoxLayout->addWidget(createNewKey("w")); tempHBoxLayout->addWidget(createNewKey("e")); tempHBoxLayout->addWidget(createNewKey("r")); tempHBoxLayout->addWidget(createNewKey("t")); tempHBoxLayout->addWidget(createNewKey("y")); tempHBoxLayout->addWidget(createNewKey("u")); tempHBoxLayout->addWidget(createNewKey("i")); tempHBoxLayout->addWidget(createNewKey("o")); tempHBoxLayout->addWidget(createNewKey("p")); tempHBoxLayout->addWidget(createNewKey("bracketleft")); tempHBoxLayout->addWidget(createNewKey("bracketright")); if ((QLocale::system().language() != QLocale::French) && (QLocale::system().language() != QLocale::German)) { tempHBoxLayout->addWidget(createNewKey("backslash")); } if (!m_isNumKeypad) { tempHBoxLayout->addWidget(createNewKey("Prior")); tempVBoxLayout->addLayout(tempHBoxLayout); } else { tempMiddleVLayout->addLayout(tempHBoxLayout); } tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); tempHBoxLayout->addWidget(createNewKey("Caps_Lock")); tempHBoxLayout->addWidget(createNewKey("a")); tempHBoxLayout->addWidget(createNewKey("s")); tempHBoxLayout->addWidget(createNewKey("d")); tempHBoxLayout->addWidget(createNewKey("f")); tempHBoxLayout->addWidget(createNewKey("g")); tempHBoxLayout->addWidget(createNewKey("h")); tempHBoxLayout->addWidget(createNewKey("j")); tempHBoxLayout->addWidget(createNewKey("k")); tempHBoxLayout->addWidget(createNewKey("l")); tempHBoxLayout->addWidget(createNewKey("semicolon")); tempHBoxLayout->addWidget(createNewKey("apostrophe")); if ((QLocale::system().language() == QLocale::French) || (QLocale::system().language() == QLocale::German)) { tempHBoxLayout->addWidget(createNewKey("asterisk")); } if (m_isNumKeypad) { tempMiddleVLayout->addLayout(tempHBoxLayout); tempMiddleHLayout->addLayout(tempMiddleVLayout); tempMiddleHLayout->setSpacing(0); tempMiddleHLayout->addWidget(createNewKey("Return")); tempVBoxLayout->addLayout(tempMiddleHLayout); } else { tempHBoxLayout->addWidget(createNewKey("Return")); tempHBoxLayout->addWidget(createNewKey("Next")); tempVBoxLayout->addLayout(tempHBoxLayout); delete tempMiddleHLayout; delete tempMiddleVLayout; } tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); tempHBoxLayout->addWidget(createNewKey("Shift_L")); if (QLocale::system().language() == QLocale::French) { tempHBoxLayout->addWidget(createNewKey("less")); } tempHBoxLayout->addWidget(createNewKey("z")); tempHBoxLayout->addWidget(createNewKey("x")); tempHBoxLayout->addWidget(createNewKey("c")); tempHBoxLayout->addWidget(createNewKey("v")); tempHBoxLayout->addWidget(createNewKey("b")); tempHBoxLayout->addWidget(createNewKey("n")); tempHBoxLayout->addWidget(createNewKey("m")); tempHBoxLayout->addWidget(createNewKey("comma")); tempHBoxLayout->addWidget(createNewKey("period")); tempHBoxLayout->addWidget(createNewKey("slash")); tempHBoxLayout->addWidget(createNewKey("Shift_R")); if (!m_isNumKeypad) { tempHBoxLayout->addWidget(createNewKey("Up")); tempHBoxLayout->addWidget(createNewKey("End")); } tempVBoxLayout->addLayout(tempHBoxLayout); tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); tempHBoxLayout->addWidget(createNewKey("Control_L")); tempHBoxLayout->addWidget(createNewKey("Super_L")); tempHBoxLayout->addWidget(createNewKey("Alt_L")); tempHBoxLayout->addWidget(createNewKey("space")); VirtualKeyPushButton *altR = createNewKey("Alt_R"); if (altR->getKeycode() <= 0) { tempHBoxLayout->addWidget(createNewKey("ISO_Level3_Shift")); delete altR; } else { tempHBoxLayout->addWidget(altR); } tempHBoxLayout->addWidget(createNewKey("Menu")); tempHBoxLayout->addWidget(createNewKey("Control_R")); if (!m_isNumKeypad) { tempHBoxLayout->addWidget(createNewKey("Left")); tempHBoxLayout->addWidget(createNewKey("Down")); tempHBoxLayout->addWidget(createNewKey("Right")); } tempVBoxLayout->addLayout(tempHBoxLayout); if (m_isNumKeypad) { tempVBoxLayout->setStretch(0, 1); tempVBoxLayout->setStretch(1, 2); tempVBoxLayout->setStretch(2, 1); tempVBoxLayout->setStretch(3, 1); } finalVBoxLayout->addLayout(tempVBoxLayout); if (m_isNumKeypad) { finalVBoxLayout->setStretch(0, 1); finalVBoxLayout->setStretch(1, 0); finalVBoxLayout->setStretch(2, 2); } return finalVBoxLayout; } QVBoxLayout *VirtualKeyboardMouseWidget::setupAuxKeyboardLayout() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHBoxLayout *tempHBoxLayout = new QHBoxLayout(); QVBoxLayout *tempVBoxLayout = new QVBoxLayout(); QGridLayout *tempGridLayout = new QGridLayout(); tempHBoxLayout->setSpacing(0); tempVBoxLayout->setSpacing(0); tempGridLayout->setSpacing(0); tempHBoxLayout->addWidget(createNewKey("Print")); tempHBoxLayout->addWidget(createNewKey("Scroll_Lock")); tempHBoxLayout->addWidget(createNewKey("Pause")); tempVBoxLayout->addLayout(tempHBoxLayout); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 45, QSizePolicy::Minimum, QSizePolicy::Fixed)); tempGridLayout->addWidget(createNewKey("Insert"), 1, 1, 1, 1); tempGridLayout->addWidget(createNewKey("Home"), 1, 2, 1, 1); tempGridLayout->addWidget(createNewKey("Prior"), 1, 3, 1, 1); tempGridLayout->addWidget(createNewKey("Delete"), 2, 1, 1, 1); tempGridLayout->addWidget(createNewKey("End"), 2, 2, 1, 1); tempGridLayout->addWidget(createNewKey("Next"), 2, 3, 1, 1); tempVBoxLayout->addLayout(tempGridLayout); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 35, QSizePolicy::Minimum, QSizePolicy::Fixed)); tempGridLayout = new QGridLayout(); tempGridLayout->addWidget(createNewKey("Up"), 1, 2, 1, 1); tempGridLayout->addWidget(createNewKey("Left"), 2, 1, 1, 1); tempGridLayout->addWidget(createNewKey("Down"), 2, 2, 1, 1); tempGridLayout->addWidget(createNewKey("Right"), 2, 3, 1, 1); tempVBoxLayout->addLayout(tempGridLayout); return tempVBoxLayout; } QVBoxLayout *VirtualKeyboardMouseWidget::setupKeyboardNumPadLayout() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHBoxLayout *tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); QVBoxLayout *tempVBoxLayout = new QVBoxLayout(); tempVBoxLayout->setSpacing(0); QGridLayout *tempGridLayout = new QGridLayout(); tempGridLayout->setSpacing(0); QVBoxLayout *finalVBoxLayout = new QVBoxLayout(); finalVBoxLayout->setSpacing(0); QPushButton *othersKeysButton = createOtherKeysMenu(); finalVBoxLayout->addWidget(noneButton); finalVBoxLayout->addWidget(othersKeysButton); finalVBoxLayout->setStretchFactor(noneButton, 1); finalVBoxLayout->setStretchFactor(othersKeysButton, 1); finalVBoxLayout->addSpacerItem(new QSpacerItem(0, 29, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding)); tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); tempHBoxLayout->addWidget(createNewKey("Num_Lock")); tempHBoxLayout->addWidget(createNewKey("KP_Divide")); tempHBoxLayout->addWidget(createNewKey("KP_Multiply")); tempHBoxLayout->addWidget(createNewKey("KP_Subtract")); tempVBoxLayout->addLayout(tempHBoxLayout); tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); tempGridLayout->addWidget(createNewKey("KP_7"), 1, 1, 1, 1); tempGridLayout->addWidget(createNewKey("KP_8"), 1, 2, 1, 1); tempGridLayout->addWidget(createNewKey("KP_9"), 1, 3, 1, 1); tempGridLayout->addWidget(createNewKey("KP_4"), 2, 1, 1, 1); tempGridLayout->addWidget(createNewKey("KP_5"), 2, 2, 1, 1); tempGridLayout->addWidget(createNewKey("KP_6"), 2, 3, 1, 1); tempHBoxLayout->addLayout(tempGridLayout); tempHBoxLayout->addWidget(createNewKey("KP_Add")); tempVBoxLayout->addLayout(tempHBoxLayout); tempHBoxLayout = new QHBoxLayout(); tempHBoxLayout->setSpacing(0); tempGridLayout = new QGridLayout(); tempGridLayout->setSpacing(0); tempGridLayout->addWidget(createNewKey("KP_1"), 1, 1, 1, 1); tempGridLayout->addWidget(createNewKey("KP_2"), 1, 2, 1, 1); tempGridLayout->addWidget(createNewKey("KP_3"), 1, 3, 1, 1); tempGridLayout->addWidget(createNewKey("KP_0"), 2, 1, 1, 2); tempGridLayout->addWidget(createNewKey("KP_Delete"), 2, 3, 1, 1); tempHBoxLayout->addLayout(tempGridLayout); tempHBoxLayout->addWidget(createNewKey("KP_Enter")); tempVBoxLayout->addLayout(tempHBoxLayout); finalVBoxLayout->addLayout(tempVBoxLayout); finalVBoxLayout->setStretchFactor(tempVBoxLayout, 8); return finalVBoxLayout; } void VirtualKeyboardMouseWidget::setupMouseControlLayout() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHBoxLayout *tempHBoxLayout = new QHBoxLayout(); QVBoxLayout *tempVBoxLayout = new QVBoxLayout(); QGridLayout *tempGridLayout = new QGridLayout(); QVBoxLayout *finalVBoxLayout = new QVBoxLayout(mouseTab); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); VirtualMousePushButton *pushButton = new VirtualMousePushButton(tr("Left", "Mouse"), JoyButtonSlot::MouseLeft, JoyButtonSlot::JoyMouseMovement, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(50); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 50, QSizePolicy::Minimum, QSizePolicy::Expanding)); tempVBoxLayout->addWidget(pushButton); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 50, QSizePolicy::Minimum, QSizePolicy::Expanding)); tempHBoxLayout->addLayout(tempVBoxLayout); tempHBoxLayout->addSpacerItem(new QSpacerItem(10, 20, QSizePolicy::Fixed)); tempVBoxLayout = new QVBoxLayout(); pushButton = new VirtualMousePushButton(tr("Up", "Mouse"), JoyButtonSlot::MouseUp, JoyButtonSlot::JoyMouseMovement, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(50); tempVBoxLayout->addWidget(pushButton); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Fixed)); QHBoxLayout *tempInnerHBoxLayout = new QHBoxLayout(); pushButton = new VirtualMousePushButton(tr("Left Button", "Mouse"), 1, JoyButtonSlot::JoyMouseButton, this); pushButton->setSizePolicy(sizePolicy); tempInnerHBoxLayout->addWidget(pushButton); pushButton = new VirtualMousePushButton(tr("Middle Button", "Mouse"), 2, JoyButtonSlot::JoyMouseButton, this); pushButton->setSizePolicy(sizePolicy); tempInnerHBoxLayout->addWidget(pushButton); pushButton = new VirtualMousePushButton(tr("Right Button", "Mouse"), 3, JoyButtonSlot::JoyMouseButton, this); pushButton->setSizePolicy(sizePolicy); tempInnerHBoxLayout->addWidget(pushButton); tempVBoxLayout->addLayout(tempInnerHBoxLayout); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Fixed)); pushButton = new VirtualMousePushButton(tr("Wheel Up", "Mouse"), 4, JoyButtonSlot::JoyMouseButton, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(30); tempGridLayout->addWidget(pushButton, 1, 2, 1, 1); pushButton = new VirtualMousePushButton(tr("Wheel Left", "Mouse"), 6, JoyButtonSlot::JoyMouseButton, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(30); tempGridLayout->addWidget(pushButton, 2, 1, 1, 1); pushButton = new VirtualMousePushButton(tr("Wheel Right", "Mouse"), 7, JoyButtonSlot::JoyMouseButton, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(30); tempGridLayout->addWidget(pushButton, 2, 3, 1, 1); pushButton = new VirtualMousePushButton(tr("Wheel Down", "Mouse"), 5, JoyButtonSlot::JoyMouseButton, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(30); tempGridLayout->addWidget(pushButton, 3, 2, 1, 1); tempVBoxLayout->addLayout(tempGridLayout); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Fixed)); pushButton = new VirtualMousePushButton(tr("Down", "Mouse"), JoyButtonSlot::MouseDown, JoyButtonSlot::JoyMouseMovement, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(50); tempVBoxLayout->addWidget(pushButton); tempVBoxLayout->setStretch(0, 1); tempVBoxLayout->setStretch(2, 1); tempVBoxLayout->setStretch(4, 3); tempVBoxLayout->setStretch(6, 1); tempHBoxLayout->addLayout(tempVBoxLayout); tempHBoxLayout->addSpacerItem(new QSpacerItem(10, 20, QSizePolicy::Fixed)); tempVBoxLayout = new QVBoxLayout(); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 50, QSizePolicy::Minimum, QSizePolicy::Expanding)); pushButton = new VirtualMousePushButton(tr("Right", "Mouse"), JoyButtonSlot::MouseRight, JoyButtonSlot::JoyMouseMovement, this); pushButton->setSizePolicy(sizePolicy); pushButton->setMinimumHeight(50); tempVBoxLayout->addWidget(pushButton); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 50, QSizePolicy::Minimum, QSizePolicy::Expanding)); tempHBoxLayout->addLayout(tempVBoxLayout); tempHBoxLayout->addSpacerItem(new QSpacerItem(10, 20, QSizePolicy::Fixed)); tempVBoxLayout = new QVBoxLayout(); tempVBoxLayout->setSpacing(20); pushButton = new VirtualMousePushButton(tr("Mouse 8", "Mouse"), 8, JoyButtonSlot::JoyMouseButton, this); pushButton->setMinimumHeight(40); tempVBoxLayout->addWidget(pushButton); pushButton = new VirtualMousePushButton(tr("Mouse 9", "Mouse"), 9, JoyButtonSlot::JoyMouseButton, this); pushButton->setMinimumHeight(40); tempVBoxLayout->addWidget(pushButton); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 50, QSizePolicy::Minimum, QSizePolicy::Expanding)); tempHBoxLayout->addLayout(tempVBoxLayout); tempHBoxLayout->addSpacerItem(new QSpacerItem(10, 20, QSizePolicy::Fixed)); tempVBoxLayout = new QVBoxLayout(); tempVBoxLayout->setSpacing(20); tempVBoxLayout->addSpacerItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Expanding)); mouseSettingsPushButton = new QPushButton(tr("Mouse Settings"), this); mouseSettingsPushButton->setIcon(PadderCommon::loadIcon("input-mouse", ":/icons/actions/edit_select.png")); tempVBoxLayout->addWidget(mouseSettingsPushButton); mouseSettingsPushButton->setEnabled(false); tempHBoxLayout->addLayout(tempVBoxLayout); finalVBoxLayout->addLayout(tempHBoxLayout); } VirtualKeyPushButton *VirtualKeyboardMouseWidget::createNewKey(QString xcodestring) { qInstallMessageHandler(MessageHandler::myMessageOutput); int width = 32; int height = 32; QFont font1; font1.setPointSize(8); font1.setBold(true); VirtualKeyPushButton *pushButton = new VirtualKeyPushButton(xcodestring, this); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); pushButton->setSizePolicy(sizePolicy); if (xcodestring == "space") { width = 131; } else if (xcodestring == "Tab") { width = 43; } else if (xcodestring == "Shift_L") { width = 77; } else if (xcodestring == "Shift_R") { if (!m_isNumKeypad) width = 59; else width = 95; } else if (xcodestring == "Caps_Lock") { width = 59; } else if (xcodestring == "Return") { width = 64; if (m_isNumKeypad) height = 64; pushButton->setMaximumWidth(100); } else if (xcodestring == "BackSpace") { width = 68; } else if (topRowKeys.contains(xcodestring)) { width = 30; height = 32; pushButton->setMaximumSize(100, 100); } else if ((xcodestring == "Print") || (xcodestring == "Scroll_Lock") || (xcodestring == "Pause")) { width = 32; height = 32; pushButton->setMaximumSize(100, 100); font1.setPointSize(6); } else if ((xcodestring == "KP_Add") || (xcodestring == "KP_Enter")) { height = 56; width = 32; font1.setPointSize(5); } else if (xcodestring == "Num_Lock") { width = 32; height = 32; font1.setPointSize(5); } else if (xcodestring.startsWith("KP_")) { width = 32; } else if (xcodestring == "backslash") { if (m_isNumKeypad) width = 32; else width = 43; } else if ((xcodestring == "Down") || (xcodestring == "Left") || (xcodestring == "Right")) { if (!m_isNumKeypad) { QSizePolicy sizePolicy2(QSizePolicy::Fixed, QSizePolicy::Preferred); pushButton->setSizePolicy(sizePolicy2); pushButton->setFixedWidth(58); } } else if ((xcodestring == "Control_L") || (xcodestring == "Super_L") || (xcodestring == "Alt_L") || (xcodestring == "Alt_R") || (xcodestring == "ISO_Level3_Shift") || (xcodestring == "Menu") || (xcodestring == "Control_R")) { if (!m_isNumKeypad) width = 32; else width = 41; } else if ((xcodestring.startsWith("F") && (xcodestring.count() > 1)) || (xcodestring == "Print") || (xcodestring == "Escape") || (xcodestring == "Pause") || (xcodestring == "Delete")) { if (!m_isNumKeypad) { QSizePolicy sizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed); pushButton->setSizePolicy(sizePolicy2); width = 32; height = 25; font1.setPointSize(5); } } pushButton->setObjectName(xcodestring); pushButton->setMinimumSize(width, height); pushButton->setFont(font1); return pushButton; } QPushButton *VirtualKeyboardMouseWidget::createNoneKey() { qInstallMessageHandler(MessageHandler::myMessageOutput); QPushButton *pushButton = new QPushButton(tr("NONE"), this); pushButton->setMinimumSize(0, 25); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); pushButton->setSizePolicy(sizePolicy); QFont font1; font1.setBold(true); pushButton->setFont(font1); return pushButton; } void VirtualKeyboardMouseWidget::processSingleKeyboardSelection(int keycode, int alias) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((currentQuickDialog == nullptr) && !withoutQuickSetDialog) { currentQuickDialog = new QuickSetDialog(joystick, helper, "setAssignedSlot", keycode, alias, 0, JoyButtonSlot::JoyKeyboard, true, true, this); currentQuickDialog->show(); connect(currentQuickDialog, &QuickSetDialog::finished, this, &VirtualKeyboardMouseWidget::nullifyDialogPointer); } else if (withoutQuickSetDialog) { ButtonEditDialog::getInstance()->invokeMethodLastBtn(lastPressedBtn, helper, "setAssignedSlot", keycode, alias, 0, JoyButtonSlot::JoyKeyboard, true, true, Qt::QueuedConnection, Qt::QueuedConnection, Qt::QueuedConnection); ButtonEditDialog::getInstance()->refreshForLastBtn(); } } void VirtualKeyboardMouseWidget::processAdvancedKeyboardSelection(int keycode, int alias) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit selectionMade(keycode, alias); } void VirtualKeyboardMouseWidget::processSingleMouseSelection(JoyButtonSlot *tempslot) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((currentQuickDialog == nullptr) && !withoutQuickSetDialog) { currentQuickDialog = new QuickSetDialog(joystick, helper, "setAssignedSlot", tempslot->getSlotCode(), -1, -1, tempslot->getSlotMode(), true, true, this); currentQuickDialog->show(); connect(currentQuickDialog, &QuickSetDialog::finished, this, &VirtualKeyboardMouseWidget::nullifyDialogPointer); } else if (withoutQuickSetDialog) { ButtonEditDialog::getInstance()->invokeMethodLastBtn( lastPressedBtn, helper, "setAssignedSlot", tempslot->getSlotCode(), -1, -1, tempslot->getSlotMode(), true, true, Qt::QueuedConnection, Qt::QueuedConnection, Qt::QueuedConnection); ButtonEditDialog::getInstance()->refreshForLastBtn(); } } void VirtualKeyboardMouseWidget::processAdvancedMouseSelection(JoyButtonSlot *tempslot) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit selectionMade(tempslot); } void VirtualKeyboardMouseWidget::populateTopRowKeys() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (topRowKeys.isEmpty()) { topRowKeys.insert("Escape", "Escape"); topRowKeys.insert("F1", "F1"); topRowKeys.insert("F2", "F2"); topRowKeys.insert("F3", "F3"); topRowKeys.insert("F4", "F4"); topRowKeys.insert("F5", "F5"); topRowKeys.insert("F6", "F6"); topRowKeys.insert("F7", "F7"); topRowKeys.insert("F8", "F8"); topRowKeys.insert("F9", "F9"); topRowKeys.insert("F10", "F10"); topRowKeys.insert("F11", "F11"); topRowKeys.insert("F12", "F12"); } } void VirtualKeyboardMouseWidget::addFButtonToOthers(int qt_keycode, QString keycode_text) { if (keysymToKeyString(AntKeyMapper::getInstance()->returnVirtualKey(qt_keycode)) != tr("[NO KEY]")) { QAction *tempAction = new QAction(keycode_text, otherKeysMenu); tempAction->setData(AntKeyMapper::getInstance()->returnVirtualKey(qt_keycode)); otherKeysMenu->addAction(tempAction); } } void VirtualKeyboardMouseWidget::establishVirtualKeyboardSingleSignalConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList newlist = keyboardTab->findChildren(); QListIterator iter(newlist); while (iter.hasNext()) { VirtualKeyPushButton *keybutton = iter.next(); disconnect(keybutton, &VirtualKeyPushButton::keycodeObtained, nullptr, nullptr); connect(keybutton, &VirtualKeyPushButton::keycodeObtained, this, &VirtualKeyboardMouseWidget::processSingleKeyboardSelection); } QListIterator iterActions(otherKeysMenu->actions()); while (iterActions.hasNext()) { QAction *temp = iterActions.next(); disconnect(temp, &QAction::triggered, nullptr, nullptr); connect(temp, &QAction::triggered, this, [this, temp](bool checked) { otherKeysActionSingle(temp, checked); }); } disconnect(noneButton, &QPushButton::clicked, nullptr, nullptr); connect(noneButton, &QPushButton::clicked, this, &VirtualKeyboardMouseWidget::clearButtonSlotsFinish); } void VirtualKeyboardMouseWidget::establishVirtualKeyboardAdvancedSignalConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList newlist = keyboardTab->findChildren(); QListIterator iter(newlist); while (iter.hasNext()) { VirtualKeyPushButton *keybutton = iter.next(); disconnect(keybutton, &VirtualKeyPushButton::keycodeObtained, nullptr, nullptr); connect(keybutton, &VirtualKeyPushButton::keycodeObtained, this, &VirtualKeyboardMouseWidget::processAdvancedKeyboardSelection); } QListIterator iterActions(otherKeysMenu->actions()); while (iterActions.hasNext()) { QAction *temp = iterActions.next(); disconnect(temp, &QAction::triggered, nullptr, nullptr); connect(temp, &QAction::triggered, this, [this, temp](bool checked) { otherKeysActionAdvanced(temp, checked); }); } disconnect(noneButton, &QPushButton::clicked, nullptr, nullptr); connect(noneButton, &QPushButton::clicked, this, &VirtualKeyboardMouseWidget::clearButtonSlots); } void VirtualKeyboardMouseWidget::establishVirtualMouseSignalConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList newlist = mouseTab->findChildren(); QListIterator iter(newlist); while (iter.hasNext()) { VirtualMousePushButton *mousebutton = iter.next(); disconnect(mousebutton, &VirtualMousePushButton::mouseSlotCreated, nullptr, nullptr); connect(mousebutton, &VirtualMousePushButton::mouseSlotCreated, this, &VirtualKeyboardMouseWidget::processSingleMouseSelection); } } void VirtualKeyboardMouseWidget::establishVirtualMouseAdvancedSignalConnections() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList newlist = mouseTab->findChildren(); QListIterator iter(newlist); while (iter.hasNext()) { VirtualMousePushButton *mousebutton = iter.next(); disconnect(mousebutton, &VirtualMousePushButton::mouseSlotCreated, nullptr, nullptr); connect(mousebutton, &VirtualMousePushButton::mouseSlotCreated, this, &VirtualKeyboardMouseWidget::processAdvancedMouseSelection); } } void VirtualKeyboardMouseWidget::clearButtonSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ButtonEditDialog::getInstance() != nullptr) { if (ButtonEditDialog::getInstance()->getLastJoyButton() != nullptr) QMetaObject::invokeMethod(ButtonEditDialog::getInstance()->getLastJoyButton(), "clearSlotsEventReset", Qt::BlockingQueuedConnection); emit selectionCleared(); lastPressedBtn->buildActiveZoneSummaryString(); } else { QMessageBox::information(this, tr("Last button"), tr("Slots for button couldn't be cleared, because there was not any set button from " "keyboard for gamepad. Map at least one button from keyboard to gamepad")); } } void VirtualKeyboardMouseWidget::clearButtonSlotsFinish() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ButtonEditDialog::getInstance() != nullptr) { if (ButtonEditDialog::getInstance()->getLastJoyButton() != nullptr) QMetaObject::invokeMethod(ButtonEditDialog::getInstance()->getLastJoyButton(), "clearSlotsEventReset", Qt::BlockingQueuedConnection); emit selectionFinished(); lastPressedBtn->buildActiveZoneSummaryString(); } else { QMessageBox::information(this, tr("Last button"), tr("Slots for button couldn't be cleared, because there was not any set button from " "keyboard for gamepad. Map at least one button from keyboard to gamepad")); } } bool VirtualKeyboardMouseWidget::isKeyboardTabVisible() { qInstallMessageHandler(MessageHandler::myMessageOutput); return this->keyboardTab->isVisible(); } void VirtualKeyboardMouseWidget::openMouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); mouseSettingsPushButton->setEnabled(false); // TODO instead of buttons, get pointer to static getInstance from ButtonEditDialog for last pressed button, and then // getting button from public method if (ButtonEditDialog::getInstance() != nullptr) { if (ButtonEditDialog::getInstance()->getLastJoyButton() != nullptr) { MouseButtonSettingsDialog *dialog = new MouseButtonSettingsDialog(ButtonEditDialog::getInstance()->getLastJoyButton(), this); dialog->show(); QDialog *parent = qobject_cast(this->parentWidget()); // static_cast connect(parent, &QDialog::finished, dialog, &MouseButtonSettingsDialog::close); connect(dialog, &MouseButtonSettingsDialog::finished, this, &VirtualKeyboardMouseWidget::enableMouseSettingButton); } else { QMessageBox::information(this, QObject::tr("Last button"), QObject::tr("There isn't a last button pressed from gamepad in data. Did you set at " "least one button from gamepad for keyboard?")); } } } void VirtualKeyboardMouseWidget::enableMouseSettingButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); mouseSettingsPushButton->setEnabled(true); } void VirtualKeyboardMouseWidget::disableMouseSettingButton() { qInstallMessageHandler(MessageHandler::myMessageOutput); mouseSettingsPushButton->setEnabled(false); } void VirtualKeyboardMouseWidget::resizeEvent(QResizeEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); QTabWidget::resizeEvent(event); setButtonFontSizes(); } // Dynamically change font size of list of push button according to the // size of the buttons. void VirtualKeyboardMouseWidget::setButtonFontSizes() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList buttonList = this->findChildren(); QListIterator iter(buttonList); while (iter.hasNext()) { VirtualKeyPushButton *temp = iter.next(); QFont tempFont(temp->font()); tempFont.setPointSize(temp->calculateFontSize()); temp->setFont(tempFont); } } QPushButton *VirtualKeyboardMouseWidget::createOtherKeysMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); QPushButton *otherKeysPushbutton = new QPushButton(tr("Others"), this); otherKeysPushbutton->setMinimumSize(0, 25); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); otherKeysPushbutton->setSizePolicy(sizePolicy); QFont font1; font1.setBold(true); otherKeysPushbutton->setFont(font1); otherKeysMenu = new QMenu(this); QAction *tempAction = nullptr; int temp = 0; tempAction = new QAction(tr("Browser Back"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Back); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Browser Favorites"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Favorites); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Browser Forward"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Forward); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Browser Home"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_HomePage); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Browser Refresh"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Refresh); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Browser Search"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Search); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Browser Stop"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Stop); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Calc"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Launch1); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Email"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_LaunchMail); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); addFButtonToOthers(Qt::Key_F13, tr("F13")); addFButtonToOthers(Qt::Key_F14, tr("F14")); addFButtonToOthers(Qt::Key_F15, tr("F15")); addFButtonToOthers(Qt::Key_F16, tr("F16")); addFButtonToOthers(Qt::Key_F17, tr("F17")); addFButtonToOthers(Qt::Key_F18, tr("F18")); addFButtonToOthers(Qt::Key_F19, tr("F19")); addFButtonToOthers(Qt::Key_F20, tr("F20")); addFButtonToOthers(Qt::Key_F21, tr("F21")); addFButtonToOthers(Qt::Key_F22, tr("F22")); addFButtonToOthers(Qt::Key_F23, tr("F23")); addFButtonToOthers(Qt::Key_F24, tr("F24")); tempAction = new QAction(tr("Media"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_LaunchMedia); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Media Next"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_MediaNext); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Media Play"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_MediaPlay); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Media Previous"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_MediaPrevious); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Media Stop"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_MediaStop); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Search"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_Search); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Volume Down"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_VolumeDown); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Volume Mute"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_VolumeMute); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); tempAction = new QAction(tr("Volume Up"), otherKeysMenu); temp = AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_VolumeUp); tempAction->setData(temp); otherKeysMenu->addAction(tempAction); otherKeysPushbutton->setMenu(otherKeysMenu); return otherKeysPushbutton; } void VirtualKeyboardMouseWidget::otherKeysActionSingle(QAction *tempAction, bool triggered) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(triggered); int virtualkey = tempAction->data().toInt(); processSingleKeyboardSelection(virtualkey, AntKeyMapper::getInstance()->returnQtKey(virtualkey)); } void VirtualKeyboardMouseWidget::otherKeysActionAdvanced(QAction *tempAction, bool triggered) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(triggered); int virtualkey = tempAction->data().toInt(); processAdvancedKeyboardSelection(virtualkey, AntKeyMapper::getInstance()->returnQtKey(virtualkey)); } void VirtualKeyboardMouseWidget::nullifyDialogPointer() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (currentQuickDialog != nullptr) { ButtonEditDialog::getInstance()->setUpLastJoyButton(currentQuickDialog->getLastPressedButton()); ButtonEditDialog::getInstance()->refreshForLastBtn(); enableMouseSettingButton(); currentQuickDialog = nullptr; emit buttonDialogClosed(); } } InputDevice *VirtualKeyboardMouseWidget::getJoystick() const { return joystick; } ButtonEditDialogHelper *VirtualKeyboardMouseWidget::getHelper() const { return helper; } QWidget *VirtualKeyboardMouseWidget::getKeyboardTab() const { return keyboardTab; } QWidget *VirtualKeyboardMouseWidget::getMouseTab() const { return mouseTab; } QPushButton *VirtualKeyboardMouseWidget::getNoneButton() const { return noneButton; } QPushButton *VirtualKeyboardMouseWidget::getMouseSettingsPushButton() const { return mouseSettingsPushButton; } QMenu *VirtualKeyboardMouseWidget::getOtherKeysMenu() const { return otherKeysMenu; } QuickSetDialog *VirtualKeyboardMouseWidget::getCurrentQuickDialog() const { return currentQuickDialog; } AntiMicroX-antimicrox-2888bf6/src/keyboard/virtualkeyboardmousewidget.h000066400000000000000000000100141377703515000265030ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VIRTUALKEYBOARDMOUSEWIDGET_H #define VIRTUALKEYBOARDMOUSEWIDGET_H #include #include class JoyButton; class JoyButtonSlot; class VirtualKeyPushButton; class QVBoxLayout; class QPushButton; class QWidget; class InputDevice; class QuickSetDialog; class ButtonEditDialogHelper; class VirtualKeyboardMouseWidget : public QTabWidget { Q_OBJECT public: explicit VirtualKeyboardMouseWidget(InputDevice *joystick, ButtonEditDialogHelper *helper, bool isNumKeypad, QuickSetDialog *quickSetDialog = nullptr, JoyButton *button = nullptr, QWidget *parent = nullptr); explicit VirtualKeyboardMouseWidget(bool isNumKeypad, QWidget *parent = nullptr); bool isKeyboardTabVisible(); bool is_numlock_activated(); // RealSystemInfo class bool isLaptop(); // RealSystemInfo class InputDevice *getJoystick() const; ButtonEditDialogHelper *getHelper() const; QWidget *getKeyboardTab() const; QWidget *getMouseTab() const; QPushButton *getNoneButton() const; QPushButton *getMouseSettingsPushButton() const; QMenu *getOtherKeysMenu() const; QuickSetDialog *getCurrentQuickDialog() const; static QHash topRowKeys; protected: void setupVirtualKeyboardLayout(); QVBoxLayout *setupMainKeyboardLayout(); QVBoxLayout *setupAuxKeyboardLayout(); QVBoxLayout *setupKeyboardNumPadLayout(); void setupMouseControlLayout(); VirtualKeyPushButton *createNewKey(QString xcodestring); QPushButton *createNoneKey(); void populateTopRowKeys(); void addFButtonToOthers(int qt_keycode, QString keycode_text); QPushButton *createOtherKeysMenu(); virtual void resizeEvent(QResizeEvent *event); signals: void selectionFinished(); void selectionCleared(); void selectionMade(int keycode, int alias); void selectionMade(JoyButtonSlot *slot); void buttonDialogClosed(); public slots: void establishVirtualKeyboardSingleSignalConnections(); void establishVirtualMouseSignalConnections(); void establishVirtualKeyboardAdvancedSignalConnections(); void establishVirtualMouseAdvancedSignalConnections(); void enableMouseSettingButton(); void disableMouseSettingButton(); private slots: void processSingleKeyboardSelection(int keycode, int alias); void processAdvancedKeyboardSelection(int keycode, int alias); void processSingleMouseSelection(JoyButtonSlot *tempslot); void processAdvancedMouseSelection(JoyButtonSlot *tempslot); void clearButtonSlots(); void clearButtonSlotsFinish(); void openMouseSettingsDialog(); void setButtonFontSizes(); void otherKeysActionSingle(QAction *action, bool triggered); void otherKeysActionAdvanced(QAction *action, bool triggered); void nullifyDialogPointer(); private: bool withoutQuickSetDialog; bool m_isNumKeypad; InputDevice *joystick; JoyButton *lastPressedBtn; ButtonEditDialogHelper *helper; QWidget *keyboardTab; QWidget *mouseTab; QPushButton *noneButton; QPushButton *mouseSettingsPushButton; QMenu *otherKeysMenu; QuickSetDialog *currentQuickDialog; }; #endif // VIRTUALKEYBOARDMOUSEWIDGET_H AntiMicroX-antimicrox-2888bf6/src/keyboard/virtualkeypushbutton.cpp000066400000000000000000000165111377703515000257150ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "virtualkeypushbutton.h" #include "antkeymapper.h" #include "event.h" #include "eventhandlerfactory.h" #include "messagehandler.h" #include #include #include #include QHash VirtualKeyPushButton::knownAliases = QHash(); VirtualKeyPushButton::VirtualKeyPushButton(QString xcodestring, QWidget *parent) : QPushButton(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); populateKnownAliases(); // qDebug() << "Question: " << X11KeySymToKeycode("KP_7") << endl; // qDebug() << "Question: " << X11KeySymToKeycode(79) << endl; this->keycode = 0; this->qkeyalias = 0; this->xcodestring = ""; this->displayString = ""; this->currentlyActive = false; this->onCurrentButton = false; int temp = 0; if (!xcodestring.isEmpty()) { temp = X11KeySymToKeycode(xcodestring); BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (handler->getIdentifier() == "xtest") { temp = X11KeyCodeToX11KeySym(temp); } } if (temp > 0) { this->keycode = temp; // this->keycode = X11KeyCodeToX11KeySym(temp); this->qkeyalias = AntKeyMapper::getInstance()->returnQtKey(this->keycode); // this->keycode = temp; this->xcodestring = xcodestring; this->displayString = setDisplayString(xcodestring); } qDebug() << "qkeyalias after returnQtKey: " << this->qkeyalias; qDebug() << "keycode: " << this->keycode; qDebug() << "xcodestring: " << this->xcodestring; qDebug() << "displayString: " << this->displayString; this->setText(this->displayString.replace("&", "&&")); connect(this, &VirtualKeyPushButton::clicked, this, &VirtualKeyPushButton::processSingleSelection); } void VirtualKeyPushButton::processSingleSelection() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit keycodeObtained(keycode, qkeyalias); } QString VirtualKeyPushButton::setDisplayString(QString xcodestring) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (knownAliases.contains(xcodestring)) { temp = knownAliases.value(xcodestring); } else { temp = keycodeToKeyString(X11KeySymToKeycode(xcodestring)); } if (temp.isEmpty() && !xcodestring.isEmpty()) { temp = xcodestring; } return temp.toUpper(); } // Define display strings that will be used for various keys on the // virtual keyboard. void VirtualKeyPushButton::populateKnownAliases() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (knownAliases.isEmpty()) { knownAliases.insert("space", tr("Space")); knownAliases.insert("Tab", tr("Tab")); knownAliases.insert("Shift_L", tr("Shift (L)")); knownAliases.insert("Shift_R", tr("Shift (R)")); knownAliases.insert("Control_L", tr("Ctrl (L)")); knownAliases.insert("Control_R", tr("Ctrl (R)")); knownAliases.insert("Alt_L", tr("Alt (L)")); knownAliases.insert("Alt_R", tr("Alt (R)")); knownAliases.insert("ISO_Level3_Shift", tr("Alt Gr")); knownAliases.insert("Multi_key", tr("Alt (R)")); knownAliases.insert("grave", tr("`")); knownAliases.insert("asciitilde", tr("~")); knownAliases.insert("minus", tr("-")); knownAliases.insert("equal", tr("=")); knownAliases.insert("bracketleft", tr("[")); knownAliases.insert("bracketright", tr("]")); knownAliases.insert("backslash", tr("\\")); knownAliases.insert("Caps_Lock", tr("Caps")); knownAliases.insert("semicolon", tr(";")); knownAliases.insert("apostrophe", tr("'")); knownAliases.insert("comma", tr(",")); knownAliases.insert("period", tr(".")); knownAliases.insert("slash", tr("/")); knownAliases.insert("Escape", tr("ESC")); knownAliases.insert("Print", tr("PRTSC")); knownAliases.insert("Scroll_Lock", tr("SCLK")); knownAliases.insert("Insert", tr("INS")); knownAliases.insert("Prior", tr("PGUP")); knownAliases.insert("Delete", tr("DEL")); knownAliases.insert("Next", tr("PGDN")); knownAliases.insert("KP_1", tr("1")); knownAliases.insert("KP_2", tr("2")); knownAliases.insert("KP_3", tr("3")); knownAliases.insert("KP_4", tr("4")); knownAliases.insert("KP_5", tr("5")); knownAliases.insert("KP_6", tr("6")); knownAliases.insert("KP_7", tr("7")); knownAliases.insert("KP_8", tr("8")); knownAliases.insert("KP_9", tr("9")); knownAliases.insert("KP_0", tr("0")); knownAliases.insert("Num_Lock", tr("NUM\nLK")); knownAliases.insert("KP_Divide", tr("/")); knownAliases.insert("KP_Multiply", tr("*")); knownAliases.insert("KP_Subtract", tr("-")); knownAliases.insert("KP_Add", tr("+")); knownAliases.insert("KP_Enter", tr("Enter")); knownAliases.insert("KP_Decimal", tr(".")); knownAliases.insert("KP_Delete", tr("Del")); knownAliases.insert("asterisk", tr("*")); knownAliases.insert("less", tr("<")); knownAliases.insert("colon", tr(":")); knownAliases.insert("Super_L", tr("Super (L)")); knownAliases.insert("Menu", tr("Menu")); knownAliases.insert("Up", tr("Up")); knownAliases.insert("Down", tr("Down")); knownAliases.insert("Left", tr("Left")); knownAliases.insert("Right", tr("Right")); } } int VirtualKeyPushButton::calculateFontSize() { qInstallMessageHandler(MessageHandler::myMessageOutput); QFont tempScaledFont(this->font()); tempScaledFont.setPointSize(10); QFontMetrics fm(tempScaledFont); int less_width = this->width() - 4; while ((less_width < fm.boundingRect(this->rect(), Qt::AlignCenter, this->text()).width()) && (tempScaledFont.pointSize() > 5)) { tempScaledFont.setPointSize(tempScaledFont.pointSize() - 1); fm = QFontMetrics(tempScaledFont); } return tempScaledFont.pointSize(); } int VirtualKeyPushButton::getKeycode() const { return keycode; } int VirtualKeyPushButton::getQkeyalias() const { return qkeyalias; } QString VirtualKeyPushButton::getXcodestring() const { return xcodestring; } QString VirtualKeyPushButton::getDisplayString() const { return displayString; } bool VirtualKeyPushButton::getCurrentlyActive() const { return currentlyActive; } bool VirtualKeyPushButton::getOnCurrentButton() const { return onCurrentButton; } AntiMicroX-antimicrox-2888bf6/src/keyboard/virtualkeypushbutton.h000066400000000000000000000033251377703515000253610ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VIRTUALKEYPUSHBUTTON_H #define VIRTUALKEYPUSHBUTTON_H #include class VirtualKeyPushButton : public QPushButton { Q_OBJECT public: explicit VirtualKeyPushButton(QString xcodestring, QWidget *parent = nullptr); int calculateFontSize(); QString getXcodestring() const; QString getDisplayString() const; int getKeycode() const; int getQkeyalias() const; bool getCurrentlyActive() const; bool getOnCurrentButton() const; static QHash knownAliases; protected: QString setDisplayString(QString xcodestring); void populateKnownAliases(); signals: void keycodeObtained(int code, int alias); private slots: void processSingleSelection(); private: int keycode; int qkeyalias; QString xcodestring; QString displayString; bool currentlyActive; bool onCurrentButton; }; #endif // VIRTUALKEYPUSHBUTTON_H AntiMicroX-antimicrox-2888bf6/src/keyboard/virtualmousepushbutton.cpp000066400000000000000000000051021377703515000262470ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "virtualmousepushbutton.h" #include "messagehandler.h" #include VirtualMousePushButton::VirtualMousePushButton(QString displayText, int code, JoyButtonSlot::JoySlotInputAction mode, QWidget *parent) : QPushButton(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((mode == JoyButtonSlot::JoyMouseButton) || (mode == JoyButtonSlot::JoyMouseMovement)) { this->setText(displayText); if (mode == JoyButtonSlot::JoyMouseMovement) { switch (code) { case JoyButtonSlot::MouseUp: case JoyButtonSlot::MouseDown: case JoyButtonSlot::MouseLeft: case JoyButtonSlot::MouseRight: { this->code = code; break; } default: { this->code = 0; break; } } } else { this->code = code; } this->mode = mode; } else { this->setText(tr("INVALID")); this->code = 0; this->mode = JoyButtonSlot::JoyMouseButton; } connect(this, &VirtualMousePushButton::clicked, this, &VirtualMousePushButton::createTempSlot); } int VirtualMousePushButton::getMouseCode() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return code; } JoyButtonSlot::JoySlotInputAction VirtualMousePushButton::getMouseMode() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return mode; } void VirtualMousePushButton::createTempSlot() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButtonSlot *tempslot = new JoyButtonSlot(this->code, this->mode, this); emit mouseSlotCreated(tempslot); } AntiMicroX-antimicrox-2888bf6/src/keyboard/virtualmousepushbutton.h000066400000000000000000000027271377703515000257260ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VIRTUALMOUSEPUSHBUTTON_H #define VIRTUALMOUSEPUSHBUTTON_H #include #include class VirtualMousePushButton : public QPushButton { Q_OBJECT public: explicit VirtualMousePushButton(QString displayText, int code, JoyButtonSlot::JoySlotInputAction mode, QWidget *parent = nullptr); int getMouseCode() const; JoyButtonSlot::JoySlotInputAction getMouseMode() const; signals: void mouseSlotCreated(JoyButtonSlot *tempslot); private slots: void createTempSlot(); private: int code; JoyButtonSlot::JoySlotInputAction mode; }; #endif // VIRTUALMOUSEPUSHBUTTON_H AntiMicroX-antimicrox-2888bf6/src/localantimicroserver.cpp000066400000000000000000000072221377703515000240100ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "localantimicroserver.h" #include "common.h" #include "messagehandler.h" #include #include #include #include LocalAntiMicroServer::LocalAntiMicroServer(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); localServer = new QLocalServer(this); } void LocalAntiMicroServer::startLocalServer() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (localServer != nullptr) { bool removedServer = QLocalServer::removeServer(PadderCommon::localSocketKey); if (!removedServer) qDebug() << "Couldn't remove local server named " << PadderCommon::localSocketKey << endl; if (localServer->maxPendingConnections() != 1) localServer->setMaxPendingConnections(1); if (!localServer->isListening()) { if (!localServer->listen(PadderCommon::localSocketKey)) { QTextStream errorstream(stderr); QString message("Could not start signal server. Profiles cannot be reloaded\n"); message.append("from command-line"); errorstream << tr(message.toStdString().c_str()) << endl; qDebug() << "Could not start signal server. Profiles cannot be reloaded\n" << " \nfrom command-line\n " << tr(message.toStdString().c_str()) << endl; } else { connect(localServer, &QLocalServer::newConnection, this, &LocalAntiMicroServer::handleOutsideConnection); } } } else { qDebug() << "LocalAntiMicroXServer::startLocalServer(): localServer is nullptr" << endl; } } void LocalAntiMicroServer::handleOutsideConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (localServer != nullptr) { QLocalSocket *socket = localServer->nextPendingConnection(); if (socket != nullptr) { qDebug() << "There is next pending connection: " << socket->socketDescriptor() << endl; connect(socket, &QLocalSocket::disconnected, this, &LocalAntiMicroServer::handleSocketDisconnect); connect(socket, &QLocalSocket::disconnected, socket, &QLocalSocket::deleteLater); } else { qDebug() << "There isn't next pending connection: " << endl; } } else { qDebug() << "LocalAntiMicroXServer::handleOutsideConnection(): localServer is nullptr" << endl; } } void LocalAntiMicroServer::handleSocketDisconnect() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit clientdisconnect(); } void LocalAntiMicroServer::close() { qInstallMessageHandler(MessageHandler::myMessageOutput); localServer->close(); } QLocalServer *LocalAntiMicroServer::getLocalServer() const { return localServer; } AntiMicroX-antimicrox-2888bf6/src/localantimicroserver.h000066400000000000000000000025131377703515000234530ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef LOCALANTIMICROSERVER_H #define LOCALANTIMICROSERVER_H #include class QLocalServer; class LocalAntiMicroServer : public QObject { Q_OBJECT public: explicit LocalAntiMicroServer(QObject *parent = nullptr); QLocalServer *getLocalServer() const; signals: void clientdisconnect(); public slots: void startLocalServer(); void handleOutsideConnection(); void handleSocketDisconnect(); void close(); private: QLocalServer *localServer; }; #endif // LOCALANTIMICROSERVER_H AntiMicroX-antimicrox-2888bf6/src/logger.cpp000066400000000000000000000265461377703515000210520ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "logger.h" #include "messagehandler.h" #include #include Logger *Logger::instance = nullptr; /** * @brief Outputs log messages to a given text stream. Client code * should determine whether it points to a console stream or * to a file. * @param Stream used to output text * @param Messages based of a given output level or lower will be logged * @param Parent object */ Logger::Logger(QTextStream *stream, LogLevel outputLevel, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); instance = this; instance->outputStream = stream; instance->outputLevel = outputLevel; instance->errorStream = nullptr; instance->pendingTimer.setInterval(1); instance->pendingTimer.setSingleShot(true); instance->writeTime = false; connect(instance, &Logger::pendingMessage, instance, &Logger::startPendingTimer); connect(&(instance->pendingTimer), &QTimer::timeout, instance, &Logger::Log); } /** * @brief Outputs log messages to a given text stream. Client code * should determine whether it points to a console stream or * to a file. * @param Stream used to output standard text * @param Stream used to output error text * @param Messages based of a given output level or lower will be logged * @param Parent object */ Logger::Logger(QTextStream *stream, QTextStream *errorStream, LogLevel outputLevel, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); instance = this; instance->outputStream = stream; instance->outputLevel = outputLevel; instance->errorStream = errorStream; instance->pendingTimer.setInterval(1); instance->pendingTimer.setSingleShot(true); instance->writeTime = false; connect(instance, &Logger::pendingMessage, instance, &Logger::startPendingTimer); connect(&(instance->pendingTimer), &QTimer::timeout, instance, &Logger::Log); } /** * @brief Close output stream and set instance to 0. */ Logger::~Logger() { qInstallMessageHandler(MessageHandler::myMessageOutput); closeLogger(); closeErrorLogger(); } /** * @brief Set the highest logging level. Determines which messages * are output to the output stream. * @param Highest log level utilized. */ void Logger::setLogLevel(LogLevel level) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); QMutexLocker locker(&instance->logMutex); Q_UNUSED(locker); instance->outputLevel = level; } /** * @brief Get the current output level associated with the logger. * @return Current output level */ Logger::LogLevel Logger::getCurrentLogLevel() { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); return instance->outputLevel; } void Logger::setCurrentStream(QTextStream *stream) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); QMutexLocker locker(&instance->logMutex); Q_UNUSED(locker); instance->outputStream->flush(); instance->outputStream = stream; } QTextStream *Logger::getCurrentStream() { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); return instance->outputStream; } void Logger::setCurrentErrorStream(QTextStream *stream) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); QMutexLocker locker(&instance->logMutex); Q_UNUSED(locker); if (instance->errorStream) { instance->errorStream->flush(); } instance->errorStream = stream; } QTextStream *Logger::getCurrentErrorStream() { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); return instance->errorStream; } /** * @brief Go through a list of pending messages and check if message should be * logged according to the set log level. Log the message to the output * stream. * @param Log level * @param String to write to output stream if appropriate to the current * log level. */ void Logger::Log() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMutexLocker locker(&logMutex); Q_UNUSED(locker); QListIterator iter(getPendingMessages()); while (iter.hasNext()) { LogMessage pendingMessage = iter.next(); logMessage(pendingMessage); } pendingMessages.clear(); instance->pendingTimer.stop(); } /** * @brief Flushes output stream and closes stream if requested. * @param Whether to close the current stream. Defaults to true. */ void Logger::closeLogger(bool closeStream) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (outputStream != nullptr) { outputStream->flush(); if (closeStream && (outputStream->device() != nullptr)) { QIODevice *device = outputStream->device(); if (device->isOpen()) { device->close(); } } } } /** * @brief Flushes output stream and closes stream if requested. * @param Whether to close the current stream. Defaults to true. */ void Logger::closeErrorLogger(bool closeStream) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (errorStream != nullptr) { errorStream->flush(); if (closeStream && (errorStream->device() != nullptr)) { QIODevice *device = errorStream->device(); if (device->isOpen()) { device->close(); } } } instance->pendingTimer.stop(); instance = nullptr; } /** * @brief Append message to list of messages that might get placed in the * log. Messages will be written later. * @param Log level * @param String to write to output stream if appropriate to the current * log level. * @param Whether the logger should add a newline to the end of the message. */ void Logger::appendLog(LogLevel level, const QString &message, bool newline) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); QMutexLocker locker(&instance->logMutex); Q_UNUSED(locker); LogMessage temp; temp.level = level; temp.message = QString(message); temp.newline = newline; instance->pendingMessages.append(temp); emit instance->pendingMessage(); } /** * @brief Immediately write a message to a text stream. * @param Log level * @param String to write to output stream if appropriate to the current * log level. * @param Whether the logger should add a newline to the end of the message. */ void Logger::directLog(LogLevel level, const QString &message, bool newline) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); QMutexLocker locker(&instance->logMutex); Q_UNUSED(locker); LogMessage temp; temp.level = level; temp.message = QString(message); temp.newline = newline; instance->logMessage(temp); } /** * @brief Write an individual message to the text stream. * @param LogMessage instance for a single message */ void Logger::logMessage(LogMessage msg) { qInstallMessageHandler(MessageHandler::myMessageOutput); LogLevel level = msg.level; QString message = msg.message; bool newline = msg.newline; if ((outputLevel != LOG_NONE) && (level <= outputLevel)) { QString displayTime = ""; QString initialPrefix = ""; QString finalMessage = QString(); if ((outputLevel > LOG_INFO) || writeTime) { displayTime = QString("[%1] - ").arg(QTime::currentTime().toString("hh:mm:ss.zzz")); initialPrefix = displayTime; } QTextStream *writeStream = outputStream; if ((level < LOG_INFO) && (errorStream != nullptr)) { writeStream = errorStream; } finalMessage.append(initialPrefix).append(message); if (newline) { finalMessage.append("\n"); } *writeStream << finalMessage; writeStream->flush(); emit stringWritten(finalMessage); } } /** * @brief Get the associated timer used by the logger. * @return QTimer instance */ QTimer *Logger::getLogTimer() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &pendingTimer; } /** * @brief Stop the logger's timer if it is currently active. */ void Logger::stopLogTimer() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (pendingTimer.isActive()) { pendingTimer.stop(); } } /** * @brief Set whether the current time should be written with a message. * This property is only used if outputLevel is set to LOG_INFO. * @param status */ void Logger::setWriteTime(bool status) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); QMutexLocker locker(&instance->logMutex); Q_UNUSED(locker); writeTime = status; } /** * @brief Get whether the current time should be written with a LOG_INFO * message. * @return Whether the current time is written with a LOG_INFO message */ bool Logger::getWriteTime() { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); return writeTime; } void Logger::startPendingTimer() { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); if (!instance->pendingTimer.isActive()) { instance->pendingTimer.start(); } } void Logger::setCurrentLogFile(QString filename) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); if (instance->outputFile.isOpen()) { instance->closeLogger(true); } instance->outputFile.setFileName(filename); instance->outputFile.open(QIODevice::WriteOnly | QIODevice::Append); instance->outFileStream.setDevice(&instance->outputFile); instance->setCurrentStream(&instance->outFileStream); instance->LogInfo(QObject::tr("Logging started"), true, true); } void Logger::setCurrentErrorLogFile(QString filename) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(instance != nullptr); if (instance->errorFile.isOpen()) { instance->closeErrorLogger(true); } instance->errorFile.setFileName(filename); instance->errorFile.open(QIODevice::WriteOnly | QIODevice::Append); instance->outErrorFileStream.setDevice(&instance->errorFile); instance->setCurrentErrorStream(&instance->outErrorFileStream); } QList const &Logger::getPendingMessages() { return pendingMessages; } AntiMicroX-antimicrox-2888bf6/src/logger.h000066400000000000000000000102631377703515000205040ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef LOGGER_H #define LOGGER_H #include #include #include #include #include class Logger : public QObject { Q_OBJECT public: enum LogLevel { LOG_NONE = 0, LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG, LOG_MAX = LOG_DEBUG }; typedef struct { QString message; LogLevel level; bool newline; } LogMessage; explicit Logger(QTextStream *stream, LogLevel outputLevel = LOG_INFO, QObject *parent = nullptr); explicit Logger(QTextStream *stream, QTextStream *errorStream, LogLevel outputLevel = LOG_INFO, QObject *parent = nullptr); ~Logger(); static void setLogLevel(LogLevel level); LogLevel getCurrentLogLevel(); QList const &getPendingMessages(); static void setCurrentStream(QTextStream *stream); static void setCurrentLogFile(QString filename); static QTextStream *getCurrentStream(); static void setCurrentErrorStream(QTextStream *stream); static void setCurrentErrorLogFile(QString filename); static QTextStream *getCurrentErrorStream(); QTimer *getLogTimer(); void stopLogTimer(); bool getWriteTime(); void setWriteTime(bool status); static void appendLog(LogLevel level, const QString &message, bool newline = true); static void directLog(LogLevel level, const QString &message, bool newline = true); // Some convenience functions that will hopefully speed up // logging operations. inline static void LogInfo(const QString &message, bool newline = true, bool direct = false) { if (!direct) { appendLog(LOG_INFO, message, newline); } else { directLog(LOG_INFO, message, newline); } } inline static void LogDebug(const QString &message, bool newline = true, bool direct = false) { if (!direct) { appendLog(LOG_DEBUG, message, newline); } else { directLog(LOG_DEBUG, message, newline); } } inline static void LogWarning(const QString &message, bool newline = true, bool direct = false) { if (!direct) { appendLog(LOG_WARNING, message, newline); } else { directLog(LOG_WARNING, message, newline); } } inline static void LogError(const QString &message, bool newline = true, bool direct = false) { if (!direct) { appendLog(LOG_ERROR, message, newline); } else { directLog(LOG_ERROR, message, newline); } } inline static Logger *getInstance() { Q_ASSERT(instance != nullptr); return instance; } static Logger *instance; protected: void closeLogger(bool closeStream = true); void closeErrorLogger(bool closeStream = true); void logMessage(LogMessage msg); bool writeTime; QFile outputFile; QFile errorFile; QTextStream outFileStream; QTextStream *outputStream; QTextStream outErrorFileStream; QTextStream *errorStream; LogLevel outputLevel; QMutex logMutex; QTimer pendingTimer; QList pendingMessages; signals: void stringWritten(QString text); void pendingMessage(); public slots: void Log(); void startPendingTimer(); }; #endif // LOGGER_H AntiMicroX-antimicrox-2888bf6/src/main.cpp000066400000000000000000001020021377703515000204750ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "antimicrosettings.h" #include "antkeymapper.h" #include "applaunchhelper.h" #include "autoprofileinfo.h" #include "commandlineutility.h" #include "common.h" #include "inputdaemon.h" #include "inputdevice.h" #include "joybuttonslot.h" #include "localantimicroserver.h" #include "mainwindow.h" #include "setjoystick.h" #include "simplekeygrabberbutton.h" #include "eventhandlerfactory.h" #include "logger.h" #include "messagehandler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #include #include #include #ifdef WITH_X11 #include "x11extras.h" #endif #endif static void termSignalTermHandler(int signal) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(signal) qApp->exit(0); } static void termSignalIntHandler(int signal) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(signal) qApp->exit(0); } // was non static static void deleteInputDevices(QMap *joysticks) { qInstallMessageHandler(MessageHandler::myMessageOutput); QMapIterator iter(*joysticks); while (iter.hasNext()) { InputDevice *joystick = iter.next().value(); if (joystick != nullptr) { delete joystick; joystick = nullptr; } } joysticks->clear(); } /** * @brief Function used for copying settings used by antimicro and * previous revisions of antimicrox to provide backward compatibility */ void importLegacySettingsIfExist() { qDebug() << "Importing settings"; const QFileInfo config(PadderCommon::configFilePath()); const bool configExists = config.exists() && config.isFile(); // 'antimicroX' const QFileInfo legacyConfig(PadderCommon::configLegacyFilePath()); const bool legacyConfigExists = legacyConfig.exists() && legacyConfig.isFile(); // 'antimicro' const QFileInfo legacyAntimicroConfig(PadderCommon::configAntimicroLegacyFilePath()); const bool legacyAntimicroConfigExists = legacyAntimicroConfig.exists() && legacyAntimicroConfig.isFile(); const bool requireMigration = !configExists && (legacyConfigExists || legacyAntimicroConfigExists); if (requireMigration) { const QFileInfo fileToCopy = legacyConfigExists ? legacyConfig : legacyAntimicroConfig; const bool copySuccess = QFile::copy(fileToCopy.canonicalFilePath(), PadderCommon::configFilePath()); qDebug() << "Legacy settings found"; const QString successMessage = QString("Your original settings (previously stored in %1) " "have been copied to " "~/.config/antimicrox to ensure consistent naming across " "entire project.\nIf you want you can " "delete the original directory or leave it as it is.") .arg(fileToCopy.canonicalFilePath()); const QString errorMessage = QString("Some problem with settings migration occurred.\nOriginal " "configs are stored in %1 " "but their new location is ~/.config/antimicrox.\n" "You can migrate manually by renaming old directory and " "renaming file to antimicrox_settings.ini.") .arg(fileToCopy.canonicalFilePath()); QMessageBox msgBox; if (copySuccess) { qDebug() << "Legacy settings copied"; msgBox.setText(successMessage); } else { qWarning() << "Problem with importing settings from: " << fileToCopy.canonicalFilePath() << " to: " << PadderCommon::configFilePath(); msgBox.setText(errorMessage); } msgBox.exec(); } } int main(int argc, char *argv[]) { qInstallMessageHandler(MessageHandler::myMessageOutput); QApplication antimicrox(argc, argv); QCoreApplication::setApplicationName("antimicrox"); QCoreApplication::setApplicationVersion(PadderCommon::programVersion); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType("SDL_JoystickID"); qRegisterMetaType("JoyButtonSlot::JoySlotInputAction"); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { XInitThreads(); } #endif QFile logFile; QTextStream logFileStream; QTextStream outstream(stdout); QTextStream errorstream(stderr); QCommandLineParser parser; parser.setApplicationDescription( QCoreApplication::translate("antimicrox", "Graphical program used to map keyboard buttons and mouse controls to " "a " "gamepad. Useful for playing games with no gamepad support.")); parser.addHelpOption(); parser.addVersionOption(); #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) parser.addOptions({ // A boolean option with a single name (-p) {"tray", QCoreApplication::translate("main", "Launch program in system tray only.")}, // A boolean option with multiple names (-f, --force) {"no-tray", QCoreApplication::translate("main", "Launch program with the tray menu disabled")}, // An option with a value {"hidden", QCoreApplication::translate("main", "Launch program without the main window displayed")}, {"profile", QCoreApplication::translate("main", "Launch program with the configuration file selected as " "the default for " "selected controllers. Defaults to all controllers"), QCoreApplication::translate("main", "location")}, {"profile-controller", QCoreApplication::translate("main", "Apply configuration file to a specific controller. Value " "can be a controller index, name, or GUID"), QCoreApplication::translate("main", "value")}, {"unload", QCoreApplication::translate("main", "Unload currently enabled profile(s)"), QCoreApplication::translate("main", "value(s)")}, {"startSet", QCoreApplication::translate("main", "Start joysticks on a specific set. Value can be a " "controller index, name, or GUID"), QCoreApplication::translate("main", "number value")}, {{"daemon", "d"}, QCoreApplication::translate("main", "Launch program as a daemon. Use only on Linux.")}, {"log-level", QCoreApplication::translate("main", "Enable logging. Levels (from the least strict): warn,info,debug"), QCoreApplication::translate("main", "log-type")}, {"log-file", QCoreApplication::translate("main", "Choose a file for logs writing"), QCoreApplication::translate("main", "filename")}, {"eventgen", QCoreApplication::translate("main", "Choose between using XTest support and uinput support " "for event generation. Use only if you have " "enabled xtest and uinput options on Linux or vmulti on " "Windows. Default: xtest."), QCoreApplication::translate("main", "event-generation-type"), "xtest"}, // default {{"list", "l"}, QCoreApplication::translate("main", "Print information about joysticks detected by SDL. Use " "only if you have sdl " "library. You can check your controller index, name or " "even GUID.")}, // {"display", // QCoreApplication::translate("main", "Use specified display for // X11 calls")}, // {"next", // QCoreApplication::translate("main", "Advance profile loading set // options")}, // {"map", // QCoreApplication::translate("main", "Open game controller // mapping window of selected controller. Value can be // a controller index or GUID."), // QCoreApplication::translate("main", "value")}, }); #else parser.addOption(QCommandLineOption("tray", QObject::trUtf8("Launch program in system tray only."))); parser.addOption(QCommandLineOption("no-tray", QObject::trUtf8("Launch program with the tray menu disabled"))); parser.addOption(QCommandLineOption("hidden", QObject::trUtf8("Launch program without the main window displayed"))); parser.addOption(QCommandLineOption("profile", QObject::trUtf8("Launch program with the configuration file selected as the " "default " "for selected controllers. Defaults to all controllers"), QObject::trUtf8("location"))); parser.addOption(QCommandLineOption("profile-controller", QObject::trUtf8("Apply configuration file to a specific controller. " "Value can be a controller index, name, or GUID"), QObject::trUtf8("value"))); parser.addOption( QCommandLineOption("unload", QObject::trUtf8("Unload currently enabled profile(s)"), QObject::trUtf8("value(s)"))); parser.addOption(QCommandLineOption("startSet", QObject::trUtf8("Start joysticks on a specific set. Value can be a " "controller index, name, or GUID"), QObject::trUtf8("number value"))); parser.addOption(QCommandLineOption(QStringList() << "daemon" << "d", QObject::trUtf8("Launch program as a daemon. Use only on Linux."))); parser.addOption(QCommandLineOption("log-level", QObject::trUtf8("Enable logging"), QObject::trUtf8("log-type"))); parser.addOption( QCommandLineOption("log-file", QObject::trUtf8("Choose a file for logs writing"), QObject::trUtf8("filename"))); parser.addOption(QCommandLineOption("eventgen", QObject::trUtf8("Choose between using XTest support and uinput support " "for event generation. Use only if you have " "enabled xtest and uinput options on Linux or vmulti " "on Windows. Default: xtest."), QObject::trUtf8("event-generation-type"), "xtest")); parser.addOption(QCommandLineOption(QStringList() << "list" << "l", QObject::trUtf8("Print information about joysticks detected by SDL. " "Use only if you have sdl " "library. You can check your controller index, name or " "even GUID."))); #endif parser.process(antimicrox); CommandLineUtility cmdutility; cmdutility.parseArguments(&parser); Logger appLogger(&outstream, &errorstream); // If a log level wasn't specified at the command-line, then use a default. if (cmdutility.getCurrentLogLevel() == Logger::LOG_NONE) { appLogger.setLogLevel(Logger::LOG_WARNING); } else if (cmdutility.getCurrentLogLevel() != appLogger.getCurrentLogLevel()) { appLogger.setLogLevel(cmdutility.getCurrentLogLevel()); } if (!cmdutility.getCurrentLogFile().isEmpty()) { appLogger.setCurrentLogFile(cmdutility.getCurrentLogFile()); appLogger.setCurrentErrorStream(nullptr); } Q_INIT_RESOURCE(resources); QDir configDir(PadderCommon::configPath()); if (!configDir.exists()) { configDir.mkpath(PadderCommon::configPath()); } QMap *joysticks = new QMap(); QThread *inputEventThread = nullptr; // Cross-platform way of performing IPC. Currently, // only establish a connection and then disconnect. // In the future, there might be a reason to actually send // messages to the QLocalServer. QLocalSocket socket; if ((socket.serverName() == QString())) { socket.connectToServer(PadderCommon::localSocketKey); if (!socket.waitForConnected(3000)) { qDebug() << "Socket's state: " << socket.state() << endl; qDebug() << "Server name: " << socket.serverName() << endl; qDebug() << "Socket descriptor: " << socket.socketDescriptor() << endl; qDebug() << "The connection hasn't been established: \nerror text -> " << socket.error() << "\nerror text 2 ->" << socket.errorString() << endl; } else { qDebug() << "Socket connected" << endl; } } else { socket.abort(); } if (!socket.isValid()) { qDebug() << "Socket is not valid" << endl; qDebug() << "Socket's state: " << socket.state() << endl; qDebug() << "Server name: " << socket.serverName() << endl; qDebug() << "Socket descriptor: " << socket.socketDescriptor() << endl; } if (socket.state() == QLocalSocket::ConnectedState) { // An instance of this program is already running. // Save app config and exit. AntiMicroSettings settings(PadderCommon::configFilePath(), QSettings::IniFormat); // Update log info based on config values if (cmdutility.getCurrentLogLevel() == Logger::LOG_NONE && settings.contains("LogLevel")) { appLogger.setLogLevel(static_cast(settings.value("LogLevel").toInt())); } if (cmdutility.getCurrentLogFile().isEmpty() && settings.contains("LogFile")) { appLogger.setCurrentLogFile(settings.value("LogFile").toString()); appLogger.setCurrentErrorStream(nullptr); } QPointer joypad_worker = new InputDaemon(joysticks, &settings, false); MainWindow mainWindow(joysticks, &cmdutility, &settings, false); mainWindow.fillButtons(); mainWindow.alterConfigFromSettings(); if (!cmdutility.hasError() && (cmdutility.hasProfile() || cmdutility.hasProfileInOptions())) { mainWindow.saveAppConfig(); } else if (!cmdutility.hasError() && cmdutility.isUnloadRequested()) { mainWindow.saveAppConfig(); } mainWindow.removeJoyTabs(); QObject::connect(&antimicrox, &QApplication::aboutToQuit, joypad_worker.data(), &InputDaemon::quit); #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) QTimer::singleShot(50, &antimicrox, &QApplication::quit); #else QTimer::singleShot(50, &antimicrox, SLOT(quit())); #endif int result = antimicrox.exec(); settings.sync(); socket.disconnectFromServer(); if (socket.waitForDisconnected(2000)) qDebug() << "Socket " << socket.socketDescriptor() << " disconnected!" << endl; deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; if (!joypad_worker.isNull()) { delete joypad_worker; joypad_worker.clear(); } return result; } LocalAntiMicroServer *localServer = nullptr; #ifdef Q_OS_UNIX if (cmdutility.launchAsDaemon()) { pid_t pid, sid; pid = fork(); // Fork the Parent Process if (pid == 0) { appLogger.LogInfo(QObject::tr("Daemon launched"), true, true); localServer = new LocalAntiMicroServer(); localServer->startLocalServer(); } else if (pid < 0) { appLogger.LogError(QObject::tr("Failed to launch daemon"), true, true); deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; exit(EXIT_FAILURE); } else if (pid > 0) // We got a good pid, Close the Parent Process { appLogger.LogInfo(QObject::tr("Launching daemon"), true, true); deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; exit(EXIT_SUCCESS); } #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { if (cmdutility.getDisplayString().isEmpty()) { X11Extras::getInstance()->syncDisplay(); } else { X11Extras::setCustomDisplay(cmdutility.getDisplayString()); X11Extras::getInstance()->syncDisplay(); if (X11Extras::getInstance()->display() == nullptr) { appLogger.LogError(QObject::tr("Display string \"%1\" is not valid.").arg(cmdutility.getDisplayString()), true, true); deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; delete localServer; localServer = nullptr; X11Extras::getInstance()->closeDisplay(); exit(EXIT_FAILURE); } } } #endif umask(0); // Change File Mask sid = setsid(); // Create a new Signature Id for our child if (sid < 0) { appLogger.LogError(QObject::tr("Failed to set a signature id for the daemon"), true, true); deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; delete localServer; localServer = nullptr; #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { X11Extras::getInstance()->closeDisplay(); } #endif exit(EXIT_FAILURE); } if ((chdir("/")) < 0) { appLogger.LogError(QObject::tr("Failed to change working directory to /"), true, true); deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; delete localServer; localServer = nullptr; #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { X11Extras::getInstance()->closeDisplay(); } #endif exit(EXIT_FAILURE); } // Close Standard File Descriptors close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } else { localServer = new LocalAntiMicroServer(); localServer->startLocalServer(); #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { if (!cmdutility.getDisplayString().isEmpty()) { X11Extras::getInstance()->syncDisplay(cmdutility.getDisplayString()); if (X11Extras::getInstance()->display() == nullptr) { appLogger.LogError(QObject::tr("Display string \"%1\" is not valid.").arg(cmdutility.getDisplayString()), true, true); deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; delete localServer; localServer = nullptr; X11Extras::getInstance()->closeDisplay(); exit(EXIT_FAILURE); } } } #endif } #endif antimicrox.setQuitOnLastWindowClosed(false); QStringList appDirsLocations = QStandardPaths::standardLocations(QStandardPaths::DataLocation); appDirsLocations.append(QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)); QStringList themePathsTries = QStringList(); QList::const_iterator i; for (i = appDirsLocations.constBegin(); i != appDirsLocations.constEnd(); ++i) { themePathsTries.append(QString("%1%2").arg(*i).arg("/icons")); qDebug() << QString("%1%2").arg(*i).arg("/icons"); } QIcon::setThemeSearchPaths(themePathsTries); qDebug() << "Theme name: " << QIcon::themeName(); importLegacySettingsIfExist(); AntiMicroSettings *settings = new AntiMicroSettings(PadderCommon::configFilePath(), QSettings::IniFormat); settings->importFromCommandLine(cmdutility); // Update log info based on config values if (cmdutility.getCurrentLogLevel() == Logger::LOG_NONE && settings->contains("LogLevel")) { appLogger.setLogLevel(static_cast(settings->value("LogLevel").toInt())); } if (cmdutility.getCurrentLogFile().isEmpty() && settings->contains("LogFile")) { appLogger.setCurrentLogFile(settings->value("LogFile").toString()); appLogger.setCurrentErrorStream(nullptr); } QString targetLang = QLocale::system().name(); if (settings->contains("Language")) { targetLang = settings->value("Language").toString(); } QTranslator qtTranslator; #if defined(Q_OS_UNIX) QString transPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); if (QDir(transPath).entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).count() == 0) { qtTranslator.load(QString("qt_").append(targetLang), "/app/share/antimicrox/translations"); } else { qtTranslator.load(QString("qt_").append(targetLang), transPath); } #endif antimicrox.installTranslator(&qtTranslator); QTranslator myappTranslator; if (QDir("/app/share/antimicrox").entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).count() > 0) { myappTranslator.load(QString("antimicrox_").append(targetLang), "app/share/antimicrox/translations"); } else { myappTranslator.load(QString("antimicrox_").append(targetLang), QApplication::applicationDirPath().append("/../share/antimicrox/translations")); } antimicrox.installTranslator(&myappTranslator); // Have program handle SIGTERM struct sigaction termaction; termaction.sa_handler = &termSignalTermHandler; sigemptyset(&termaction.sa_mask); termaction.sa_flags = 0; sigaction(SIGTERM, &termaction, nullptr); // Have program handle SIGINT struct sigaction termint; termint.sa_handler = &termSignalIntHandler; sigemptyset(&termint.sa_mask); termint.sa_flags = 0; sigaction(SIGINT, &termint, nullptr); if (cmdutility.shouldListControllers()) { QPointer joypad_worker = new InputDaemon(joysticks, settings, false); AppLaunchHelper mainAppHelper(settings, false); mainAppHelper.printControllerList(joysticks); joypad_worker->quit(); joypad_worker->deleteJoysticks(); delete joysticks; joysticks = nullptr; delete localServer; localServer = nullptr; #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { X11Extras::getInstance()->closeDisplay(); } #endif return 0; } else if (cmdutility.shouldMapController()) { PadderCommon::mouseHelperObj.initDeskWid(); QPointer joypad_worker = new InputDaemon(joysticks, settings); inputEventThread = new QThread; MainWindow *mainWindow = new MainWindow(joysticks, &cmdutility, settings); QObject::connect(&antimicrox, &QApplication::aboutToQuit, mainWindow, &MainWindow::removeJoyTabs); QObject::connect(&antimicrox, &QApplication::aboutToQuit, joypad_worker.data(), &InputDaemon::quit); QObject::connect(&antimicrox, &QApplication::aboutToQuit, joypad_worker.data(), &InputDaemon::deleteJoysticks, Qt::BlockingQueuedConnection); QObject::connect(&antimicrox, &QApplication::aboutToQuit, &PadderCommon::mouseHelperObj, &MouseHelper::deleteDeskWid, Qt::DirectConnection); QObject::connect(&antimicrox, &QApplication::aboutToQuit, joypad_worker.data(), &InputDaemon::deleteLater, Qt::BlockingQueuedConnection); mainWindow->makeJoystickTabs(); #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) QTimer::singleShot(0, mainWindow, &MainWindow::controllerMapOpening); #else QTimer::singleShot(0, mainWindow, SLOT(controllerMapOpening())); #endif joypad_worker->startWorker(); joypad_worker->moveToThread(inputEventThread); PadderCommon::mouseHelperObj.moveToThread(inputEventThread); inputEventThread->start(QThread::HighPriority); int app_result = antimicrox.exec(); appLogger.Log(); // Log any remaining messages if they exist. inputEventThread->quit(); inputEventThread->wait(); delete joysticks; joysticks = nullptr; delete localServer; localServer = nullptr; delete inputEventThread; inputEventThread = nullptr; #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { X11Extras::getInstance()->closeDisplay(); } #endif delete mainWindow; mainWindow = nullptr; if (!joypad_worker.isNull()) { delete joypad_worker; joypad_worker.clear(); } return app_result; } bool status = true; QString eventGeneratorIdentifier = QString(); AntKeyMapper *keyMapper = nullptr; EventHandlerFactory *factory = EventHandlerFactory::getInstance(cmdutility.getEventGenerator()); if (!factory) { status = false; } else { eventGeneratorIdentifier = factory->handler()->getIdentifier(); keyMapper = AntKeyMapper::getInstance(eventGeneratorIdentifier); status = factory->handler()->init(); factory->handler()->printPostMessages(); } #if defined(WITH_UINPUT) && defined(WITH_XTEST) // Use fallback event handler. if (!status && cmdutility.getEventGenerator() != EventHandlerFactory::fallBackIdentifier()) { QString eventDisplayName = EventHandlerFactory::handlerDisplayName(EventHandlerFactory::fallBackIdentifier()); appLogger.LogInfo(QObject::tr("Attempting to use fallback option %1 for event generation.").arg(eventDisplayName)); if (keyMapper != nullptr) { keyMapper->deleteInstance(); keyMapper = nullptr; } factory->deleteInstance(); factory = EventHandlerFactory::getInstance(EventHandlerFactory::fallBackIdentifier()); if (!factory) { status = false; } else { eventGeneratorIdentifier = factory->handler()->getIdentifier(); keyMapper = AntKeyMapper::getInstance(eventGeneratorIdentifier); status = factory->handler()->init(); factory->handler()->printPostMessages(); } } #endif if (!status) { appLogger.LogError(QObject::tr("Failed to open event generator. Exiting.")); appLogger.Log(); deleteInputDevices(joysticks); delete joysticks; joysticks = nullptr; delete localServer; localServer = nullptr; if (keyMapper != nullptr) { keyMapper->deleteInstance(); keyMapper = nullptr; } #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { X11Extras::getInstance()->closeDisplay(); } #endif return EXIT_FAILURE; } else { appLogger.LogInfo(QObject::tr("Using %1 as the event generator.").arg(factory->handler()->getName())); } PadderCommon::mouseHelperObj.initDeskWid(); QPointer joypad_worker = new InputDaemon(joysticks, settings); inputEventThread = new QThread(); MainWindow *mainWindow = new MainWindow(joysticks, &cmdutility, settings); mainWindow->setAppTranslator(&qtTranslator); mainWindow->setTranslator(&myappTranslator); AppLaunchHelper mainAppHelper(settings, mainWindow->getGraphicalStatus()); QObject::connect(mainWindow, &MainWindow::joystickRefreshRequested, joypad_worker.data(), &InputDaemon::refresh); QObject::connect(joypad_worker.data(), &InputDaemon::joystickRefreshed, mainWindow, &MainWindow::fillButtonsID); QObject::connect(joypad_worker.data(), &InputDaemon::joysticksRefreshed, mainWindow, &MainWindow::fillButtonsMap); QObject::connect(&antimicrox, &QApplication::aboutToQuit, localServer, &LocalAntiMicroServer::close); QObject::connect(&antimicrox, &QApplication::aboutToQuit, mainWindow, &MainWindow::saveAppConfig); QObject::connect(&antimicrox, &QApplication::aboutToQuit, mainWindow, &MainWindow::removeJoyTabs); QObject::connect(&antimicrox, &QApplication::aboutToQuit, &mainAppHelper, &AppLaunchHelper::revertMouseThread); QObject::connect(&antimicrox, &QApplication::aboutToQuit, joypad_worker.data(), &InputDaemon::quit); QObject::connect(&antimicrox, &QApplication::aboutToQuit, joypad_worker.data(), &InputDaemon::deleteJoysticks); QObject::connect(&antimicrox, &QApplication::aboutToQuit, joypad_worker.data(), &InputDaemon::deleteLater); QObject::connect(&antimicrox, &QApplication::aboutToQuit, &PadderCommon::mouseHelperObj, &MouseHelper::deleteDeskWid, Qt::DirectConnection); QObject::connect(localServer, &LocalAntiMicroServer::clientdisconnect, mainWindow, &MainWindow::handleInstanceDisconnect); QObject::connect(mainWindow, &MainWindow::mappingUpdated, joypad_worker.data(), &InputDaemon::refreshMapping); QObject::connect(joypad_worker.data(), &InputDaemon::deviceUpdated, mainWindow, &MainWindow::testMappingUpdateNow); QObject::connect(joypad_worker.data(), &InputDaemon::deviceRemoved, mainWindow, &MainWindow::removeJoyTab); QObject::connect(joypad_worker.data(), &InputDaemon::deviceAdded, mainWindow, &MainWindow::addJoyTab); mainAppHelper.initRunMethods(); QTimer::singleShot(0, mainWindow, SLOT(fillButtons())); QTimer::singleShot(0, mainWindow, SLOT(alterConfigFromSettings())); QTimer::singleShot(0, mainWindow, SLOT(changeWindowStatus())); mainAppHelper.changeMouseThread(inputEventThread); joypad_worker->startWorker(); joypad_worker->moveToThread(inputEventThread); PadderCommon::mouseHelperObj.moveToThread(inputEventThread); inputEventThread->start(QThread::HighPriority); int app_result = antimicrox.exec(); appLogger.Log(); // Log any remaining messages if they exist. appLogger.LogInfo(QObject::tr("Quitting Program"), true, true); delete localServer; localServer = nullptr; inputEventThread->quit(); inputEventThread->wait(); delete inputEventThread; inputEventThread = nullptr; delete joysticks; joysticks = nullptr; AntKeyMapper::getInstance()->deleteInstance(); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { X11Extras::getInstance()->closeDisplay(); } #endif EventHandlerFactory::getInstance()->handler()->cleanup(); EventHandlerFactory::getInstance()->deleteInstance(); delete mainWindow; mainWindow = nullptr; delete settings; settings = nullptr; if (!joypad_worker.isNull()) { delete joypad_worker; joypad_worker.clear(); } return app_result; } AntiMicroX-antimicrox-2888bf6/src/mainsettingsdialog.cpp000066400000000000000000002116201377703515000234450ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mainsettingsdialog.h" #include "addeditautoprofiledialog.h" #include "antimicrosettings.h" #include "autoprofileinfo.h" #include "common.h" #include "editalldefaultautoprofiledialog.h" #include "eventhandlerfactory.h" #include "globalvariables.h" #include "inputdevice.h" #include "messagehandler.h" #ifdef WITH_X11 #include "x11extras.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const QString RUNATSTARTUPREGKEY("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"); static const QString RUNATSTARTUPLOCATION(QString("%0\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\antimicrox.lnk") .arg(QString::fromUtf8(qgetenv("AppData")))); MainSettingsDialog::MainSettingsDialog(AntiMicroSettings *settings, QList *devices, QWidget *parent) : QDialog(parent, Qt::Dialog) , ui(new Ui::MainSettingsDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); ui->profileOpenDirPushButton->setIcon( PadderCommon::loadIcon("document-open", ":/icons/actions/document_open_folder.png")); ui->logFilePushButton->setIcon(PadderCommon::loadIcon("document-open", ":/icons/actions/document_open_folder.png")); this->settings = settings; this->allDefaultProfile = nullptr; this->connectedDevices = devices; fillControllerMappingsTable(); settings->getLock()->lock(); bool attachedNumKeypad = settings->value("AttachNumKeypad", false).toBool(); QString defaultProfileDir = settings->value("DefaultProfileDir", "").toString(); int numberRecentProfiles = settings->value("NumberRecentProfiles", 5).toInt(); bool closeToTray = settings->value("CloseToTray", false).toBool(); if (!defaultProfileDir.isEmpty() && QDir(defaultProfileDir).exists()) { ui->profileDefaultDirLineEdit->setText(defaultProfileDir); } else { ui->profileDefaultDirLineEdit->setText(PadderCommon::preferredProfileDir(settings)); } ui->numberRecentProfileSpinBox->setValue(numberRecentProfiles); if (closeToTray) { ui->closeToTrayCheckBox->setChecked(true); } changePresetLanguage(); ui->autoProfileTableWidget->hideColumn(7); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { populateAutoProfiles(); fillAllAutoProfilesTable(); fillGUIDComboBox(); } else { delete ui->categoriesListWidget->item(2); ui->stackedWidget->removeWidget(ui->page_2); } #elif !defined(WITH_X11) delete ui->categoriesListWidget->item(2); ui->stackedWidget->removeWidget(ui->page_2); #endif QString autoProfileActive = settings->value("AutoProfiles/AutoProfilesActive", "").toString(); if (autoProfileActive == "1") { ui->activeCheckBox->setChecked(true); ui->autoProfileTableWidget->setEnabled(true); ui->autoProfileAddPushButton->setEnabled(true); } ui->launchAtWinStartupCheckBox->setVisible(false); // TODO #115 ui->keyRepeatGroupBox->setVisible(false); bool useSingleProfileList = settings->value("TrayProfileList", false).toBool(); if (useSingleProfileList) { ui->traySingleProfileListCheckBox->setChecked(true); } bool minimizeToTaskBar = settings->value("MinimizeToTaskbar", false).toBool(); if (minimizeToTaskBar) { ui->minimizeTaskbarCheckBox->setChecked(true); } bool hideEmpty = settings->value("HideEmptyButtons", false).toBool(); if (hideEmpty) { ui->hideEmptyCheckBox->setChecked(true); } bool autoOpenLastProfile = settings->value("AutoOpenLastProfile", true).toBool(); if (autoOpenLastProfile) { ui->autoLoadPreviousCheckBox->setChecked(true); } else { ui->autoLoadPreviousCheckBox->setChecked(false); } bool launchInTray = settings->value("LaunchInTray", false).toBool(); if (launchInTray) { ui->launchInTrayCheckBox->setChecked(true); } ui->associateProfilesCheckBox->setVisible(false); ui->disableWindowsEnhancedPointCheckBox->setVisible(false); if (attachedNumKeypad) ui->attachNumKeypadCheckbox->setChecked(true); bool smoothingEnabled = settings->value("Mouse/Smoothing", false).toBool(); if (smoothingEnabled) { ui->smoothingEnableCheckBox->setChecked(true); ui->historySizeSpinBox->setEnabled(true); ui->weightModifierDoubleSpinBox->setEnabled(true); } int historySize = settings->value("Mouse/HistorySize", 0).toInt(); if ((historySize > 0) && (historySize <= GlobalVariables::JoyButton::MAXIMUMMOUSEHISTORYSIZE)) { ui->historySizeSpinBox->setValue(historySize); } double weightModifier = settings->value("Mouse/WeightModifier", 0).toDouble(); if ((weightModifier > 0.0) && (weightModifier <= GlobalVariables::JoyButton::MAXIMUMWEIGHTMODIFIER)) { ui->weightModifierDoubleSpinBox->setValue(weightModifier); } for (int i = 1; i <= GlobalVariables::JoyButton::MAXIMUMMOUSEREFRESHRATE; i++) { ui->mouseRefreshRateComboBox->addItem(QString("%1 ms").arg(i), i); } int refreshIndex = ui->mouseRefreshRateComboBox->findData(GlobalVariables::JoyButton::mouseRefreshRate); if (refreshIndex >= 0) { ui->mouseRefreshRateComboBox->setCurrentIndex(refreshIndex); } fillSpringScreenPresets(); for (int i = 1; i <= 16; i++) { ui->gamepadPollRateComboBox->addItem(QString("%1 ms").arg(i), QVariant(i)); } int gamepadPollIndex = ui->gamepadPollRateComboBox->findData(GlobalVariables::JoyButton::gamepadRefreshRate); if (gamepadPollIndex >= 0) { ui->gamepadPollRateComboBox->setCurrentIndex(gamepadPollIndex); } if (QApplication::platformName() == QStringLiteral("xcb")) { refreshExtraMouseInfo(); } else { ui->extraInfoFrame->hide(); } // Begin Advanced Tab QString curLogFile = settings->value("LogFile", "").toString(); int logLevel = settings->value("LogLevel", Logger::LOG_NONE).toInt(); if (!curLogFile.isEmpty()) { ui->logFilePathEdit->setText(curLogFile); } ui->logLevelComboBox->setCurrentIndex(logLevel); // End Advanced Tab settings->getLock()->unlock(); connect(ui->categoriesListWidget, &QListWidget::currentRowChanged, ui->stackedWidget, &QStackedWidget::setCurrentIndex); connect(ui->controllerMappingsTableWidget, &QTableWidget::itemChanged, this, &MainSettingsDialog::mappingsTableItemChanged); connect(ui->mappingDeletePushButton, &QPushButton::clicked, this, &MainSettingsDialog::deleteMappingRow); connect(ui->mappngInsertPushButton, &QPushButton::clicked, this, &MainSettingsDialog::insertMappingRow); connect(this, &MainSettingsDialog::accepted, this, &MainSettingsDialog::saveNewSettings); connect(ui->profileOpenDirPushButton, &QPushButton::clicked, this, &MainSettingsDialog::selectDefaultProfileDir); connect(ui->activeCheckBox, &QCheckBox::toggled, ui->autoProfileTableWidget, &QTableWidget::setEnabled); connect(ui->activeCheckBox, &QCheckBox::toggled, this, &MainSettingsDialog::autoProfileButtonsActiveState); connect(ui->devicesComboBox, static_cast(&QComboBox::activated), this, &MainSettingsDialog::changeDeviceForProfileTable); connect(ui->autoProfileTableWidget, &QTableWidget::itemChanged, this, &MainSettingsDialog::processAutoProfileActiveClick); connect(ui->autoProfileAddPushButton, &QPushButton::clicked, this, &MainSettingsDialog::openAddAutoProfileDialog); connect(ui->autoProfileDeletePushButton, &QPushButton::clicked, this, &MainSettingsDialog::openDeleteAutoProfileConfirmDialog); connect(ui->autoProfileEditPushButton, &QPushButton::clicked, this, &MainSettingsDialog::openEditAutoProfileDialog); connect(ui->autoProfileTableWidget, &QTableWidget::itemSelectionChanged, this, &MainSettingsDialog::changeAutoProfileButtonsState); connect(ui->keyRepeatEnableCheckBox, &QCheckBox::clicked, this, &MainSettingsDialog::changeKeyRepeatWidgetsStatus); connect(ui->keyDelayHorizontalSlider, &QSlider::valueChanged, ui->keyDelaySpinBox, &QSpinBox::setValue); connect(ui->keyDelaySpinBox, static_cast(&QSpinBox::valueChanged), ui->keyDelayHorizontalSlider, &QSlider::setValue); connect(ui->keyRateHorizontalSlider, &QSlider::valueChanged, ui->keyRateSpinBox, &QSpinBox::setValue); connect(ui->keyRateSpinBox, static_cast(&QSpinBox::valueChanged), ui->keyRateHorizontalSlider, &QSlider::setValue); connect(ui->smoothingEnableCheckBox, &QCheckBox::toggled, this, &MainSettingsDialog::checkSmoothingWidgetStatus); connect(ui->resetAccelPushButton, &QPushButton::clicked, this, &MainSettingsDialog::resetMouseAcceleration); // Advanced Tab connect(ui->logFilePushButton, &QPushButton::clicked, this, &MainSettingsDialog::selectLogFile); } MainSettingsDialog::~MainSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (connectedDevices != nullptr) { delete connectedDevices; connectedDevices = nullptr; } delete ui; } void MainSettingsDialog::fillControllerMappingsTable() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->controllerMappingsTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); QHash> tempHash; settings->getLock()->lock(); settings->beginGroup("Mappings"); QStringList mappings = settings->allKeys(); QStringListIterator iter(mappings); while (iter.hasNext()) { QString tempkey = iter.next(); QString tempGUID = QString(); if (tempkey.contains("Disable")) { bool disableGameController = settings->value(tempkey, false).toBool(); tempGUID = tempkey.remove("Disable"); insertTempControllerMapping(tempHash, tempGUID); if (tempHash.contains(tempGUID)) { QList templist = tempHash.value(tempGUID); templist.replace(2, QVariant(disableGameController)); tempHash.insert(tempGUID, templist); // Overwrite original list } } else { QString mappingString = settings->value(tempkey, QString()).toString(); if (!mappingString.isEmpty()) { tempGUID = tempkey; insertTempControllerMapping(tempHash, tempGUID); if (tempHash.contains(tempGUID)) { QList templist = tempHash.value(tempGUID); templist.replace(1, mappingString); tempHash.insert(tempGUID, templist); // Overwrite original list } } } } settings->endGroup(); settings->getLock()->unlock(); QHashIterator> iter2(tempHash); int i = 0; while (iter2.hasNext()) { ui->controllerMappingsTableWidget->insertRow(i); QList templist = iter2.next().value(); QTableWidgetItem *item = new QTableWidgetItem(templist.at(0).toString()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, iter2.key()); item->setToolTip(templist.at(0).toString()); ui->controllerMappingsTableWidget->setItem(i, 0, item); item = new QTableWidgetItem(templist.at(1).toString()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, iter2.key()); ui->controllerMappingsTableWidget->setItem(i, 1, item); bool disableController = templist.at(2).toBool(); item = new QTableWidgetItem(); item->setCheckState(disableController ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole, iter2.key()); ui->controllerMappingsTableWidget->setItem(i, 2, item); i++; } } void MainSettingsDialog::insertTempControllerMapping(QHash> &hash, QString newGUID) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!newGUID.isEmpty() && !hash.contains(newGUID)) { QList templist; templist.append(QVariant(newGUID)); templist.append(QVariant("")); templist.append(QVariant(false)); hash.insert(newGUID, templist); } } void MainSettingsDialog::mappingsTableItemChanged(QTableWidgetItem *item) { qInstallMessageHandler(MessageHandler::myMessageOutput); int column = item->column(); int row = item->row(); if ((column == 0) && !item->text().isEmpty()) { QTableWidgetItem *disableitem = ui->controllerMappingsTableWidget->item(row, column); if (disableitem != nullptr) { disableitem->setData(Qt::UserRole, item->text()); } item->setData(Qt::UserRole, item->text()); } } void MainSettingsDialog::insertMappingRow() { qInstallMessageHandler(MessageHandler::myMessageOutput); int insertRowIndex = ui->controllerMappingsTableWidget->rowCount(); ui->controllerMappingsTableWidget->insertRow(insertRowIndex); QTableWidgetItem *item = new QTableWidgetItem(); ui->controllerMappingsTableWidget->setItem(insertRowIndex, 0, item); item = new QTableWidgetItem(); item->setFlags(item->flags() & ~Qt::ItemIsEditable); ui->controllerMappingsTableWidget->setItem(insertRowIndex, 1, item); item = new QTableWidgetItem(); item->setCheckState(Qt::Unchecked); ui->controllerMappingsTableWidget->setItem(insertRowIndex, 2, item); } void MainSettingsDialog::deleteMappingRow() { qInstallMessageHandler(MessageHandler::myMessageOutput); int row = ui->controllerMappingsTableWidget->currentRow(); if (row >= 0) { ui->controllerMappingsTableWidget->removeRow(row); } } void MainSettingsDialog::syncMappingSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); settings->getLock()->lock(); settings->beginGroup("Mappings"); settings->remove(""); for (int i = 0; i < ui->controllerMappingsTableWidget->rowCount(); i++) { QTableWidgetItem *itemGUID = ui->controllerMappingsTableWidget->item(i, 0); QTableWidgetItem *itemMapping = ui->controllerMappingsTableWidget->item(i, 1); QTableWidgetItem *itemDisable = ui->controllerMappingsTableWidget->item(i, 2); if ((itemGUID != nullptr) && !itemGUID->text().isEmpty() && (itemDisable != nullptr)) { QString disableController = (itemDisable->checkState() == Qt::Checked) ? "1" : "0"; if ((itemMapping != nullptr) && !itemMapping->text().isEmpty()) { settings->setValue(itemGUID->text(), itemMapping->text()); } settings->setValue(QString("%1Disable").arg(itemGUID->text()), disableController); } } settings->endGroup(); settings->getLock()->unlock(); } void MainSettingsDialog::saveNewSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); syncMappingSettings(); settings->getLock()->lock(); QString oldProfileDir = settings->value("DefaultProfileDir", "").toString(); QString possibleProfileDir = ui->profileDefaultDirLineEdit->text(); bool closeToTray = ui->closeToTrayCheckBox->isChecked(); bool attachNumKeypad = ui->attachNumKeypadCheckbox->isChecked(); settings->setValue("AttachNumKeypad", attachNumKeypad ? "1" : "0"); if (oldProfileDir != possibleProfileDir) { if (QFileInfo(possibleProfileDir).exists()) { settings->setValue("DefaultProfileDir", possibleProfileDir); } else if (possibleProfileDir.isEmpty()) { settings->remove("DefaultProfileDir"); } } int numRecentProfiles = ui->numberRecentProfileSpinBox->value(); settings->setValue("NumberRecentProfiles", numRecentProfiles); if (closeToTray) { settings->setValue("CloseToTray", closeToTray ? "1" : "0"); } else { settings->remove("CloseToTray"); } settings->getLock()->unlock(); checkLocaleChange(); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { saveAutoProfileSettings(); } #endif settings->getLock()->lock(); if (ui->traySingleProfileListCheckBox->isChecked()) { settings->setValue("TrayProfileList", "1"); } else { settings->setValue("TrayProfileList", "0"); } bool minimizeToTaskbar = ui->minimizeTaskbarCheckBox->isChecked(); settings->setValue("MinimizeToTaskbar", minimizeToTaskbar ? "1" : "0"); bool hideEmpty = ui->hideEmptyCheckBox->isChecked(); settings->setValue("HideEmptyButtons", hideEmpty ? "1" : "0"); bool autoOpenLastProfile = ui->autoLoadPreviousCheckBox->isChecked(); settings->setValue("AutoOpenLastProfile", autoOpenLastProfile ? "1" : "0"); bool launchInTray = ui->launchInTrayCheckBox->isChecked(); settings->setValue("LaunchInTray", launchInTray ? "1" : "0"); PadderCommon::lockInputDevices(); if (connectedDevices->size() > 0) { InputDevice *tempDevice = connectedDevices->at(0); QMetaObject::invokeMethod(tempDevice, "haltServices", Qt::BlockingQueuedConnection); } bool smoothingEnabled = ui->smoothingEnableCheckBox->isChecked(); int historySize = ui->historySizeSpinBox->value(); double weightModifier = ui->weightModifierDoubleSpinBox->value(); settings->setValue("Mouse/Smoothing", smoothingEnabled ? "1" : "0"); if (smoothingEnabled) { if (historySize > 0) { JoyButton::setMouseHistorySize(historySize, GlobalVariables::JoyButton::MAXIMUMMOUSEHISTORYSIZE, GlobalVariables::JoyButton::mouseHistorySize, &GlobalVariables::JoyButton::mouseHistoryX, &GlobalVariables::JoyButton::mouseHistoryY); } if (weightModifier != 0.0) { JoyButton::setWeightModifier(weightModifier, GlobalVariables::JoyButton::MAXIMUMWEIGHTMODIFIER, GlobalVariables::JoyButton::weightModifier); } } else { JoyButton::setMouseHistorySize( 1, GlobalVariables::JoyButton::MAXIMUMMOUSEHISTORYSIZE, GlobalVariables::JoyButton::mouseHistorySize, &GlobalVariables::JoyButton::mouseHistoryX, &GlobalVariables::JoyButton::mouseHistoryY); JoyButton::setWeightModifier(0.0, GlobalVariables::JoyButton::MAXIMUMWEIGHTMODIFIER, GlobalVariables::JoyButton::weightModifier); } if (historySize > 0) { settings->setValue("Mouse/HistorySize", historySize); } if (weightModifier > 0.0) { settings->setValue("Mouse/WeightModifier", weightModifier); } int refreshIndex = ui->mouseRefreshRateComboBox->currentIndex(); int mouseRefreshRate = ui->mouseRefreshRateComboBox->itemData(refreshIndex).toInt(); if (mouseRefreshRate != GlobalVariables::JoyButton::mouseRefreshRate) { settings->setValue("Mouse/RefreshRate", mouseRefreshRate); JoyButton::setMouseRefreshRate(mouseRefreshRate, GlobalVariables::JoyButton::mouseRefreshRate, GlobalVariables::JoyButton::IDLEMOUSEREFRESHRATE, JoyButton::getMouseHelper(), &GlobalVariables::JoyButton::mouseHistoryX, &GlobalVariables::JoyButton::mouseHistoryY, JoyButton::getTestOldMouseTime(), JoyButton::getStaticMouseEventTimer()); } int springIndex = ui->springScreenComboBox->currentIndex(); int springScreen = ui->springScreenComboBox->itemData(springIndex).toInt(); JoyButton::setSpringModeScreen(springScreen, GlobalVariables::JoyButton::springModeScreen); settings->setValue("Mouse/SpringScreen", QString::number(springScreen)); int pollIndex = ui->gamepadPollRateComboBox->currentIndex(); int gamepadPollRate = ui->gamepadPollRateComboBox->itemData(pollIndex).toInt(); if (gamepadPollRate != GlobalVariables::JoyButton::gamepadRefreshRate) { JoyButton::setGamepadRefreshRate(gamepadPollRate, GlobalVariables::JoyButton::gamepadRefreshRate, JoyButton::getMouseHelper()); settings->setValue("GamepadPollRate", QString::number(gamepadPollRate)); } // Advanced Tab settings->setValue("LogFile", ui->logFilePathEdit->text()); int logLevel = ui->logLevelComboBox->currentIndex(); if (logLevel < 0) { logLevel = 0; } if (Logger::LOG_MAX < logLevel) { logLevel = Logger::LOG_MAX; } settings->setValue("LogLevel", logLevel); // End Advanced Tab PadderCommon::unlockInputDevices(); settings->sync(); settings->getLock()->unlock(); } void MainSettingsDialog::selectDefaultProfileDir() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString lookupDir = PadderCommon::preferredProfileDir(settings); QString directory = QFileDialog::getExistingDirectory(this, tr("Select Default Profile Directory"), lookupDir); if (!directory.isEmpty() && QFileInfo(directory).exists()) { ui->profileDefaultDirLineEdit->setText(directory); } } void MainSettingsDialog::checkLocaleChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); settings->getLock()->lock(); int row = ui->localeListWidget->currentRow(); if (row == 0) { if (settings->contains("Language")) { settings->remove("Language"); } settings->getLock()->unlock(); emit changeLanguage(QLocale::system().name()); } else { QString newLocale = "en"; switch (row) { case 1: { newLocale = "br"; break; } case 2: { newLocale = "en"; break; } case 3: { newLocale = "fr"; break; } case 4: { newLocale = "de"; break; } case 5: { newLocale = "it"; break; } case 6: { newLocale = "ja"; break; } case 7: { newLocale = "ru"; break; } case 8: { newLocale = "sr"; break; } case 9: { newLocale = "zh_CN"; break; } case 10: { newLocale = "es"; break; } case 11: { newLocale = "uk"; break; } case 12: { newLocale = "pl"; break; } } settings->setValue("Language", newLocale); settings->getLock()->unlock(); emit changeLanguage(newLocale); } } void MainSettingsDialog::populateAutoProfiles() { qInstallMessageHandler(MessageHandler::myMessageOutput); exeAutoProfiles.clear(); defaultAutoProfiles.clear(); settings->beginGroup("DefaultAutoProfiles"); QStringList registeredGUIDs = settings->value("Uniques", QStringList()).toStringList(); settings->endGroup(); QString allProfile = settings->value(QString("DefaultAutoProfileAll/Profile"), "all").toString(); QString allActive = settings->value(QString("DefaultAutoProfileAll/Active"), "0").toString(); QString partialTitle = settings->value(QString("DefaultAutoProfileAll/PartialTitle"), "").toString(); bool defaultActive = allActive == "1" ? true : false; bool partialTitleBool = partialTitle == "1" ? true : false; allDefaultProfile = new AutoProfileInfo("all", allProfile, defaultActive, partialTitleBool, this); allDefaultProfile->setDefaultState(true); QStringListIterator iter(registeredGUIDs); while (iter.hasNext()) { QString tempkey = iter.next(); QString guid = tempkey; QString profile = settings->value(QString("DefaultAutoProfile-%1/Profile").arg(guid), "").toString(); QString active = settings->value(QString("DefaultAutoProfile-%1/Active").arg(guid), "0").toString(); QString partialTitle = settings->value(QString("DefaultAutoProfile-%1/PartialTitle").arg(guid), "0").toString(); bool partialTitleBool = partialTitle == "1" ? true : false; QString deviceName = settings->value(QString("DefaultAutoProfile-%1/DeviceName").arg(guid), "").toString(); QString windowClass = settings->value(QString("DefaultAutoProfile-%1/WindowClass").arg(guid), "").toString(); QString windowName = settings->value(QString("DefaultAutoProfile-%1/WindowName").arg(guid), "").toString(); QString exe = settings->value(QString("DefaultAutoProfile-%1/Exe").arg(guid), "").toString(); if (!guid.isEmpty() && !profile.isEmpty() && !deviceName.isEmpty()) { bool profileActive = active == "1" ? true : false; if (!defaultAutoProfiles.contains(guid) && guid != "all") { AutoProfileInfo *info = new AutoProfileInfo(guid, profile, profileActive, partialTitleBool, this); info->setDefaultState(true); info->setDeviceName(deviceName); info->setExe(exe); info->setWindowName(windowName); info->setWindowClass(windowClass); defaultAutoProfiles.insert(guid, info); defaultList.append(info); QList templist; templist.append(info); deviceAutoProfiles.insert(guid, templist); } } } settings->beginGroup("AutoProfiles"); bool quitSearch = false; for (int i = 1; !quitSearch; i++) { QString exe = settings->value(QString("AutoProfile%1Exe").arg(i), "").toString(); QString windowName = settings->value(QString("AutoProfile%1WindowName").arg(i), "").toString(); QString windowClass = settings->value(QString("AutoProfile%1WindowClass").arg(i), "").toString(); convToUniqueIDAutoProfGroupSett(settings, QString("AutoProfile%1GUID").arg(i), QString("AutoProfile%1UniqueID").arg(i)); QString guid = settings->value(QString("AutoProfile%1UniqueID").arg(i), "").toString(); QString profile = settings->value(QString("AutoProfile%1Profile").arg(i), "").toString(); QString active = settings->value(QString("AutoProfile%1Active").arg(i), 0).toString(); QString partialTitle = settings->value(QString("AutoProfile%1PartialTitle").arg(i), 0).toString(); bool partialTitleBool = partialTitle == "1" ? true : false; QString deviceName = settings->value(QString("AutoProfile%1DeviceName").arg(i), "").toString(); // Check if all required elements exist. If not, assume that the end of the // list has been reached. if ((!exe.isEmpty() || !windowClass.isEmpty() || !windowName.isEmpty()) && !guid.isEmpty()) { bool profileActive = active == "1" ? true : false; AutoProfileInfo *info = new AutoProfileInfo(guid, profile, exe, profileActive, partialTitleBool, this); if (!deviceName.isEmpty()) { info->setDeviceName(deviceName); } info->setWindowName(windowName); info->setWindowClass(windowClass); profileList.append(info); QList templist; if (guid != "all") { if (deviceAutoProfiles.contains(guid)) { templist = deviceAutoProfiles.value(guid); } templist.append(info); deviceAutoProfiles.insert(guid, templist); } } else { quitSearch = true; } } settings->endGroup(); } void MainSettingsDialog::fillAutoProfilesTable(QString guid) { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = ui->autoProfileTableWidget->rowCount() - 1; i >= 0; i--) { ui->autoProfileTableWidget->removeRow(i); } ui->autoProfileTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); if (defaultAutoProfiles.contains(guid) || deviceAutoProfiles.contains(guid)) { int i = 0; AutoProfileInfo *defaultForGUID = nullptr; if (defaultAutoProfiles.contains(guid)) { AutoProfileInfo *info = defaultAutoProfiles.value(guid); defaultForGUID = info; ui->autoProfileTableWidget->insertRow(i); QTableWidgetItem *item = new QTableWidgetItem(); item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked); ui->autoProfileTableWidget->setItem(i, 0, item); QString deviceName = info->getDeviceName(); QString guidDisplay = info->getUniqueID(); if (!deviceName.isEmpty()) { guidDisplay = QString("%1 ").arg(info->getDeviceName()); guidDisplay.append(QString("(%1)").arg(info->getUniqueID())); } item = new QTableWidgetItem(guidDisplay); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getUniqueID()); item->setToolTip(info->getUniqueID()); ui->autoProfileTableWidget->setItem(i, 1, item); QFileInfo profilePath(info->getProfileLocation()); item = new QTableWidgetItem(profilePath.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getProfileLocation()); item->setToolTip(info->getProfileLocation()); ui->autoProfileTableWidget->setItem(i, 2, item); item = new QTableWidgetItem(info->getWindowClass()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowClass()); item->setToolTip(info->getWindowClass()); ui->autoProfileTableWidget->setItem(i, 3, item); item = new QTableWidgetItem(info->getWindowName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowName()); item->setToolTip(info->getWindowName()); ui->autoProfileTableWidget->setItem(i, 4, item); QFileInfo exeInfo(info->getExe()); item = new QTableWidgetItem(exeInfo.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getExe()); item->setToolTip(info->getExe()); ui->autoProfileTableWidget->setItem(i, 5, item); item = new QTableWidgetItem("Default"); item->setData(Qt::UserRole, "default"); ui->autoProfileTableWidget->setItem(i, 6, item); item = new QTableWidgetItem("Instance"); item->setData(Qt::UserRole, QVariant::fromValue(info)); ui->autoProfileTableWidget->setItem(i, 7, item); i++; } QListIterator iter(deviceAutoProfiles.value(guid)); while (iter.hasNext()) { AutoProfileInfo *info = iter.next(); if (!defaultForGUID || info != defaultForGUID) { ui->autoProfileTableWidget->insertRow(i); QTableWidgetItem *item = new QTableWidgetItem(); item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked); ui->autoProfileTableWidget->setItem(i, 0, item); QString deviceName = info->getDeviceName(); QString guidDisplay = info->getUniqueID(); if (!deviceName.isEmpty()) { guidDisplay = QString("%1 ").arg(info->getDeviceName()); guidDisplay.append(QString("(%1)").arg(info->getUniqueID())); } item = new QTableWidgetItem(guidDisplay); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getUniqueID()); item->setToolTip(info->getUniqueID()); ui->autoProfileTableWidget->setItem(i, 1, item); QFileInfo profilePath(info->getProfileLocation()); item = new QTableWidgetItem(profilePath.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getProfileLocation()); item->setToolTip(info->getProfileLocation()); ui->autoProfileTableWidget->setItem(i, 2, item); // nie są wstawiane wartości jeśli !deviceName.isEmpty(), więc jest inne niż all i jeśli jest default item = new QTableWidgetItem(info->getWindowClass()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowClass()); item->setToolTip(info->getWindowClass()); ui->autoProfileTableWidget->setItem(i, 3, item); // nie są wstawiane wartości jeśli !deviceName.isEmpty(), więc jest inne niż all i jeśli jest default item = new QTableWidgetItem(info->getWindowName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowName()); item->setToolTip(info->getWindowName()); ui->autoProfileTableWidget->setItem(i, 4, item); // nie są wstawiane wartości jeśli !deviceName.isEmpty(), więc jest inne niż all i jeśli jest default QFileInfo exeInfo(info->getExe()); item = new QTableWidgetItem(exeInfo.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getExe()); item->setToolTip(info->getExe()); ui->autoProfileTableWidget->setItem(i, 5, item); item = new QTableWidgetItem("Instance"); item->setData(Qt::UserRole, QVariant::fromValue(info)); ui->autoProfileTableWidget->setItem(i, 7, item); i++; } } } } void MainSettingsDialog::clearAutoProfileData() { qInstallMessageHandler(MessageHandler::myMessageOutput); } void MainSettingsDialog::fillGUIDComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->devicesComboBox->clear(); ui->devicesComboBox->addItem(tr("All"), QVariant("all")); QList guids = deviceAutoProfiles.keys(); QListIterator iter(guids); while (iter.hasNext()) { QString guid = iter.next(); QList temp = deviceAutoProfiles.value(guid); if (temp.count() > 0) { QString deviceName = temp.first()->getDeviceName(); if (!deviceName.isEmpty()) { ui->devicesComboBox->addItem(deviceName, QVariant(guid)); } else { ui->devicesComboBox->addItem(guid, QVariant(guid)); } } else { ui->devicesComboBox->addItem(guid, QVariant(guid)); } } } void MainSettingsDialog::changeDeviceForProfileTable(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(ui->autoProfileTableWidget, &QTableWidget::itemChanged, this, &MainSettingsDialog::processAutoProfileActiveClick); if (index == 0) { fillAllAutoProfilesTable(); } else { QString guid = ui->devicesComboBox->itemData(index).toString(); fillAutoProfilesTable(guid); } connect(ui->autoProfileTableWidget, &QTableWidget::itemChanged, this, &MainSettingsDialog::processAutoProfileActiveClick); } void MainSettingsDialog::saveAutoProfileSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); settings->getLock()->lock(); settings->beginGroup("DefaultAutoProfiles"); QStringList defaultkeys = settings->allKeys(); settings->endGroup(); QStringListIterator iterDefaults(defaultkeys); while (iterDefaults.hasNext()) { QString tempkey = iterDefaults.next(); QString guid = QString(tempkey).replace("UniqueID", ""); QString testkey = QString("DefaultAutoProfile-%1").arg(guid); settings->beginGroup(testkey); settings->remove(""); settings->endGroup(); } settings->beginGroup("DefaultAutoProfiles"); settings->remove(""); settings->endGroup(); settings->beginGroup("DefaultAutoProfileAll"); settings->remove(""); settings->endGroup(); settings->beginGroup("AutoProfiles"); settings->remove(""); settings->endGroup(); if (allDefaultProfile) { QString profile = allDefaultProfile->getProfileLocation(); QString defaultActive = allDefaultProfile->isActive() ? "1" : "0"; settings->setValue(QString("DefaultAutoProfileAll/Profile"), profile); settings->setValue(QString("DefaultAutoProfileAll/Active"), defaultActive); } QMapIterator iter(defaultAutoProfiles); QStringList registeredGUIDs = QStringList(); while (iter.hasNext()) { iter.next(); QString guid = iter.key(); registeredGUIDs.append(guid); AutoProfileInfo *info = iter.value(); QString profileActive = info->isActive() ? "1" : "0"; QString deviceName = info->getDeviceName(); settings->setValue(QString("DefaultAutoProfiles/UniqueID%1").arg(guid), guid); settings->setValue(QString("DefaultAutoProfile-%1/Profile").arg(guid), info->getProfileLocation()); settings->setValue(QString("DefaultAutoProfile-%1/Active").arg(guid), profileActive); settings->setValue(QString("DefaultAutoProfile-%1/DeviceName").arg(guid), deviceName); settings->setValue(QString("DefaultAutoProfile-%1/WindowName").arg(guid), info->getWindowName()); settings->setValue(QString("DefaultAutoProfile-%1/WindowClass").arg(guid), info->getWindowClass()); settings->setValue(QString("DefaultAutoProfile-%1/Exe").arg(guid), info->getExe()); settings->setValue(QString("DefaultAutoProfile-%1/PartialTitle").arg(guid), 0); } if (!registeredGUIDs.isEmpty()) settings->setValue("DefaultAutoProfiles/Uniques", registeredGUIDs); settings->beginGroup("AutoProfiles"); QString autoActive = ui->activeCheckBox->isChecked() ? "1" : "0"; settings->setValue("AutoProfilesActive", autoActive); QListIterator iterProfiles(profileList); int i = 1; while (iterProfiles.hasNext()) { AutoProfileInfo *info = iterProfiles.next(); QString defaultActive = info->isActive() ? "1" : "0"; QString partialTitle = info->isPartialState() ? "1" : "0"; if (!info->getExe().isEmpty()) { settings->setValue(QString("AutoProfile%1Exe").arg(i), info->getExe()); } if (!info->getWindowClass().isEmpty()) { settings->setValue(QString("AutoProfile%1WindowClass").arg(i), info->getWindowClass()); } if (!info->getWindowName().isEmpty()) { settings->setValue(QString("AutoProfile%1WindowName").arg(i), info->getWindowName()); } convToUniqueIDAutoProfGroupSett(settings, QString("AutoProfile%1GUID").arg(i), QString("AutoProfile%1UniqueID").arg(i)); settings->setValue(QString("AutoProfile%1UniqueID").arg(i), info->getUniqueID()); settings->setValue(QString("AutoProfile%1Profile").arg(i), info->getProfileLocation()); settings->setValue(QString("AutoProfile%1Active").arg(i), defaultActive); settings->setValue(QString("AutoProfile%1PartialTitle").arg(i), partialTitle); settings->setValue(QString("AutoProfile%1DeviceName").arg(i), info->getDeviceName()); i++; } settings->endGroup(); settings->getLock()->unlock(); } void MainSettingsDialog::fillAllAutoProfilesTable() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = ui->autoProfileTableWidget->rowCount() - 1; i >= 0; i--) { ui->autoProfileTableWidget->removeRow(i); } ui->autoProfileTableWidget->horizontalHeader()->setVisible(true); ui->autoProfileTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->autoProfileTableWidget->hideColumn(7); int i = 0; AutoProfileInfo *info = allDefaultProfile; ui->autoProfileTableWidget->insertRow(i); QTableWidgetItem *item = new QTableWidgetItem(); item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked); ui->autoProfileTableWidget->setItem(i, 0, item); QString deviceName = info->getDeviceName(); QString guidDisplay = info->getUniqueID(); if (!deviceName.isEmpty()) { guidDisplay = QString("%1 ").arg(info->getDeviceName()); guidDisplay.append(QString("(%1)").arg(info->getUniqueID())); } item = new QTableWidgetItem(guidDisplay); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getUniqueID()); item->setToolTip(info->getUniqueID()); ui->autoProfileTableWidget->setItem(i, 1, item); QFileInfo profilePath(info->getProfileLocation()); item = new QTableWidgetItem(profilePath.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getProfileLocation()); item->setToolTip(info->getProfileLocation()); ui->autoProfileTableWidget->setItem(i, 2, item); QFileInfo exeInfo(info->getExe()); item = new QTableWidgetItem(exeInfo.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getExe()); item->setToolTip(info->getExe()); ui->autoProfileTableWidget->setItem(i, 5, item); item = new QTableWidgetItem("Default"); item->setData(Qt::UserRole, "default"); ui->autoProfileTableWidget->setItem(i, 6, item); item = new QTableWidgetItem("Instance"); item->setData(Qt::UserRole, QVariant::fromValue(info)); ui->autoProfileTableWidget->setItem(i, 7, item); i++; QListIterator iterDefaults(defaultList); while (iterDefaults.hasNext()) { AutoProfileInfo *info = iterDefaults.next(); ui->autoProfileTableWidget->insertRow(i); QTableWidgetItem *item = new QTableWidgetItem(); item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked); ui->autoProfileTableWidget->setItem(i, 0, item); QString deviceName = info->getDeviceName(); QString guidDisplay = info->getUniqueID(); if (!deviceName.isEmpty()) { guidDisplay = QString("%1 ").arg(info->getDeviceName()); guidDisplay.append(QString("(%1)").arg(info->getUniqueID())); } item = new QTableWidgetItem(guidDisplay); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getUniqueID()); item->setToolTip(info->getUniqueID()); ui->autoProfileTableWidget->setItem(i, 1, item); QFileInfo profilePath(info->getProfileLocation()); item = new QTableWidgetItem(profilePath.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getProfileLocation()); item->setToolTip(info->getProfileLocation()); ui->autoProfileTableWidget->setItem(i, 2, item); item = new QTableWidgetItem(info->getWindowClass()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowClass()); item->setToolTip(info->getWindowClass()); ui->autoProfileTableWidget->setItem(i, 3, item); item = new QTableWidgetItem(info->getWindowName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowName()); item->setToolTip(info->getWindowName()); ui->autoProfileTableWidget->setItem(i, 4, item); QFileInfo exeInfo(info->getExe()); item = new QTableWidgetItem(exeInfo.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getExe()); item->setToolTip(info->getExe()); ui->autoProfileTableWidget->setItem(i, 5, item); item = new QTableWidgetItem("Default"); item->setData(Qt::UserRole, "default"); ui->autoProfileTableWidget->setItem(i, 6, item); item = new QTableWidgetItem("Instance"); item->setData(Qt::UserRole, QVariant::fromValue(info)); ui->autoProfileTableWidget->setItem(i, 7, item); i++; } QListIterator iter(profileList); while (iter.hasNext()) { AutoProfileInfo *info = iter.next(); ui->autoProfileTableWidget->insertRow(i); QTableWidgetItem *item = new QTableWidgetItem(); item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked); ui->autoProfileTableWidget->setItem(i, 0, item); QString deviceName = info->getDeviceName(); QString guidDisplay = info->getUniqueID(); if (!deviceName.isEmpty()) { guidDisplay = QString("%1 ").arg(info->getDeviceName()); guidDisplay.append(QString("(%1)").arg(info->getUniqueID())); } item = new QTableWidgetItem(guidDisplay); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getUniqueID()); item->setToolTip(info->getUniqueID()); ui->autoProfileTableWidget->setItem(i, 1, item); QFileInfo profilePath(info->getProfileLocation()); item = new QTableWidgetItem(profilePath.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getProfileLocation()); item->setToolTip(info->getProfileLocation()); ui->autoProfileTableWidget->setItem(i, 2, item); item = new QTableWidgetItem(info->getWindowClass()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowClass()); item->setToolTip(info->getWindowClass()); ui->autoProfileTableWidget->setItem(i, 3, item); item = new QTableWidgetItem(info->getWindowName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getWindowName()); item->setToolTip(info->getWindowName()); ui->autoProfileTableWidget->setItem(i, 4, item); QFileInfo exeInfo(info->getExe()); item = new QTableWidgetItem(exeInfo.fileName()); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getExe()); item->setToolTip(info->getExe()); ui->autoProfileTableWidget->setItem(i, 5, item); item = new QTableWidgetItem(); item->setData(Qt::UserRole, ""); ui->autoProfileTableWidget->setItem(i, 6, item); item = new QTableWidgetItem("Instance"); item->setData(Qt::UserRole, QVariant::fromValue(info)); ui->autoProfileTableWidget->setItem(i, 7, item); i++; } } void MainSettingsDialog::processAutoProfileActiveClick(QTableWidgetItem *item) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (item && (item->column() == 0)) { QTableWidgetItem *infoitem = ui->autoProfileTableWidget->item(item->row(), 7); AutoProfileInfo *info = infoitem->data(Qt::UserRole).value(); Qt::CheckState active = item->checkState(); if (active == Qt::Unchecked) { info->setActive(false); } else if (active == Qt::Checked) { info->setActive(true); } } } void MainSettingsDialog::openAddAutoProfileDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList reservedGUIDs = defaultAutoProfiles.keys(); AutoProfileInfo *info = new AutoProfileInfo(this); AddEditAutoProfileDialog *dialog = new AddEditAutoProfileDialog(info, settings, connectedDevices, reservedGUIDs, false, this); connect(dialog, &AddEditAutoProfileDialog::accepted, this, [this, dialog] { addNewAutoProfile(dialog); }); connect(dialog, &AddEditAutoProfileDialog::rejected, info, &AutoProfileInfo::deleteLater); dialog->show(); } void MainSettingsDialog::openEditAutoProfileDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); int selectedRow = ui->autoProfileTableWidget->currentRow(); if (selectedRow >= 0) { QTableWidgetItem *item = ui->autoProfileTableWidget->item(selectedRow, 7); AutoProfileInfo *info = item->data(Qt::UserRole).value(); if (info != allDefaultProfile) { QList reservedGUIDs = defaultAutoProfiles.keys(); if (info->getUniqueID() != "all") { AutoProfileInfo *temp = defaultAutoProfiles.value(info->getUniqueID()); if (info == temp) { reservedGUIDs.removeAll(info->getUniqueID()); } } QTableWidgetItem *itemDefault = ui->autoProfileTableWidget->item(selectedRow, 6); if (itemDefault->data(Qt::UserRole) == "default" || itemDefault->text() == "Default") info->setDefaultState(true); AddEditAutoProfileDialog *dialog = new AddEditAutoProfileDialog(info, settings, connectedDevices, reservedGUIDs, true, this); connect(dialog, &AddEditAutoProfileDialog::accepted, this, [this, dialog] { transferEditsToCurrentTableRow(dialog); }); dialog->show(); } else { info->setDefaultState(true); EditAllDefaultAutoProfileDialog *dialog = new EditAllDefaultAutoProfileDialog(info, settings, this); dialog->show(); connect(dialog, &EditAllDefaultAutoProfileDialog::accepted, this, [this, dialog] { transferAllProfileEditToCurrentTableRow(dialog); }); } } } void MainSettingsDialog::openDeleteAutoProfileConfirmDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); QMessageBox msgBox; msgBox.setText(tr("Are you sure you want to delete the profile?")); msgBox.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); int ret = msgBox.exec(); if (ret == QMessageBox::Discard) { int selectedRow = ui->autoProfileTableWidget->currentRow(); if (selectedRow >= 0) { QTableWidgetItem *item = ui->autoProfileTableWidget->item(selectedRow, 7); AutoProfileInfo *info = item->data(Qt::UserRole).value(); if (info->isCurrentDefault()) { if (info->getUniqueID() == "all") { delete allDefaultProfile; allDefaultProfile = nullptr; } else if (defaultAutoProfiles.contains(info->getUniqueID())) { defaultAutoProfiles.remove(info->getUniqueID()); defaultList.removeAll(info); delete info; info = nullptr; } } else { if (deviceAutoProfiles.contains(info->getUniqueID())) { QList temp = deviceAutoProfiles.value(info->getUniqueID()); temp.removeAll(info); deviceAutoProfiles.insert(info->getUniqueID(), temp); } profileList.removeAll(info); delete info; info = nullptr; } } ui->autoProfileTableWidget->removeRow(selectedRow); } } void MainSettingsDialog::changeAutoProfileButtonsState() { qInstallMessageHandler(MessageHandler::myMessageOutput); int selectedRow = ui->autoProfileTableWidget->currentRow(); if (selectedRow >= 0) { QTableWidgetItem *item = ui->autoProfileTableWidget->item(selectedRow, 7); AutoProfileInfo *info = item->data(Qt::UserRole).value(); if (info == allDefaultProfile) { ui->autoProfileAddPushButton->setEnabled(true); ui->autoProfileEditPushButton->setEnabled(true); ui->autoProfileDeletePushButton->setEnabled(false); } else { ui->autoProfileAddPushButton->setEnabled(true); ui->autoProfileEditPushButton->setEnabled(true); ui->autoProfileDeletePushButton->setEnabled(true); } } else { ui->autoProfileAddPushButton->setEnabled(true); ui->autoProfileDeletePushButton->setEnabled(false); ui->autoProfileEditPushButton->setEnabled(false); } } void MainSettingsDialog::transferAllProfileEditToCurrentTableRow(EditAllDefaultAutoProfileDialog *dialog) { qInstallMessageHandler(MessageHandler::myMessageOutput); AutoProfileInfo *info = dialog->getAutoProfile(); allDefaultProfile = info; changeDeviceForProfileTable(0); } void MainSettingsDialog::transferEditsToCurrentTableRow(AddEditAutoProfileDialog *dialog) { qInstallMessageHandler(MessageHandler::myMessageOutput); AutoProfileInfo *info = dialog->getAutoProfile(); // Delete pointers to object that might be misplaced // due to an association change. QString oldGUID = dialog->getOriginalUniqueID(); if (oldGUID != info->getUniqueID()) { if (defaultAutoProfiles.value(oldGUID) == info) { defaultAutoProfiles.remove(oldGUID); } if (info->isCurrentDefault()) { defaultAutoProfiles.insert(info->getUniqueID(), info); } } if ((oldGUID != info->getUniqueID()) && deviceAutoProfiles.contains(oldGUID)) { QList temp = deviceAutoProfiles.value(oldGUID); temp.removeAll(info); if (temp.count() > 0) { deviceAutoProfiles.insert(oldGUID, temp); } else { deviceAutoProfiles.remove(oldGUID); } if (deviceAutoProfiles.contains(info->getUniqueID())) { QList temp2 = deviceAutoProfiles.value(oldGUID); if (!temp2.contains(info)) { temp2.append(info); deviceAutoProfiles.insert(info->getUniqueID(), temp2); } } else if (info->getUniqueID().toLower() != "all") { QList temp2; temp2.append(info); deviceAutoProfiles.insert(info->getUniqueID(), temp2); } } else if ((oldGUID != info->getUniqueID()) && (info->getUniqueID().toLower() != "all")) { QList temp; temp.append(info); deviceAutoProfiles.insert(info->getUniqueID(), temp); } if (!info->isCurrentDefault()) { defaultList.removeAll(info); if (!profileList.contains(info)) { profileList.append(info); } } else { profileList.removeAll(info); if (!defaultList.contains(info)) { defaultList.append(info); } } if (deviceAutoProfiles.contains(info->getUniqueID())) { QList temp2 = deviceAutoProfiles.value(info->getUniqueID()); if (!temp2.contains(info)) { temp2.append(info); deviceAutoProfiles.insert(info->getUniqueID(), temp2); } } else { QList temp2; temp2.append(info); deviceAutoProfiles.insert(info->getUniqueID(), temp2); } fillGUIDComboBox(); int currentIndex = ui->devicesComboBox->currentIndex(); changeDeviceForProfileTable(currentIndex); } void MainSettingsDialog::addNewAutoProfile(AddEditAutoProfileDialog *dialog) { qInstallMessageHandler(MessageHandler::myMessageOutput); // AddEditAutoProfileDialog *dialog = static_cast(sender()); AutoProfileInfo *info = dialog->getAutoProfile(); bool found = false; if (info->isCurrentDefault() && defaultAutoProfiles.contains(info->getUniqueID())) { found = true; } if (!found) { if (info->isCurrentDefault()) { if (!info->getUniqueID().isEmpty() && !info->getExe().isEmpty()) { defaultAutoProfiles.insert(info->getUniqueID(), info); defaultList.append(info); } } else { if (!info->getUniqueID().isEmpty() && !info->getExe().isEmpty()) { profileList.append(info); if (info->getUniqueID() != "all") { QList tempDevProfileList; if (deviceAutoProfiles.contains(info->getUniqueID())) tempDevProfileList = deviceAutoProfiles.value(info->getUniqueID()); tempDevProfileList.append(info); deviceAutoProfiles.insert(info->getUniqueID(), tempDevProfileList); } } } fillGUIDComboBox(); changeDeviceForProfileTable(ui->devicesComboBox->currentIndex()); } } void MainSettingsDialog::autoProfileButtonsActiveState(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (enabled) { changeAutoProfileButtonsState(); } else { ui->autoProfileAddPushButton->setEnabled(false); ui->autoProfileEditPushButton->setEnabled(false); ui->autoProfileDeletePushButton->setEnabled(false); } } void MainSettingsDialog::changeKeyRepeatWidgetsStatus(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->keyDelayHorizontalSlider->setEnabled(enabled); ui->keyDelaySpinBox->setEnabled(enabled); ui->keyRateHorizontalSlider->setEnabled(enabled); ui->keyRateSpinBox->setEnabled(enabled); } void MainSettingsDialog::checkSmoothingWidgetStatus(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (enabled) { ui->historySizeSpinBox->setEnabled(true); ui->weightModifierDoubleSpinBox->setEnabled(true); } else { ui->historySizeSpinBox->setEnabled(false); ui->weightModifierDoubleSpinBox->setEnabled(false); } } void MainSettingsDialog::changePresetLanguage() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (settings->contains("Language")) { QString targetLang = settings->value("Language").toString(); if (targetLang == "br") { ui->localeListWidget->setCurrentRow(1); } else if (targetLang == "en") { ui->localeListWidget->setCurrentRow(2); } else if (targetLang == "fr") { ui->localeListWidget->setCurrentRow(3); } else if (targetLang == "de") { ui->localeListWidget->setCurrentRow(4); } else if (targetLang == "it") { ui->localeListWidget->setCurrentRow(5); } else if (targetLang == "ja") { ui->localeListWidget->setCurrentRow(6); } else if (targetLang == "ru") { ui->localeListWidget->setCurrentRow(7); } else if (targetLang == "sr") { ui->localeListWidget->setCurrentRow(8); } else if (targetLang == "zh_CN") { ui->localeListWidget->setCurrentRow(9); } else if (targetLang == "es") { ui->localeListWidget->setCurrentRow(10); } else if (targetLang == "uk") { ui->localeListWidget->setCurrentRow(11); } else if (targetLang == "pl") { ui->localeListWidget->setCurrentRow(12); } else { ui->localeListWidget->setCurrentRow(0); } } else { ui->localeListWidget->setCurrentRow(0); } } void MainSettingsDialog::fillSpringScreenPresets() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->springScreenComboBox->clear(); ui->springScreenComboBox->addItem(tr("Default"), QVariant(GlobalVariables::AntimicroSettings::defaultSpringScreen)); QDesktopWidget deskWid; for (int i = 0; i < deskWid.screenCount(); i++) { ui->springScreenComboBox->addItem(QString(":%1").arg(i), QVariant(i)); } int screenIndex = ui->springScreenComboBox->findData(GlobalVariables::JoyButton::springModeScreen); if (screenIndex > -1) { ui->springScreenComboBox->setCurrentIndex(screenIndex); } } void MainSettingsDialog::refreshExtraMouseInfo() { qInstallMessageHandler(MessageHandler::myMessageOutput); #if defined(WITH_X11) QString handler = EventHandlerFactory::getInstance()->handler()->getIdentifier(); if (QApplication::platformName() == QStringLiteral("xcb")) { struct X11Extras::ptrInformation temp; if (handler == "uinput") { temp = X11Extras::getInstance()->getPointInformation(); } else if (handler == "xtest") { temp = X11Extras::getInstance()->getPointInformation(GlobalVariables::X11Extras::xtestMouseDeviceName); } if (temp.id >= 0) { ui->accelNumLabel->setText(QString::number(temp.accelNum)); ui->accelDenomLabel->setText(QString::number(temp.accelDenom)); ui->accelThresLabel->setText(QString::number(temp.threshold)); } } #endif } void MainSettingsDialog::resetMouseAcceleration() { qInstallMessageHandler(MessageHandler::myMessageOutput); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { X11Extras::getInstance()->x11ResetMouseAccelerationChange(); refreshExtraMouseInfo(); } #endif } void MainSettingsDialog::selectLogFile() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString oldLogFile = settings->value("LogFile", "").toString(); QString newLogFile = QFileDialog::getSaveFileName(this, tr("Save Log File As"), oldLogFile, tr("Log Files (*.log)")); if (!newLogFile.isEmpty()) ui->logFilePathEdit->setText(newLogFile); } AntiMicroSettings *MainSettingsDialog::getSettings() const { return settings; } QMap *MainSettingsDialog::getDefaultAutoProfiles() { return &defaultAutoProfiles; } QMap> *MainSettingsDialog::getDeviceAutoProfiles() { return &deviceAutoProfiles; } QMap> *MainSettingsDialog::getExeAutoProfiles() { return &exeAutoProfiles; } QList *MainSettingsDialog::getDefaultList() { return &defaultList; } QList *MainSettingsDialog::getProfileList() { return &profileList; } AutoProfileInfo *MainSettingsDialog::getAllDefaultProfile() const { return allDefaultProfile; } QList *MainSettingsDialog::getConnectedDevices() const { return connectedDevices; } void MainSettingsDialog::on_resetBtn_clicked() { QMessageBox msgBox; msgBox.setText(tr("Do you really want to reset setting?")); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); switch (msgBox.exec()) { case QMessageBox::Ok: resetGeneralSett(); resetAutoProfSett(); resetMouseSett(); resetAdvancedSett(); ui->localeListWidget->setCurrentRow(0); break; case QMessageBox::Cancel: break; default: break; } QMessageBox msgBox2; msgBox2.setText(tr("Would you like to reset mappings too?")); msgBox2.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); switch (msgBox2.exec()) { case QMessageBox::Ok: ui->controllerMappingsTableWidget->setRowCount(0); break; case QMessageBox::Cancel: break; default: break; } } void MainSettingsDialog::resetGeneralSett() { ui->profileDefaultDirLineEdit->setText(PadderCommon::preferredProfileDir(settings)); ui->numberRecentProfileSpinBox->setValue(5); int gamepadPollIndex = ui->gamepadPollRateComboBox->findData(GlobalVariables::JoyButton::gamepadRefreshRate); if (gamepadPollIndex >= 0) { ui->gamepadPollRateComboBox->setCurrentIndex(gamepadPollIndex); } ui->closeToTrayCheckBox->setChecked(false); ui->attachNumKeypadCheckbox->setChecked(false); ui->launchAtWinStartupCheckBox->setChecked(false); ui->traySingleProfileListCheckBox->setChecked(false); ui->minimizeTaskbarCheckBox->setChecked(false); ui->hideEmptyCheckBox->setChecked(false); ui->autoLoadPreviousCheckBox->setChecked(true); ui->launchInTrayCheckBox->setChecked(false); ui->associateProfilesCheckBox->setChecked(true); ui->keyRepeatEnableCheckBox->setChecked(false); ui->keyDelayHorizontalSlider->setValue(660); ui->keyRateHorizontalSlider->setValue(25); } void MainSettingsDialog::resetAutoProfSett() { disconnect(ui->autoProfileTableWidget, &QTableWidget::itemChanged, this, &MainSettingsDialog::processAutoProfileActiveClick); ui->activeCheckBox->setChecked(false); ui->devicesComboBox->setCurrentIndex(0); ui->autoProfileTableWidget->setRowCount(0); AutoProfileInfo *info = allDefaultProfile; ui->autoProfileTableWidget->insertRow(0); QTableWidgetItem *item = new QTableWidgetItem(); item->setCheckState(info->isActive() ? Qt::Checked : Qt::Unchecked); ui->autoProfileTableWidget->setItem(0, 0, item); QString deviceName = info->getDeviceName(); QString guidDisplay = info->getUniqueID(); if (!deviceName.isEmpty()) { guidDisplay = QString("%1 ").arg(info->getDeviceName()); guidDisplay.append(QString("(%1)").arg(info->getUniqueID())); } item = new QTableWidgetItem(guidDisplay); item->setFlags(item->flags() & ~Qt::ItemIsEditable); item->setData(Qt::UserRole, info->getUniqueID()); item->setToolTip(info->getUniqueID()); ui->autoProfileTableWidget->setItem(0, 1, item); item = new QTableWidgetItem("Default"); item->setData(Qt::UserRole, "default"); ui->autoProfileTableWidget->setItem(0, 6, item); item = new QTableWidgetItem("Instance"); item->setData(Qt::UserRole, QVariant::fromValue(info)); ui->autoProfileTableWidget->setItem(0, 7, item); if (ui->autoProfileTableWidget->rowCount() == 1) profileList.clear(); connect(ui->autoProfileTableWidget, &QTableWidget::itemChanged, this, &MainSettingsDialog::processAutoProfileActiveClick); } void MainSettingsDialog::resetMouseSett() { ui->disableWindowsEnhancedPointCheckBox->setChecked(false); ui->smoothingEnableCheckBox->setChecked(false); ui->smoothingEnableCheckBox->setEnabled(true); ui->historySizeSpinBox->setValue(10); ui->historySizeSpinBox->setEnabled(false); ui->weightModifierDoubleSpinBox->setValue(0.20); ui->weightModifierDoubleSpinBox->setEnabled(false); int refreshIndex = ui->mouseRefreshRateComboBox->findData(GlobalVariables::JoyButton::mouseRefreshRate); if (refreshIndex >= 0) { ui->mouseRefreshRateComboBox->setCurrentIndex(refreshIndex); } int screenIndex = ui->springScreenComboBox->findData(GlobalVariables::JoyButton::springModeScreen); if (screenIndex > -1) { ui->springScreenComboBox->setCurrentIndex(screenIndex); } } void MainSettingsDialog::resetAdvancedSett() { ui->logFilePathEdit->setText(""); ui->logLevelComboBox->setCurrentIndex(0); } void MainSettingsDialog::convToUniqueIDAutoProfGroupSett(QSettings *sett, QString guidAutoProfSett, QString uniqueAutoProfSett) { if (sett->contains(guidAutoProfSett)) { sett->setValue(uniqueAutoProfSett, sett->value(guidAutoProfSett)); sett->remove(guidAutoProfSett); } } AntiMicroX-antimicrox-2888bf6/src/mainsettingsdialog.h000066400000000000000000000146541377703515000231220ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MAINSETTINGSDIALOG_H #define MAINSETTINGSDIALOG_H #include "ui_mainsettingsdialog.h" #include #include class AntiMicroSettings; class InputDevice; class QWidget; class AutoProfileInfo; class QTableWidgetItem; class EditAllDefaultAutoProfileDialog; class AddEditAutoProfileDialog; namespace Ui { class MainSettingsDialog; } class MainSettingsDialog : public QDialog { Q_OBJECT public: explicit MainSettingsDialog(AntiMicroSettings *settings, QList *devices, QWidget *parent = nullptr); ~MainSettingsDialog(); AntiMicroSettings *getSettings() const; QMap *getDefaultAutoProfiles(); // Default profiles assigned to a specific device QMap> * getDeviceAutoProfiles(); // Profiles assigned with an association with an application QMap> *getExeAutoProfiles(); QList *getDefaultList(); QList *getProfileList(); AutoProfileInfo *getAllDefaultProfile() const; QList *getConnectedDevices() const; protected: void fillControllerMappingsTable(); // MainSettingsMapping class void insertTempControllerMapping(QHash> &hash, QString newGUID); // MainSettingsMapping class void checkLocaleChange(); // MainSettingsLang class void populateAutoProfiles(); // MainSettingsProfile class void fillAutoProfilesTable(QString guid); // MainSettingsProfile class void fillAllAutoProfilesTable(); // MainSettingsProfile class void clearAutoProfileData(); // MainSettingsProfile class void changePresetLanguage(); // MainSettingsLang class void fillSpringScreenPresets(); // MainSettingsMouse class void refreshExtraMouseInfo(); // MainSettingsMouse class void convToUniqueIDAutoProfGroupSett(QSettings *sett, QString guidAutoProfSett, QString uniqueAutoProfSett); signals: void changeLanguage(QString language); // MainSettingsLang class protected slots: void mappingsTableItemChanged(QTableWidgetItem *item); // MainSettingsMapping class void insertMappingRow(); // MainSettingsMapping class void deleteMappingRow(); // MainSettingsMapping class void syncMappingSettings(); // MainSettingsMapping class void saveNewSettings(); void selectDefaultProfileDir(); // MainSettingsProfile class void fillGUIDComboBox(); // MainSettingsProfile class void changeDeviceForProfileTable(int index); // MainSettingsProfile class void saveAutoProfileSettings(); // MainSettingsProfile class void processAutoProfileActiveClick(QTableWidgetItem *item); // MainSettingsProfile class void openAddAutoProfileDialog(); // MainSettingsProfile class void openEditAutoProfileDialog(); // MainSettingsProfile class void openDeleteAutoProfileConfirmDialog(); // MainSettingsProfile class void changeAutoProfileButtonsState(); // MainSettingsProfile class void transferEditsToCurrentTableRow(AddEditAutoProfileDialog *dialog); // MainSettingsProfile class void transferAllProfileEditToCurrentTableRow(EditAllDefaultAutoProfileDialog *dialog); // MainSettingsProfile class void addNewAutoProfile(AddEditAutoProfileDialog *dialog); // MainSettingsProfile class void autoProfileButtonsActiveState(bool enabled); // MainSettingsProfile class void changeKeyRepeatWidgetsStatus(bool enabled); // MainSettingsProfile class void checkSmoothingWidgetStatus(bool enabled); // MainSettingsMouse class void resetMouseAcceleration(); // MainSettingsMouse class void selectLogFile(); // MainSettingsLogs class private slots: void on_resetBtn_clicked(); private: Ui::MainSettingsDialog *ui; AntiMicroSettings *settings; QMap defaultAutoProfiles; // Default profiles assigned to a specific device QMap> deviceAutoProfiles; // Profiles assigned with an association with an application QMap> exeAutoProfiles; QList defaultList; QList profileList; AutoProfileInfo *allDefaultProfile; QList *connectedDevices; void resetGeneralSett(); void resetAutoProfSett(); void resetMouseSett(); void resetAdvancedSett(); }; #endif // MAINSETTINGSDIALOG_H AntiMicroX-antimicrox-2888bf6/src/mainsettingsdialog.ui000066400000000000000000001406331377703515000233050ustar00rootroot00000000000000 MainSettingsDialog Qt::WindowModal 0 0 555 664 0 0 0 0 Edit Settings true 0 0 180 16777215 QListView::TopToBottom false QListView::Fixed false -1 General Controller Mappings Language Auto Profile Mouse Advanced 0 0 0 4 9 20 Pro&file Directory: profileDefaultDirLineEdit <html><head/><body><p>Specify the default directory that the program should use in file dialogs when loading a profile or saving a new profile.</p></body></html> 512 true false Recent Profile Count: <html><head/><body><p>Number of profiles that can be placed in recent profile list. 0 will result in the program not enforcing a limit on the number of profiles displayed.</p></body></html> 100 5 Qt::Vertical QSizePolicy::Fixed 20 8 8 Gamepad Poll Rate: Change the poll rate that the program uses to discover new events from gamepads. Defaults to 10 ms. Reducing the poll rate value could cause the application to use more CPU power so please test the setting that you use before using AntiMicroX unattended. Hide main window when the main window close button is clicked instead of quitting the program. Close To Tray Have Windows start AntiMicroX at system startup. Launch At Windows Startup Display recent profiles for all controllers as a single list in the tray menu. Defaults to using sub-menus. Single Profile List in Tray Have the program minimize to the taskbar. By default, the program minimizes to the system tray if available. Minimize to Taskbar This option will cause the program to hide all buttons that have no slots assigned to them. The Quick Set dialog window will have to be used to bring up the edit dialog for gamepad buttons. Hide Empty Buttons When the program is launched, open the last known profile that was opened during the previous session. Auto Load Last Opened Profile true Only show the system tray icon when the program first launches. Launch in Tray Associate .amgp files with AntiMicroX in Windows Explorer. Associate Profiles true Remember, it won't work if you don't have such keypad connected to computer or if it's not embedded like in desktop PCs -1 Attach the numeric keypad Qt::Vertical QSizePolicy::Minimum 20 10 Key Repeat Active keys will be repeatedly pressed when this option is enabled. Enable Delay: false Specifies how much time should elapse before key repeating begins. 250 1000 10 100 660 Qt::Horizontal QSlider::NoTicks false ms 250 1000 100 660 Rate: false Specifies how many times key presses will be performed per seconds. 5 50 25 Qt::Horizontal QSlider::NoTicks false times/s 5 50 25 4 9 Below is a list of the custom mappings that have been saved. You can use the following table to delete mappings or have mappings temporarily disabled. You can also disable mappings that are included with SDL; just insert a new row with the appropriate joystick GUID and check disable. Settings will not take affect until you either refresh all joysticks or unplug that particular joystick. false true QAbstractItemView::SingleSelection true false 70 200 50 50 GUID Mapping String Disable? Add .. Delete .. 4 <html><head/><body><p>AntiMicroX has been translated into many different languages by contributors. By default, the program will choose an appropriate translation based on your system's locale setting. However, you can make AntiMicroX load a different translation depending on the language that you choose from the list below.</p></body></html> true Qt::Vertical QSizePolicy::Minimum 10 10 -1 Default Português do Brasil English Français Deutsch Italiano 日本語 Русский српски / srpski 简体中文 Español українська Polski 4 Active 20 Qt::Horizontal 40 20 Devices: All Qt::Vertical QSizePolicy::Fixed 20 10 false QAbstractItemView::SingleSelection QAbstractItemView::SelectRows 8 false true 100 false true false Active Device Profile Class Title Program Default? Qt::Vertical QSizePolicy::Fixed 20 10 false Add .. false Edit .. false Delete .. 10 4 Disable the "Enhanced Pointer Precision" Windows setting while AntiMicroX is running. Disabling "Enhanced Pointer Precision" will allow mouse movement within AntiMicroX to be more precise. Disable Enhance Pointer Precision true Smoothing 10 20 Enable History Si&ze: historySizeSpinBox false 1 100 10 Weight Modi&fier: weightModifierDoubleSpinBox false 1.000000000000000 0.100000000000000 0.200000000000000 Refresh Rate: The refresh rate is the amount of time that will elapse in between mouse events. Please be cautious when editing this setting as it will cause the program to use more CPU power. Setting this value too low can cause system instability. Please test the setting before using it unattended. Spring 10 20 Screen: springScreenComboBox Utilize the specified screen for spring mode. On Linux, the default is to use the primary screen. On Windows, the default is to use all available screens. QFrame::StyledPanel QFrame::Raised 6 0 0 Accel Numerator: 0 0 0 Qt::Horizontal 40 20 Accel Denominator: 0 Qt::Horizontal 40 20 Accel Threshold: 0 Qt::Horizontal 40 20 Qt::Horizontal 40 20 If the acceleration values for the virtual mouse have been changed by a different process, particularly when quitting an older game, then you might want to reset the acceleration values used by the virtual mouse. Reset Acceleration Qt::Vertical 20 20 Qt::Vertical QSizePolicy::Minimum 20 10 QLayout::SetMinimumSize Log File: Qt::Vertical QSizePolicy::Minimum 20 10 QLayout::SetMinimumSize Qt::LeftToRight Log Level: 0 0 None Error Warning Info Debug Qt::Horizontal 40 20 Qt::Vertical QSizePolicy::Minimum 20 10 QLayout::SetMinimumSize 0 0 50 true false Note: To see the change of log level in console output (not in log file), application restart is required true Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true -1 Qt::Vertical 20 40 5 5 5 5 Reset Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() MainSettingsDialog accept() 248 254 157 274 buttonBox rejected() MainSettingsDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/mainwindow.cpp000066400000000000000000002027411377703515000217400ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mainwindow.h" #include "ui_mainwindow.h" #include "aboutdialog.h" #include "antimicrosettings.h" #include "autoprofileinfo.h" #include "commandlineutility.h" #include "inputdevice.h" #include "messagehandler.h" //#include "autoprofilewatcher.h" #include "advancestickassignmentdialog.h" #include "calibration.h" #include "common.h" #include "dpadpushbutton.h" #include "gamecontrollermappingdialog.h" #include "joyaxiswidget.h" #include "joybuttonwidget.h" #include "joycontrolstickbuttonpushbutton.h" #include "joycontrolstickpushbutton.h" #include "joydpadbuttonwidget.h" #include "joystick.h" #include "joystickstatuswindow.h" #include "joytabwidget.h" #include "mainsettingsdialog.h" #include "qkeydisplaydialog.h" #include "xml/inputdevicexml.h" #include "xml/joybuttonslotxml.h" #if defined(WITH_X11) #include "autoprofileinfo.h" #include "autoprofilewatcher.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CHECK_BATTERIES_MSEC 600000 MainWindow::MainWindow(QMap *joysticks, CommandLineUtility *cmdutility, AntiMicroSettings *settings, bool graphical, QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); setWindowIcon(PadderCommon::loadIcon("antimicrox", ":/images/antimicrox.png")); qInstallMessageHandler(MessageHandler::myMessageOutput); ui->stackedWidget->setCurrentIndex(0); m_translator = nullptr; m_appTranslator = nullptr; m_cmdutility = cmdutility; m_graphical = graphical; m_settings = settings; ui->actionStick_Pad_Assign->setVisible(false); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { this->appWatcher = new AutoProfileWatcher(settings, this); checkAutoProfileWatcherTimer(); } else { this->appWatcher = nullptr; qDebug() << "appWatcher instance set to null pointer"; } #endif signalDisconnect = false; showTrayIcon = !cmdutility->isTrayHidden() && graphical && !cmdutility->shouldListControllers() && !cmdutility->shouldMapController(); m_joysticks = joysticks; if (showTrayIcon) { trayIconMenu = new QMenu(this); trayIcon = new QSystemTrayIcon(this); trayIcon->setContextMenu(trayIconMenu); connect(trayIconMenu, &QMenu::aboutToShow, this, &MainWindow::refreshTrayIconMenu); connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::trayIconClickAction); } // Look at flags and call setEnabled as desired; defaults to true. // Enabled status is used to specify whether errors in profile loading and // saving should be display in a window or written to stderr. if (graphical) { if (cmdutility->isHiddenRequested() && cmdutility->isTrayHidden()) { setEnabled(false); } } else { setEnabled(false); } resize(settings->value("WindowSize", size()).toSize()); move(settings->value("WindowPosition", pos()).toPoint()); if (graphical) { aboutDialog = new AboutDialog(this); } else { aboutDialog = nullptr; } QMenu *menuPointer = ui->menuQuit; connect(ui->menuQuit, &QMenu::aboutToShow, this, [this, menuPointer] { mainMenuChange(menuPointer); }); QMenu *menuPointerOptions = ui->menuOptions; connect(ui->menuOptions, &QMenu::aboutToShow, this, [this, menuPointerOptions] { mainMenuChange(menuPointerOptions); }); connect(ui->actionKeyValue, &QAction::triggered, this, &MainWindow::openKeyCheckerDialog); connect(ui->actionAbout_Qt, &QAction::triggered, qApp, &QApplication::aboutQt); connect(ui->actionProperties, &QAction::triggered, this, &MainWindow::openJoystickStatusWindow); connect(ui->actionGitHubPage, &QAction::triggered, this, &MainWindow::openGitHubPage); connect(ui->actionIssues, &QAction::triggered, this, &MainWindow::openIssuesPage); connect(ui->actionOptions, &QAction::triggered, this, &MainWindow::openMainSettingsDialog); connect(ui->actionWiki, &QAction::triggered, this, &MainWindow::openWikiPage); connect(ui->actionCalibration, &QAction::triggered, this, &MainWindow::openCalibration); connect(ui->actionGameController_Mapping, &QAction::triggered, this, &MainWindow::openGameControllerMappingWindow); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { connect(appWatcher, &AutoProfileWatcher::foundApplicableProfile, this, &MainWindow::autoprofileLoad); } #endif ui->uacPushButton->setVisible(false); QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, [this]() { this->checkEachTenMinutesBattery(m_joysticks); }); timer->start(CHECK_BATTERIES_MSEC); } MainWindow::~MainWindow() { qInstallMessageHandler(MessageHandler::myMessageOutput); qDebug() << "removing main window"; if (trayIconMenu != nullptr) trayIconMenu->clear(); installEventFilter(trayIconMenu); installEventFilter(trayIcon); if (trayIconMenu != nullptr) delete trayIconMenu; if (trayIcon != nullptr) delete trayIcon; delete ui; } void MainWindow::alterConfigFromSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_cmdutility->shouldListControllers()) { m_graphical = false; } else if (m_cmdutility->hasProfile()) { if (m_cmdutility->hasControllerNumber()) { loadConfigFile(m_cmdutility->getProfileLocation(), m_cmdutility->getControllerNumber()); } else if (m_cmdutility->hasControllerID()) { loadConfigFile(m_cmdutility->getProfileLocation(), m_cmdutility->hasControllerID()); } else { loadConfigFile(m_cmdutility->getProfileLocation()); } } const QList tempList = m_cmdutility->getControllerOptionsList(); // unsigned int optionListSize = tempList->size(); QListIterator optionIter(tempList); while (optionIter.hasNext()) { ControllerOptionsInfo temp = optionIter.next(); if (temp.hasProfile()) { if (temp.hasControllerNumber()) { loadConfigFile(temp.getProfileLocation(), temp.getControllerNumber()); } else if (temp.hasControllerID()) { loadConfigFile(temp.getProfileLocation(), temp.hasControllerID()); } else { loadConfigFile(temp.getProfileLocation()); } } else if (temp.isUnloadRequested()) { if (temp.hasControllerNumber()) { unloadCurrentConfig(temp.getControllerNumber()); } else if (temp.hasControllerID()) { unloadCurrentConfig(temp.hasControllerID()); } else { unloadCurrentConfig(0); } } if (temp.getStartSetNumber() > 0) { if (temp.hasControllerNumber()) { changeStartSetNumber(temp.getJoyStartSetNumber(), temp.getControllerNumber()); } else if (temp.hasControllerID()) { changeStartSetNumber(temp.getJoyStartSetNumber(), temp.getControllerID()); } else { changeStartSetNumber(temp.getJoyStartSetNumber()); } } } } void MainWindow::controllerMapOpening() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_cmdutility->shouldMapController()) { m_graphical = false; const QList tempList = m_cmdutility->getControllerOptionsList(); ControllerOptionsInfo temp = tempList.at(0); if (temp.hasControllerNumber()) { int joypadIndex = m_cmdutility->getControllerNumber(); qDebug() << "It was antimicrox --map controllerNumber"; qDebug() << "controllerNumber: " << joypadIndex; selectControllerJoyTab(joypadIndex); openGameControllerMappingWindow(true); } else if (temp.hasControllerID()) { QString joypadGUID = m_cmdutility->getControllerID(); qDebug() << "It was antimicrox --map controllerID"; qDebug() << "controllerID: " << joypadGUID; selectControllerJoyTab(joypadGUID); openGameControllerMappingWindow(true); } else { qDebug() << "Could not find a proper controller identifier. Exiting"; Logger::LogInfo(tr("Could not find a proper controller identifier. " "Exiting.")); qApp->quit(); } } } void MainWindow::fillButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); fillButtonsMap(m_joysticks); } void MainWindow::makeJoystickTabs() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->stackedWidget->setCurrentIndex(0); removeJoyTabs(); // Make temporary QMap with devices inserted using the device index as the // key rather than joystick ID. QMap temp; QMapIterator iterTemp(*m_joysticks); while (iterTemp.hasNext()) { iterTemp.next(); InputDevice *joystick = iterTemp.value(); temp.insert(joystick->getJoyNumber(), joystick); } QMapIterator iter(temp); while (iter.hasNext()) { iter.next(); InputDevice *joystick = iter.value(); JoyTabWidget *tabwidget = new JoyTabWidget(joystick, m_settings, this); QString joytabName = joystick->getSDLName(); joytabName.append(" ").append(tr("(%1)").arg(joystick->getName())); ui->tabWidget->addTab(tabwidget, joytabName); } if (m_joysticks != nullptr) { ui->tabWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(1); } } void MainWindow::fillButtonsID(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); int joyindex = joystick->getJoyNumber(); JoyTabWidget *tabwidget = qobject_cast(ui->tabWidget->widget(joyindex)); // static_cast tabwidget->refreshButtons(); } void MainWindow::fillButtonsMap(QMap *joysticks) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->stackedWidget->setCurrentIndex(0); removeJoyTabs(); // Make temporary QMap with devices inserted using the device index as the // key rather than joystick ID. QMap temp; QMapIterator iterTemp(*joysticks); while (iterTemp.hasNext()) { iterTemp.next(); InputDevice *joystick = iterTemp.value(); temp.insert(joystick->getJoyNumber(), joystick); } QMapIterator iter(temp); while (iter.hasNext()) { iter.next(); InputDevice *joystick = iter.value(); JoyTabWidget *tabwidget = new JoyTabWidget(joystick, m_settings, this); QString joytabName = joystick->getSDLName(); joytabName.append(" ").append(tr("(%1)").arg(joystick->getName())); ui->tabWidget->addTab(tabwidget, joytabName); tabwidget->refreshButtons(); connect(tabwidget, &JoyTabWidget::namesDisplayChanged, this, [this, tabwidget](bool displayNames) { propogateNameDisplayStatus(tabwidget, displayNames); }); connect(tabwidget, &JoyTabWidget::mappingUpdated, this, &MainWindow::propogateMappingUpdate); if (showTrayIcon) { connect(tabwidget, &JoyTabWidget::joystickConfigChanged, this, &MainWindow::populateTrayIcon); } } if (joysticks->size() > 0) { loadAppConfig(); ui->tabWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(1); } if (showTrayIcon) { populateTrayIcon(); trayIcon->show(); } ui->actionUpdate_Joysticks->setEnabled(true); ui->actionHide->setEnabled(true); ui->actionQuit->setEnabled(true); } // Intermediate slot to be used in Form Designer void MainWindow::startJoystickRefresh() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->stackedWidget->setCurrentIndex(0); ui->actionUpdate_Joysticks->setEnabled(false); ui->actionHide->setEnabled(false); ui->actionQuit->setEnabled(false); removeJoyTabs(); emit joystickRefreshRequested(); } void MainWindow::populateTrayIcon() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(trayIconMenu, &QMenu::aboutToShow, this, &MainWindow::singleTrayProfileMenuShow); trayIconMenu->clear(); profileActions.clear(); closeAction = new QAction(tr("&Quit"), trayIconMenu); closeAction->setIcon(PadderCommon::loadIcon("application-exit", ":/icons/actions/application_exit.png")); connect(closeAction, &QAction::triggered, this, &MainWindow::quitProgram, Qt::DirectConnection); hideAction = new QAction(tr("&Hide"), trayIconMenu); hideAction->setIcon(PadderCommon::loadIcon("view-restore", ":/icons/actions/view_restore.png")); connect(hideAction, &QAction::triggered, this, &MainWindow::hideWindow); restoreAction = new QAction(tr("&Restore"), trayIconMenu); restoreAction->setIcon(PadderCommon::loadIcon("view-fullscreen", ":/icons/actions/view_fullscreen.png")); connect(restoreAction, &QAction::triggered, this, &MainWindow::show); updateJoy = new QAction(tr("&Update Joysticks"), trayIconMenu); updateJoy->setIcon(PadderCommon::loadIcon("view-refresh", ":/icons/actions/view_refresh.png")); connect(updateJoy, &QAction::triggered, this, &MainWindow::startJoystickRefresh); int joystickCount = m_joysticks->size(); qDebug() << "joystickCount: " << joystickCount << endl; QMap uniques = QMap(); int counterUniques = 1; bool duplicatedGamepad = false; if (joystickCount > 0) { QMapIterator iter(*m_joysticks); bool useSingleList = m_settings->value("TrayProfileList", false).toBool(); qDebug() << "TrayProfileList: " << useSingleList << endl; if (!useSingleList && (joystickCount == 1)) useSingleList = true; int i = 0; while (iter.hasNext()) { iter.next(); InputDevice *current = iter.value(); QString joytabName = current->getSDLName(); joytabName.append(" ").append(tr("(%1)").arg(current->getName())); qDebug() << "joytabName" << i << ": " << joytabName << endl; QMenu *joysticksubMenu = nullptr; if (!useSingleList) joysticksubMenu = trayIconMenu->addMenu(joytabName); JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (widget != nullptr) { QHash *configs = widget->recentConfigs(); QHashIterator configIter(*configs); QList tempProfileList; while (configIter.hasNext()) { configIter.next(); QAction *newaction = nullptr; if (joysticksubMenu != nullptr) { newaction = new QAction(configIter.value(), joysticksubMenu); } else { newaction = new QAction(configIter.value(), trayIconMenu); } newaction->setCheckable(true); newaction->setChecked(false); if (uniques.contains(current->getGUIDString()) && joystickCount < uniques[current->getGUIDString()]) { ++uniques[current->getGUIDString()]; duplicatedGamepad = true; } else if (joystickCount < uniques[current->getGUIDString()]) { uniques.insert(current->getGUIDString(), counterUniques); } int resultDuplicated = 0; if (duplicatedGamepad) resultDuplicated = uniques[current->getGUIDString()]; current->setCounterUniques(resultDuplicated); QString identifier = current->getStringIdentifier(); qDebug() << "current identifier: " << current->getStringIdentifier() << endl; widget->convToUniqueIDControllerGroupSett( m_settings, QString("Controller%1LastSelected").arg(current->getGUIDString()), QString("Controller%1LastSelected").arg(current->getUniqueIDString())); QString controlEntryLastSelected = QString("Controller%1LastSelected").arg(identifier); qDebug() << "controlEntryLastSelected: " << controlEntryLastSelected << endl; duplicatedGamepad = false; QString contrFile = m_settings->value(controlEntryLastSelected).toString(); QFileInfo fileInfo(contrFile); qDebug() << "controlEntryLastSelected in config file: " << contrFile << endl; qDebug() << "fileInfo.exists(): " << fileInfo.exists() << endl; qDebug() << "fileInfo.size(): " << fileInfo.size() << endl; qDebug() << "fileInfo.permissions(): " << fileInfo.permissions() << endl; if ((configIter.value() == fileInfo.baseName()) || (configIter.value() == widget->getCurrentConfigName())) { qDebug() << "fileInfo.baseName(): " << fileInfo.baseName() << endl; qDebug() << "widget->getCurrentConfigName(): " << widget->getCurrentConfigName() << endl; newaction->setChecked(true); } QHash tempmap; qDebug() << "insert " << QString::number(i) << ": " << configIter.key() << endl; tempmap.insert(QString::number(i), QVariant(configIter.key())); QVariant tempvar(tempmap); newaction->setData(tempvar); connect(newaction, &QAction::triggered, this, [this, newaction](bool checked) { profileTrayActionTriggered(newaction, checked); }); if (useSingleList) { qDebug() << "useSingleList" << endl; tempProfileList.append(newaction); } else { qDebug() << "doesn't useSingleList" << endl; joysticksubMenu->addAction(newaction); } } delete configs; configs = nullptr; QAction *newaction = nullptr; if (joysticksubMenu != nullptr) { qDebug() << "joysticksubmenu exists" << endl; newaction = new QAction(tr("Open File"), joysticksubMenu); } else { qDebug() << "created action open file for tray" << endl; newaction = new QAction(tr("Open File"), trayIconMenu); } newaction->setIcon(PadderCommon::loadIcon("document-open", ":/icons/actions/document_open.png")); connect(newaction, &QAction::triggered, widget, &JoyTabWidget::openConfigFileDialog); if (useSingleList) { qDebug() << "usesinglelist" << endl; QAction *titleAction = new QAction(joytabName, trayIconMenu); titleAction->setCheckable(false); QFont actionFont = titleAction->font(); actionFont.setBold(true); titleAction->setFont(actionFont); trayIconMenu->addAction(titleAction); trayIconMenu->addActions(tempProfileList); trayIconMenu->addAction(newaction); profileActions.insert(i, tempProfileList); qDebug() << "inserted profile action " << i << ": " << tempProfileList << endl; if (iter.hasNext()) { trayIconMenu->addSeparator(); } } else { joysticksubMenu->addAction(newaction); connect(joysticksubMenu, &QMenu::aboutToShow, this, [this, joysticksubMenu] { joystickTrayShow(joysticksubMenu); }); } i++; } } if (useSingleList) { connect(trayIconMenu, &QMenu::aboutToShow, this, &MainWindow::singleTrayProfileMenuShow); } trayIconMenu->addSeparator(); } trayIconMenu->addAction(hideAction); trayIconMenu->addAction(restoreAction); trayIconMenu->addAction(updateJoy); trayIconMenu->addAction(closeAction); QIcon icon = PadderCommon::loadIcon("antimicrox_trayicon", ":/images/antimicrox_trayicon.png"); trayIcon->setIcon(icon); trayIcon->setContextMenu(trayIconMenu); qDebug() << "end of MainWindow::populateTrayIcon function" << endl; } void MainWindow::quitProgram() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool discard = true; #ifdef WITH_X11 AutoProfileWatcher::getAutoProfileWatcherInstance()->disconnectWindowTimer(); #endif for (int i = 0; (i < ui->tabWidget->count()) && discard; i++) { JoyTabWidget *tab = qobject_cast(ui->tabWidget->widget(i)); discard = tab->discardUnsavedProfileChanges(); } if (discard) qApp->quit(); } void MainWindow::refreshTrayIconMenu() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (this->isHidden()) { hideAction->setEnabled(false); restoreAction->setEnabled(true); } else { hideAction->setEnabled(true); restoreAction->setEnabled(false); } } void MainWindow::trayIconClickAction(QSystemTrayIcon::ActivationReason reason) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (reason == QSystemTrayIcon::Trigger) { if (this->isHidden()) { this->show(); } else { this->hideWindow(); } } } void MainWindow::mainMenuChange(QMenu *tempMenu) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (tempMenu == ui->menuQuit) { if (showTrayIcon) { ui->actionHide->setEnabled(true); } else { ui->actionHide->setEnabled(false); } } } void MainWindow::saveAppConfig() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_joysticks->size() > 0) { JoyTabWidget *temptabwidget = qobject_cast(ui->tabWidget->widget(0)); // static_cast m_settings->setValue("DisplayNames", temptabwidget->isDisplayingNames() ? "1" : "0"); m_settings->beginGroup("Controllers"); QStringList tempIdentifierHolder = QStringList(); for (int i = 0; i < ui->tabWidget->count(); i++) { bool prepareSave = true; JoyTabWidget *tabwidget = qobject_cast(ui->tabWidget->widget(i)); // static_cast InputDevice *device = tabwidget->getJoystick(); // Do not allow multi-controller adapters to overwrite each // others recent config file list. Use first controller // detected to save recent config list. Flag controller string // afterwards. if (!device->getStringIdentifier().isEmpty()) { if (tempIdentifierHolder.contains(device->getStringIdentifier())) { prepareSave = false; } else { tempIdentifierHolder.append(device->getStringIdentifier()); } } if (prepareSave) { tabwidget->saveSettings(); } } m_settings->endGroup(); } m_settings->setValue("WindowSize", size()); m_settings->setValue("WindowPosition", pos()); } void MainWindow::loadAppConfig(bool forceRefresh) { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *tabwidget = qobject_cast(ui->tabWidget->widget(i)); // static_cast tabwidget->loadSettings(forceRefresh); } } void MainWindow::disableFlashActions() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < ui->tabWidget->count(); i++) { QList list = ui->tabWidget->widget(i)->findChildren(); QListIterator iter(list); while (iter.hasNext()) { JoyButtonWidget *buttonWidget = iter.next(); buttonWidget->disableFlashes(); } QList list2 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter2(list2); while (iter2.hasNext()) { JoyAxisWidget *axisWidget = iter2.next(); axisWidget->disableFlashes(); } QList list3 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter3(list3); while (iter3.hasNext()) { JoyControlStickPushButton *stickWidget = iter3.next(); stickWidget->disableFlashes(); } QList list4 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter4(list4); while (iter4.hasNext()) { JoyDPadButtonWidget *dpadWidget = iter4.next(); dpadWidget->disableFlashes(); } QList list6 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter6(list6); while (iter6.hasNext()) { JoyControlStickButtonPushButton *stickButtonWidget = iter6.next(); stickButtonWidget->disableFlashes(); } QList list7 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter7(list7); while (iter7.hasNext()) { DPadPushButton *dpadWidget = iter7.next(); dpadWidget->disableFlashes(); } JoyTabWidget *tabWidget = qobject_cast(ui->tabWidget->widget(i)); // static_cast ui->tabWidget->disableFlashes(tabWidget->getJoystick()); } } void MainWindow::enableFlashActions() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < ui->tabWidget->count(); i++) { QList list = ui->tabWidget->widget(i)->findChildren(); QListIterator iter(list); while (iter.hasNext()) { JoyButtonWidget *buttonWidget = iter.next(); buttonWidget->enableFlashes(); buttonWidget->tryFlash(); } QList list2 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter2(list2); while (iter2.hasNext()) { JoyAxisWidget *axisWidget = iter2.next(); axisWidget->enableFlashes(); axisWidget->tryFlash(); } QList list3 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter3(list3); while (iter3.hasNext()) { JoyControlStickPushButton *stickWidget = iter3.next(); stickWidget->enableFlashes(); stickWidget->tryFlash(); } QList list4 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter4(list4); while (iter4.hasNext()) { JoyDPadButtonWidget *dpadWidget = iter4.next(); dpadWidget->enableFlashes(); dpadWidget->tryFlash(); } QList list6 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter6(list6); while (iter6.hasNext()) { JoyControlStickButtonPushButton *stickButtonWidget = iter6.next(); stickButtonWidget->enableFlashes(); stickButtonWidget->tryFlash(); } QList list7 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter7(list7); while (iter7.hasNext()) { DPadPushButton *dpadWidget = iter7.next(); dpadWidget->enableFlashes(); dpadWidget->tryFlash(); } JoyTabWidget *tabWidget = qobject_cast(ui->tabWidget->widget(i)); // static_cast ui->tabWidget->enableFlashes(tabWidget->getJoystick()); } } // Intermediate slot used in Design mode void MainWindow::hideWindow() { qInstallMessageHandler(MessageHandler::myMessageOutput); disableFlashActions(); signalDisconnect = true; hide(); } void MainWindow::joystickTrayShow(QMenu *tempmenu) { qInstallMessageHandler(MessageHandler::myMessageOutput); QList menuactions = tempmenu->actions(); QListIterator listiter(menuactions); while (listiter.hasNext()) { QAction *action = listiter.next(); action->setChecked(false); QHash tempmap = action->data().toHash(); QHashIterator iter(tempmap); while (iter.hasNext()) { iter.next(); int joyindex = iter.key().toInt(); int configindex = iter.value().toInt(); JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(joyindex)); // static_cast if (configindex == widget->getCurrentConfigIndex()) { action->setChecked(true); if (widget->getJoystick()->isDeviceEdited()) { action->setIcon(PadderCommon::loadIcon("document-save-as", ":/icons/actions/document_save_as.png")); } else if (!action->icon().isNull()) { action->setIcon(QIcon()); } } else if (!action->icon().isNull()) { action->setIcon(QIcon()); } if (action->text() != widget->getConfigName(configindex)) { action->setText(widget->getConfigName(configindex)); } } } } void MainWindow::showEvent(QShowEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Check if hideEvent has been processed if (signalDisconnect && isVisible()) { // Restore flashing buttons enableFlashActions(); signalDisconnect = false; // Only needed if hidden with the system tray enabled if (showTrayIcon) { if (isMinimized()) { if (isMaximized()) { showMaximized(); } else { showNormal(); } activateWindow(); raise(); } } } QMainWindow::showEvent(event); } void MainWindow::changeEvent(QEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (event->type() == QEvent::WindowStateChange) { QWindowStateChangeEvent *e = static_cast(event); if (e->oldState() != Qt::WindowMinimized && isMinimized()) { bool minimizeToTaskbar = m_settings->value("MinimizeToTaskbar", false).toBool(); if (QSystemTrayIcon::isSystemTrayAvailable() && showTrayIcon && !minimizeToTaskbar) { this->hideWindow(); } else { disableFlashActions(); signalDisconnect = true; } } } else if (event->type() == QEvent::LanguageChange) { retranslateUi(); } QMainWindow::changeEvent(event); } void MainWindow::openAboutDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); aboutDialog->show(); } void MainWindow::loadConfigFile(QString fileLocation, int joystickIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((joystickIndex > 0) && m_joysticks->contains(joystickIndex - 1)) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(joystickIndex - 1)); // static_cast if (widget != nullptr) { widget->loadConfigFile(fileLocation); } } else if (joystickIndex <= 0) { for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (widget != nullptr) { widget->loadConfigFile(fileLocation); } } } } void MainWindow::loadConfigFile(QString fileLocation, QString controllerID) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!controllerID.isEmpty()) { QListIterator iter(ui->tabWidget->findChildren()); while (iter.hasNext()) { JoyTabWidget *tab = iter.next(); if (tab != nullptr) { InputDevice *tempdevice = tab->getJoystick(); if (controllerID == tempdevice->getStringIdentifier()) { tab->loadConfigFile(fileLocation); } } } } } void MainWindow::removeJoyTabs() { qInstallMessageHandler(MessageHandler::myMessageOutput); int oldtabcount = ui->tabWidget->count(); for (int i = oldtabcount - 1; i >= 0; i--) { QWidget *tab = ui->tabWidget->widget(i); delete tab; tab = nullptr; } ui->tabWidget->clear(); } void MainWindow::handleInstanceDisconnect() { qInstallMessageHandler(MessageHandler::myMessageOutput); m_settings->sync(); loadAppConfig(true); } void MainWindow::openJoystickStatusWindow() { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->tabWidget->currentIndex(); if (index >= 0) { JoyTabWidget *joyTab = qobject_cast(ui->tabWidget->widget(index)); // static_cast InputDevice *joystick = joyTab->getJoystick(); if (joystick != nullptr) { JoystickStatusWindow *dialog = new JoystickStatusWindow(joystick, this); dialog->show(); } } } void MainWindow::openKeyCheckerDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); QKeyDisplayDialog *dialog = new QKeyDisplayDialog(this); dialog->show(); } void MainWindow::openGitHubPage() { qInstallMessageHandler(MessageHandler::myMessageOutput); QDesktopServices::openUrl(QUrl(PadderCommon::githubProjectPage)); } void MainWindow::openIssuesPage() { qInstallMessageHandler(MessageHandler::myMessageOutput); QDesktopServices::openUrl(QUrl(PadderCommon::githubIssuesPage)); } void MainWindow::openWikiPage() { qInstallMessageHandler(MessageHandler::myMessageOutput); QDesktopServices::openUrl(QUrl(PadderCommon::wikiPage)); } void MainWindow::openCalibration() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (m_joysticks->isEmpty()) { QMessageBox::information(this, tr("Calibration couldn't be opened"), tr("You must connect at least one controller to open the window")); } else { int index = ui->tabWidget->currentIndex(); if (index >= 0) { JoyTabWidget *joyTab = qobject_cast(ui->tabWidget->widget(index)); // static_cast InputDevice *joystick = joyTab->getJoystick(); if (joystick != nullptr) { QPointer calibration = new Calibration(joystick); calibration.data()->show(); if (calibration.isNull()) calibration.clear(); } } } } void MainWindow::unloadCurrentConfig(int joystickIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((joystickIndex > 0) && m_joysticks->contains(joystickIndex - 1)) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(joystickIndex - 1)); // static_cast if (widget != nullptr) { widget->unloadConfig(); } } else if (joystickIndex <= 0) { for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (widget != nullptr) { widget->unloadConfig(); } } } } void MainWindow::unloadCurrentConfig(QString controllerID) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!controllerID.isEmpty()) { QListIterator iter(ui->tabWidget->findChildren()); while (iter.hasNext()) { JoyTabWidget *tab = iter.next(); if (tab != nullptr) { InputDevice *tempdevice = tab->getJoystick(); if (controllerID == tempdevice->getStringIdentifier()) { tab->unloadConfig(); } } } } } void MainWindow::propogateNameDisplayStatus(JoyTabWidget *tabwidget, bool displayNames) { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *tab = qobject_cast(ui->tabWidget->widget(i)); // static_cast if ((tab != nullptr) && (tab != tabwidget)) { if (tab->isDisplayingNames() != displayNames) { tab->changeNameDisplay(displayNames); } } } } void MainWindow::changeStartSetNumber(int startSetNumber, QString controllerID) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!controllerID.isEmpty()) { QListIterator iter(ui->tabWidget->findChildren()); while (iter.hasNext()) { JoyTabWidget *tab = iter.next(); if (tab != nullptr) { InputDevice *tempdevice = tab->getJoystick(); if (controllerID == tempdevice->getStringIdentifier()) { tab->changeCurrentSet(startSetNumber); } } } } } void MainWindow::changeStartSetNumber(int startSetNumber, int joystickIndex) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((joystickIndex > 0) && m_joysticks->contains(joystickIndex - 1)) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(joystickIndex - 1)); // static_cast if (widget != nullptr) { widget->changeCurrentSet(startSetNumber); } } else if (joystickIndex <= 0) { for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (widget != nullptr) { widget->changeCurrentSet(startSetNumber); } } } } /** * @brief Build list of current input devices and pass it to settings dialog * instance. Open Settings dialog. */ void MainWindow::openMainSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); QList *devices = new QList(m_joysticks->values()); MainSettingsDialog *dialog = new MainSettingsDialog(m_settings, devices, this); connect(dialog, &MainSettingsDialog::changeLanguage, this, &MainWindow::changeLanguage); if (appWatcher != nullptr) { #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { connect(dialog, &MainSettingsDialog::accepted, appWatcher, &AutoProfileWatcher::syncProfileAssignment); connect(dialog, &MainSettingsDialog::accepted, this, &MainWindow::checkAutoProfileWatcherTimer); connect(dialog, &MainSettingsDialog::rejected, this, &MainWindow::checkAutoProfileWatcherTimer); appWatcher->stopTimer(); qDebug() << "Stopping appWatcher in openMainSettingsDialog"; } #endif } connect(dialog, &MainSettingsDialog::accepted, this, &MainWindow::populateTrayIcon); connect(dialog, &MainSettingsDialog::accepted, this, &MainWindow::checkHideEmptyOption); dialog->show(); } /** * @brief Change language used by the application. * @param Language code */ void MainWindow::changeLanguage(QString language) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((m_translator != nullptr) && (m_appTranslator != nullptr)) { PadderCommon::reloadTranslations(m_translator, m_appTranslator, language); } } /** * @brief Check if the program should really quit or if it should * be minimized. * @param QCloseEvent */ void MainWindow::closeEvent(QCloseEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool closeToTray = m_settings->value("CloseToTray", false).toBool(); if (closeToTray && QSystemTrayIcon::isSystemTrayAvailable() && showTrayIcon) { this->hideWindow(); } else { qApp->quit(); } QMainWindow::closeEvent(event); } /** * @brief Show abstracted controller dialog for use in SDL 1.2. No longer * used for versions of the program running SDL 2. In SDL 2, * the Game Controller API is being used instead. */ void MainWindow::showStickAssignmentDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->tabWidget->currentIndex(); if (index >= 0) { JoyTabWidget *joyTab = qobject_cast(ui->tabWidget->widget(index)); // static_cast Joystick *joystick = qobject_cast(joyTab->getJoystick()); // static_cast AdvanceStickAssignmentDialog *dialog = new AdvanceStickAssignmentDialog(joystick, this); connect(dialog, &AdvanceStickAssignmentDialog::finished, joyTab, &JoyTabWidget::fillButtons); dialog->show(); } } /** * @brief Display a version of the tray menu that shows all recent profiles for * all controllers in one list. */ void MainWindow::singleTrayProfileMenuShow() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getProfileActions().isEmpty()) { QMapIterator> mapIter(getProfileActions()); while (mapIter.hasNext()) { mapIter.next(); QList menuactions = mapIter.value(); QListIterator listiter(menuactions); while (listiter.hasNext()) { QAction *action = listiter.next(); action->setChecked(false); QHash tempmap = action->data().toHash(); QHashIterator iter(tempmap); while (iter.hasNext()) { iter.next(); int joyindex = iter.key().toInt(); int configindex = iter.value().toInt(); JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(joyindex)); // static_cast if (configindex == widget->getCurrentConfigIndex()) { action->setChecked(true); if (widget->getJoystick()->isDeviceEdited()) { action->setIcon( PadderCommon::loadIcon("document-save-as", ":/icons/actions/document_save_as.png")); } else if (!action->icon().isNull()) { action->setIcon(QIcon()); } } else if (!action->icon().isNull()) { action->setIcon(QIcon()); } if (action->text() != widget->getConfigName(configindex)) { action->setText(widget->getConfigName(configindex)); } } } } } } void MainWindow::profileTrayActionTriggered(QAction *action, bool checked) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Obtaining the selected config QHash tempmap = action->data().toHash(); QHashIterator iter(tempmap); while (iter.hasNext()) { iter.next(); // Fetching indicies and tab associated with the current joypad int joyindex = iter.key().toInt(); int configindex = iter.value().toInt(); JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(joyindex)); // static_cast // Checking if the selected config has been disabled by the change (action->isChecked() represents the state of the // checkbox AFTER the click) if (!checked) { // It has - disabling - the 0th config is the new/'null' config widget->setCurrentConfig(0); } else { // It hasn't - enabling - note that setting this causes the menu to be updated widget->setCurrentConfig(configindex); } } } void MainWindow::checkHideEmptyOption() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *tab = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (tab != nullptr) { tab->checkHideEmptyOption(); } } } void MainWindow::openGameControllerMappingWindow(bool openAsMain) { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->tabWidget->currentIndex(); if (index >= 0) { JoyTabWidget *joyTab = qobject_cast(ui->tabWidget->widget(index)); // static_cast InputDevice *joystick = joyTab->getJoystick(); if (joystick != nullptr) { GameControllerMappingDialog *dialog = new GameControllerMappingDialog(joystick, m_settings, this); if (openAsMain) { dialog->setParent(nullptr); dialog->setWindowFlags(Qt::Window); connect(dialog, &GameControllerMappingDialog::finished, qApp, &QApplication::quit); } else { connect(dialog, &GameControllerMappingDialog::mappingUpdate, this, &MainWindow::propogateMappingUpdate); } dialog->show(); } } else if (openAsMain) { Logger::LogInfo(tr("Could not find controller. Exiting.")); qApp->quit(); } } void MainWindow::propogateMappingUpdate(QString mapping, InputDevice *device) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit mappingUpdated(mapping, device); } void MainWindow::testMappingUpdateNow(int index, InputDevice *device) { qInstallMessageHandler(MessageHandler::myMessageOutput); QWidget *tab = ui->tabWidget->widget(index); if (tab != nullptr) { ui->tabWidget->removeTab(index); delete tab; tab = nullptr; } JoyTabWidget *tabwidget = new JoyTabWidget(device, m_settings, this); QString joytabName = device->getSDLName(); joytabName.append(" ").append(tr("(%1)").arg(device->getName())); ui->tabWidget->insertTab(index, tabwidget, joytabName); tabwidget->refreshButtons(); ui->tabWidget->setCurrentIndex(index); connect(tabwidget, &JoyTabWidget::namesDisplayChanged, this, [this, tabwidget](bool displayNames) { propogateNameDisplayStatus(tabwidget, displayNames); }); connect(tabwidget, &JoyTabWidget::mappingUpdated, this, &MainWindow::propogateMappingUpdate); if (showTrayIcon) { connect(tabwidget, &JoyTabWidget::joystickConfigChanged, this, &MainWindow::populateTrayIcon); populateTrayIcon(); } } void MainWindow::removeJoyTab(SDL_JoystickID deviceID) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; for (int i = 0; (i < ui->tabWidget->count()) && !found; i++) { JoyTabWidget *tab = qobject_cast(ui->tabWidget->widget(i)); // static_cast if ((tab != nullptr) && (deviceID == tab->getJoystick()->getSDLJoystickID())) { // Save most recent profile list to settings before removing tab. tab->saveDeviceSettings(); // Remove flash event connections between buttons and // the tab before deleting tab. ui->tabWidget->disableFlashes(tab->getJoystick()); ui->tabWidget->removeTab(i); QMetaObject::invokeMethod(tab->getJoystick(), "finalRemoval"); delete tab; tab = nullptr; found = true; } } // Refresh tab text to reflect new index values. for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *tab = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (tab != nullptr) { InputDevice *device = tab->getJoystick(); QString joytabName = device->getSDLName(); joytabName.append(" ").append(tr("(%1)").arg(device->getName())); ui->tabWidget->setTabText(i, joytabName); } } if (showTrayIcon) populateTrayIcon(); if (ui->tabWidget->count() == 0) { ui->stackedWidget->setCurrentIndex(0); } } void MainWindow::addJoyTab(InputDevice *device) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyTabWidget *tabwidget = new JoyTabWidget(device, m_settings, this); QString joytabName = device->getSDLName(); joytabName.append(" ").append(tr("(%1)").arg(device->getName())); ui->tabWidget->addTab(tabwidget, joytabName); tabwidget->loadDeviceSettings(); tabwidget->refreshButtons(); // Refresh tab text to reflect new index values. for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *tab = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (tab != nullptr) { InputDevice *device_in_loop = tab->getJoystick(); QString joytabName_in_loop = device_in_loop->getSDLName(); joytabName_in_loop.append(" ").append(tr("(%1)").arg(device_in_loop->getName())); ui->tabWidget->setTabText(i, joytabName_in_loop); } } connect(tabwidget, &JoyTabWidget::namesDisplayChanged, this, [this, tabwidget](bool displayNames) { propogateNameDisplayStatus(tabwidget, displayNames); }); connect(tabwidget, &JoyTabWidget::mappingUpdated, this, &MainWindow::propogateMappingUpdate); if (showTrayIcon) { connect(tabwidget, &JoyTabWidget::joystickConfigChanged, this, &MainWindow::populateTrayIcon); populateTrayIcon(); } ui->stackedWidget->setCurrentIndex(1); } void MainWindow::autoprofileLoad(AutoProfileInfo *info) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (info != nullptr) { Logger::LogDebug(QObject::tr("Auto-switching to profile \"%1\".").arg(info->getProfileLocation())); } else { Logger::LogError(QObject::tr("Auto-switching to nullptr profile!")); } #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(i)); // static_cast if (widget != nullptr) { // if (info->getGUID() == "all") if (info->getUniqueID() == "all") { // If the all option for a Default profile was found, // first check for controller specific associations. If one exists, // skip changing the profile on the controller. A later call will // be used to switch the profile for that controller. QList *customs = appWatcher->getCustomDefaults(); bool found = false; QListIterator iter(*customs); while (iter.hasNext()) { AutoProfileInfo *tempinfo = iter.next(); // if (tempinfo->getGUID() == widget->getJoystick()->getGUIDString() && if (tempinfo->getUniqueID() == widget->getJoystick()->getUniqueIDString() && info->isCurrentDefault()) { found = true; iter.toBack(); qDebug() << "autoProfileInfo has the same GUID as GUID of joystick and the autoProfile is " "default. Found = true."; } } delete customs; customs = nullptr; // Check if profile has already been switched for a particular // controller. if (!found) { // QString tempguid = widget->getJoystick()->getGUIDString(); // if (appWatcher->isGUIDLocked(tempguid)) QString tempguid = widget->getJoystick()->getUniqueIDString(); if (appWatcher->isUniqueIDLocked(tempguid)) { found = true; qDebug() << "GUID is locked in appWatcher. Found = true."; } } if (!found) { // If the profile location is empty, assume // that an empty profile should get loaded. if (info->getProfileLocation().isEmpty()) { widget->setCurrentConfig(0); qDebug() << "profile location is empty. setCurrentConfig(0)"; } else { widget->loadConfigFile(info->getProfileLocation()); qDebug() << "loaded config file for current AutoLoadInfo"; } } } // else if (info->getGUID() == widget->getJoystick()->getStringIdentifier()) else if (info->getUniqueID() == widget->getJoystick()->getStringIdentifier()) { // qDebug() << "GUID of AutoProfileInfo: " << info->getGUID() << " == string identifier of // AutoProfileInfo: " << widget->getJoystick()->getStringIdentifier(); qDebug() << "GUID of AutoProfileInfo: " << info->getUniqueID() << " == string identifier of AutoProfileInfo: " << widget->getJoystick()->getStringIdentifier(); if (info->getProfileLocation().isEmpty()) { qDebug() << "profile location of AutoProfileInfo is empty. Set first config"; widget->setCurrentConfig(0); } else { qDebug() << "load config file for AutoProfileInfo"; widget->loadConfigFile(info->getProfileLocation()); } } } } } #endif } void MainWindow::checkAutoProfileWatcherTimer() { qInstallMessageHandler(MessageHandler::myMessageOutput); #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { QString autoProfileActive = m_settings->value("AutoProfiles/AutoProfilesActive", "0").toString(); if (autoProfileActive == "1") { appWatcher->startTimer(); qDebug() << "Started timer for appWatcher"; } else { appWatcher->stopTimer(); qDebug() << "Stopped timer for appWatcher"; } } #endif } /** * @brief TODO: Check if method is save to remove. */ void MainWindow::updateMenuOptions() { qInstallMessageHandler(MessageHandler::myMessageOutput); int index = ui->tabWidget->currentIndex(); if (index >= 0) { JoyTabWidget *joyTab = qobject_cast(ui->tabWidget->widget(index)); // static_cast InputDevice *joystick = joyTab->getJoystick(); if (qobject_cast(joystick) != nullptr) { ui->actionStick_Pad_Assign->setEnabled(false); } else { ui->actionStick_Pad_Assign->setEnabled(true); } } } void MainWindow::showBatteryLevel(SDL_JoystickPowerLevel powerLevSDL, QString batteryLev, QString percent, InputDevice *device) { if (SDL_JoystickCurrentPowerLevel(device->getJoyHandle()) == powerLevSDL) { QResource batteryFile(":/images/battery-low-level.png"); QPixmap pm(30, 30); pm.load(batteryFile.absoluteFilePath()); QMessageBox msgBox; msgBox.setWindowTitle(tr("%1 battery").arg(batteryLev)); msgBox.setIconPixmap(pm); msgBox.setText(tr("Battery level is less than %1").arg(percent)); msgBox.setInformativeText( tr("Device number: %1\nDevice name: %2").arg(device->getRealJoyNumber()).arg(device->getSDLName())); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.exec(); } } /** * @brief Select appropriate tab with the specified index. * @param Index of appropriate tab. */ void MainWindow::selectControllerJoyTab(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((index > 0) && m_joysticks->contains(index - 1)) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(index - 1)); // static_cast if (widget != nullptr) { qDebug() << "JoyTabWidget was not a null pointer in selectControllerJoyTab of index"; ui->tabWidget->setCurrentIndex(index - 1); } else { qDebug() << "JoyTabWidget was a NULL POINTER in selectControllerJoyTab of index"; } } } /** * @brief Select appropriate tab that has a device with the specified GUID. * @param GUID of joystick device. */ void MainWindow::selectControllerJoyTab(QString GUID) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!GUID.isEmpty()) { InputDevice *device = nullptr; QMapIterator deviceIter(*m_joysticks); while (deviceIter.hasNext()) { deviceIter.next(); InputDevice *tempDevice = deviceIter.value(); if (tempDevice && (GUID == tempDevice->getStringIdentifier())) { device = tempDevice; deviceIter.toBack(); } } if (device != nullptr) { qDebug() << "InputDevice was not a null pointer in selectControllerJoyTab of GUID"; ui->tabWidget->setCurrentIndex(device->getJoyNumber()); } else { qDebug() << "InputDevice was a NULL POINTER in selectControllerJoyTab of GUID"; } } } void MainWindow::changeWindowStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); // Check flags to see if user requested for the main window and the tray icon // to not be displayed. if (m_graphical) { bool launchInTraySetting = m_settings->runtimeValue("LaunchInTray", false).toBool(); if (!m_cmdutility->isHiddenRequested() && (!launchInTraySetting || !QSystemTrayIcon::isSystemTrayAvailable())) { show(); } else if (m_cmdutility->isHiddenRequested() && m_cmdutility->isTrayHidden()) { // Window should already be hidden but make sure // to disable flashing buttons. hideWindow(); setEnabled(false); // Should already be disabled. Do it again just to be sure. } else if (m_cmdutility->isHiddenRequested() || launchInTraySetting) { // Window should already be hidden but make sure // to disable flashing buttons. hideWindow(); setEnabled(true); } } } bool MainWindow::getGraphicalStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_graphical; } void MainWindow::setTranslator(QTranslator *translator) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_translator = translator; } QTranslator *MainWindow::getTranslator() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_translator; } void MainWindow::setAppTranslator(QTranslator *translator) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_appTranslator = translator; } QTranslator *MainWindow::getAppTranslator() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_appTranslator; } void MainWindow::retranslateUi() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->retranslateUi(this); } void MainWindow::refreshTabHelperThreads() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < ui->tabWidget->count(); i++) { JoyTabWidget *widget = qobject_cast(ui->tabWidget->widget(i)); if (widget != nullptr) { widget->refreshHelperThread(); } } } QMap> const &MainWindow::getProfileActions() { return profileActions; } bool MainWindow::isKeypadUnlocked() { if (m_settings == nullptr) return false; return m_settings->value("AttachNumKeypad", false).toBool(); } bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::Hide && (obj != nullptr)) { obj->deleteLater(); } return false; } void MainWindow::convertGUIDtoUniqueID(InputDevice *currentDevice, QString controlEntryLastSelectedGUID) { int exec = QMessageBox::information( this, tr("Reading old profile"), tr("This profile uses controllers' GUID numbers. Would you like to change GUID numbers to UniqueID in this file for " "use in identical gamecontrollers? Such old file cannot be loaded in antimicrox since version 2.25"), QMessageBox::Yes, QMessageBox::No); switch (exec) { case QMessageBox::Yes: QFile data(m_settings->value(controlEntryLastSelectedGUID).toString()); data.open(QIODevice::Text | QIODevice::ReadOnly); QString dataText = data.readAll(); QRegularExpression re(currentDevice->getGUIDString()); QString replacementText(currentDevice->getUniqueIDString()); dataText.replace(re, replacementText); QFile newData(m_settings->value(controlEntryLastSelectedGUID).toString()); if (newData.open(QFile::WriteOnly | QFile::Truncate)) { QTextStream out(&newData); out << dataText; } newData.close(); break; } } void MainWindow::checkEachTenMinutesBattery(QMap *joysticks) { QMapIterator deviceIter(*joysticks); while (deviceIter.hasNext()) { deviceIter.next(); InputDevice *tempDevice = deviceIter.value(); showBatteryLevel(SDL_JOYSTICK_POWER_LOW, "Low", "20%", tempDevice); showBatteryLevel(SDL_JOYSTICK_POWER_EMPTY, "Empty", "5%", tempDevice); } } AntiMicroX-antimicrox-2888bf6/src/mainwindow.h000066400000000000000000000134001377703515000213750ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include class InputDevice; class CommandLineUtility; class AntiMicroSettings; class QWidget; class QTranslator; class AutoProfileInfo; class AutoProfileWatcher; class QLocalServer; class AboutDialog; class QAction; class QMenu; class QShowEvent; class QEvent; class QCloseEvent; class JoyTabWidget; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QMap *joysticks, CommandLineUtility *cmdutility, AntiMicroSettings *settings, bool graphical = true, QWidget *parent = nullptr); ~MainWindow(); bool getGraphicalStatus(); void setTranslator(QTranslator *translator); QTranslator *getTranslator() const; void setAppTranslator(QTranslator *translator); QTranslator *getAppTranslator() const; QMap> const &getProfileActions(); bool isKeypadUnlocked(); protected: virtual void showEvent(QShowEvent *event); virtual void changeEvent(QEvent *event); virtual void closeEvent(QCloseEvent *event); bool eventFilter(QObject *obj, QEvent *event) override; void retranslateUi(); void loadConfigFile(QString fileLocation, int joystickIndex = 0); // MainConfiguration class void loadConfigFile(QString fileLocation, QString controllerID); // MainConfiguration class void unloadCurrentConfig(int joystickIndex = 0); // MainConfiguration class void unloadCurrentConfig(QString controllerID); // MainConfiguration class void changeStartSetNumber(int startSetNumber, QString controllerID); // MainConfiguration class void changeStartSetNumber(int startSetNumber, int joystickIndex = 0); // MainConfiguration class void convertGUIDtoUniqueID(InputDevice *currentDevice, QString controlEntryLastSelectedGUID); signals: void joystickRefreshRequested(); void readConfig(int index); // MainConfiguration class void mappingUpdated(QString mapping, InputDevice *device); public slots: void checkEachTenMinutesBattery(QMap *joysticks); void fillButtons(); void makeJoystickTabs(); void alterConfigFromSettings(); // MainConfiguration class void fillButtonsID(InputDevice *joystick); void fillButtonsMap(QMap *joysticks); void startJoystickRefresh(); void hideWindow(); void saveAppConfig(); // MainConfiguration class void loadAppConfig(bool forceRefresh = false); // MainConfiguration class void removeJoyTabs(); void quitProgram(); void changeWindowStatus(); void refreshTabHelperThreads(); void controllerMapOpening(); void testMappingUpdateNow(int index, InputDevice *device); void removeJoyTab(SDL_JoystickID deviceID); void addJoyTab(InputDevice *device); void selectControllerJoyTab(QString GUID); void selectControllerJoyTab(int index); void handleInstanceDisconnect(); private slots: void refreshTrayIconMenu(); void trayIconClickAction(QSystemTrayIcon::ActivationReason reason); void mainMenuChange(QMenu *tempMenu); void disableFlashActions(); void enableFlashActions(); void joystickTrayShow(QMenu *tempmenu); void singleTrayProfileMenuShow(); void profileTrayActionTriggered(QAction *action, bool checked); void populateTrayIcon(); void openAboutDialog(); void openJoystickStatusWindow(); void openKeyCheckerDialog(); void openGitHubPage(); void openIssuesPage(); void openWikiPage(); void openCalibration(); void propogateNameDisplayStatus(JoyTabWidget *tabwidget, bool displayNames); void changeLanguage(QString language); // MainConfiguration class void openMainSettingsDialog(); void showStickAssignmentDialog(); void checkHideEmptyOption(); void openGameControllerMappingWindow(bool openAsMain = false); void propogateMappingUpdate(QString mapping, InputDevice *device); void autoprofileLoad(AutoProfileInfo *info); // MainConfiguration class void checkAutoProfileWatcherTimer(); // MainConfiguration class void updateMenuOptions(); private: void showBatteryLevel(SDL_JoystickPowerLevel powerLevSDL, QString batteryLev, QString percent, InputDevice *device); Ui::MainWindow *ui; QMap *m_joysticks; QMap> profileActions; QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; AboutDialog *aboutDialog; CommandLineUtility *m_cmdutility; AntiMicroSettings *m_settings; QTranslator *m_translator; QTranslator *m_appTranslator; AutoProfileWatcher *appWatcher; QAction *hideAction; QAction *restoreAction; QAction *closeAction; QAction *updateJoy; bool signalDisconnect; bool showTrayIcon; bool m_graphical; }; #endif // MAINWINDOW_H AntiMicroX-antimicrox-2888bf6/src/mainwindow.ui000066400000000000000000000356231377703515000215760ustar00rootroot00000000000000 MainWindow Qt::WindowModal 0 0 650 580 650 0 AntiMicroX .. JoyButtonWidget[isflashing="true"], JoyAxisWidget[isflashing="true"], JoyControlStickPushButton[isflashing="true"], JoyControlStickButtonPushButton[isflashing="true"], DPadPushButton[isflashing="true"] { background-color: rgb(0, 0, 255); color: rgb(205, 197, 191); } QPushButton#setPushButton1[setActive="false"], QPushButton#setPushButton2[setActive="false"], QPushButton#setPushButton3[setActive="false"], QPushButton#setPushButton4[setActive="false"], QPushButton#setPushButton5[setActive="false"], QPushButton#setPushButton6[setActive="false"], QPushButton#setPushButton7[setActive="false"], QPushButton#setPushButton8[setActive="false"] { background-color: rgb(190, 190, 190); } QStackedWidget#stackedWidget{ padding-top: 10px; } QPushButton#namesPushButton[isDisplayingNames="true"] { background-color: rgb(192, 255, 192); } 4 0 0 0 0 QFrame::NoFrame QFrame::Plain 1 1 No Joysticks have been found. Please plug in a joystick and then choose the "Update Joysticks" option in the main menu true Qt::AlignCenter true 0 0 0 0 0 0 true 0 0 Qt::LeftToRight QTabWidget::North QTabWidget::Rounded -1 true false false false If events are not seen by a game, please click here to run this application as Administrator. false false false 0 0 650 34 &App &Options He&lp :/icons/actions/application_exit.png:/icons/actions/application_exit.png &Quit Ctrl+Q true :/icons/actions/view_refresh.png:/icons/actions/view_refresh.png &Update Joysticks Ctrl+U :/icons/actions/view_restore.png:/icons/actions/view_restore.png &Hide Ctrl+H :/icons/actions/about_antimicrox.png:/icons/actions/about_antimicrox.png &About Ctrl+A :/icons/actions/about_qt.png:/icons/actions/about_qt.png About &Qt Ctrl+T :/icons/actions/sliders.png:/icons/actions/sliders.png &Properties Ctrl+P :/icons/actions/key_checker.png:/icons/actions/key_checker.png &Key Checker Ctrl+K Home Page Ctrl+H :/icons/actions/github_page.png:/icons/actions/github_page.png &GitHub Page Ctrl+G :/icons/actions/map_controller.png:/icons/actions/map_controller.png &Game Controller Mapping Ctrl+M :/icons/actions/settings.png:/icons/actions/settings.png S&ettings Ctrl+S :/icons/actions/stick_pad_assign.png:/icons/actions/stick_pad_assign.png &Stick/Pad Assign Ctrl+X :/icons/actions/wiki.png:/icons/actions/wiki.png &Wiki Ctrl+W :/icons/actions/issues.png:/icons/actions/issues.png &Issues Ctrl+I :/icons/actions/calibration.png:/icons/actions/calibration.png &Calibration Ctrl+C JoyTabWidgetContainer QTabWidget
joytabwidgetcontainer.h
1
actionQuit triggered() MainWindow quitProgram() -1 -1 199 149 actionUpdate_Joysticks triggered() MainWindow startJoystickRefresh() -1 -1 349 262 actionHide triggered() MainWindow hideWindow() -1 -1 349 262 actionAbout triggered() MainWindow openAboutDialog() -1 -1 349 262 actionStick_Pad_Assign triggered() MainWindow showStickAssignmentDialog() -1 -1 324 289 startJoystickRefresh() hideWindow() openAboutDialog() quitProgram() showStickAssignmentDialog()
AntiMicroX-antimicrox-2888bf6/src/messagehandler.cpp000066400000000000000000000056721377703515000225520ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "messagehandler.h" #include "logger.h" #include #include #include namespace MessageHandler { void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QByteArray localMsg = msg.toLocal8Bit(); if (Logger::instance != nullptr) { switch (type) { case QtDebugMsg: if (Logger::instance->getCurrentLogLevel() == Logger::LOG_DEBUG || Logger::instance->getCurrentLogLevel() == Logger::LOG_MAX) fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; #if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) case QtInfoMsg: if (Logger::instance->getCurrentLogLevel() == Logger::LOG_INFO || Logger::instance->getCurrentLogLevel() == Logger::LOG_MAX) fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; #endif case QtWarningMsg: if (Logger::instance->getCurrentLogLevel() == Logger::LOG_WARNING || Logger::instance->getCurrentLogLevel() == Logger::LOG_MAX) fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtCriticalMsg: if (Logger::instance->getCurrentLogLevel() == Logger::LOG_ERROR || Logger::instance->getCurrentLogLevel() == Logger::LOG_MAX) fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtFatalMsg: if (Logger::instance->getCurrentLogLevel() == Logger::LOG_ERROR || Logger::instance->getCurrentLogLevel() == Logger::LOG_MAX) fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); abort(); default: break; } } } } // namespace MessageHandler AntiMicroX-antimicrox-2888bf6/src/messagehandler.h000066400000000000000000000020271377703515000222060ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MESSAGEHANDLER_H #define MESSAGEHANDLER_H #include #include namespace MessageHandler // prevents polluting the global namespace { extern void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); } #endif // MESSAGEHANDLER_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/000077500000000000000000000000001377703515000213625ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/mousedialog/mouseaxissettingsdialog.cpp000066400000000000000000000400141377703515000270430ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mouseaxissettingsdialog.h" #include "common.h" #include "inputdevice.h" #include "joyaxis.h" #include "messagehandler.h" #include "setjoystick.h" #include "springmoderegionpreview.h" #include "springmousemoveinfo.h" #include #include #include MouseAxisSettingsDialog::MouseAxisSettingsDialog(JoyAxis *axis, QWidget *parent) : MouseSettingsDialog(parent) , helper(axis) { qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->axis = axis; getHelperLocal().moveToThread(axis->thread()); calculateMouseSpeedPreset(); selectCurrentMouseModePreset(); calculateSpringPreset(); if (axis->getButtonsPresetSensitivity() > 0.0) { ui->sensitivityDoubleSpinBox->setValue(axis->getButtonsPresetSensitivity()); } updateAccelerationCurvePresetComboBox(); updateWindowTitleAxisName(); if (ui->mouseModeComboBox->currentIndex() == 2) { springPreviewWidget = new SpringModeRegionPreview(ui->springWidthSpinBox->value(), ui->springHeightSpinBox->value()); } else { springPreviewWidget = new SpringModeRegionPreview(0, 0); } calculateWheelSpeedPreset(); if (axis->isRelativeSpring()) { ui->relativeSpringCheckBox->setChecked(true); } double easingDuration = axis->getButtonsEasingDuration(); ui->easingDoubleSpinBox->setValue(easingDuration); calculateExtraAccelrationStatus(); calculateExtraAccelerationMultiplier(); calculateStartAccelerationMultiplier(); calculateMinAccelerationThreshold(); calculateMaxAccelerationThreshold(); calculateAccelExtraDuration(); calculateReleaseSpringRadius(); calculateExtraAccelerationCurve(); changeSpringSectionStatus(ui->mouseModeComboBox->currentIndex()); changeSettingsWidgetStatus(ui->accelerationComboBox->currentIndex()); connect(this, &MouseAxisSettingsDialog::finished, springPreviewWidget, &SpringModeRegionPreview::deleteLater); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseAxisSettingsDialog::changeMouseMode); connect(ui->accelerationComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseAxisSettingsDialog::changeMouseCurve); connect(ui->horizontalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseAxisSettingsDialog::updateConfigHorizontalSpeed); connect(ui->verticalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseAxisSettingsDialog::updateConfigVerticalSpeed); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseAxisSettingsDialog::updateSpringWidth); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringWidth); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseAxisSettingsDialog::updateSpringHeight); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringHeight); connect(ui->relativeSpringCheckBox, &QCheckBox::clicked, this, &MouseAxisSettingsDialog::updateSpringRelativeStatus); connect(ui->sensitivityDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &MouseAxisSettingsDialog::updateSensitivity); connect(ui->wheelHoriSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseAxisSettingsDialog::updateWheelSpeedHorizontalSpeed); connect(ui->wheelVertSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseAxisSettingsDialog::updateWheelSpeedVerticalSpeed); connect(ui->easingDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), axis, &JoyAxis::setButtonsEasingDuration); connect(ui->extraAccelerationGroupBox, &QGroupBox::clicked, &helper, &MouseAxisSettingsDialogHelper::updateExtraAccelerationStatus); connect(ui->extraAccelDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseAxisSettingsDialogHelper::updateExtraAccelerationMultiplier); connect(ui->minMultiDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseAxisSettingsDialogHelper::updateStartMultiPercentage); connect(ui->minThresholdDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseAxisSettingsDialogHelper::updateMinAccelThreshold); connect(ui->maxThresholdDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseAxisSettingsDialogHelper::updateMaxAccelThreshold); connect(ui->accelExtraDurationDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseAxisSettingsDialogHelper::updateAccelExtraDuration); connect(ui->releaseSpringRadiusspinBox, static_cast(&QSpinBox::valueChanged), &helper, &MouseAxisSettingsDialogHelper::updateReleaseSpringRadius); connect(ui->extraAccelCurveComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseAxisSettingsDialog::updateExtraAccelerationCurve); } void MouseAxisSettingsDialog::changeMouseMode(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 1) { axis->setButtonsMouseMode(JoyButton::MouseCursor); if (springPreviewWidget->isVisible()) { springPreviewWidget->hide(); } } else if (index == 2) { axis->setButtonsMouseMode(JoyButton::MouseSpring); if (!springPreviewWidget->isVisible()) { springPreviewWidget->setSpringWidth(ui->springWidthSpinBox->value()); springPreviewWidget->setSpringHeight(ui->springHeightSpinBox->value()); } axis->getPAxisButton()->setExtraAccelerationStatus(false); axis->getNAxisButton()->setExtraAccelerationStatus(false); } } void MouseAxisSettingsDialog::changeMouseCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = MouseSettingsDialog::getMouseCurveForIndex(index); axis->setButtonsMouseCurve(temp); } void MouseAxisSettingsDialog::updateConfigHorizontalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setMouseSpeedX(value); axis->getNAxisButton()->setMouseSpeedX(value); } void MouseAxisSettingsDialog::updateConfigVerticalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setMouseSpeedY(value); axis->getNAxisButton()->setMouseSpeedY(value); } void MouseAxisSettingsDialog::updateSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->setButtonsSpringWidth(value); } void MouseAxisSettingsDialog::updateSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->setButtonsSpringHeight(value); } void MouseAxisSettingsDialog::selectCurrentMouseModePreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool presetDefined = axis->hasSameButtonsMouseMode(); if (presetDefined) { JoyButton::JoyMouseMovementMode mode = axis->getButtonsPresetMouseMode(); if (mode == JoyButton::MouseCursor) { ui->mouseModeComboBox->setCurrentIndex(1); } else if (mode == JoyButton::MouseSpring) { ui->mouseModeComboBox->setCurrentIndex(2); } } else { ui->mouseModeComboBox->setCurrentIndex(0); } } void MouseAxisSettingsDialog::calculateSpringPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempWidth = axis->getButtonsPresetSpringWidth(); int tempHeight = axis->getButtonsPresetSpringHeight(); if (tempWidth > 0) { ui->springWidthSpinBox->setValue(tempWidth); } if (tempHeight > 0) { ui->springHeightSpinBox->setValue(tempHeight); } } void MouseAxisSettingsDialog::calculateMouseSpeedPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempMouseSpeedX = 0; tempMouseSpeedX = qMax(axis->getPAxisButton()->getMouseSpeedX(), axis->getNAxisButton()->getMouseSpeedX()); int tempMouseSpeedY = 0; tempMouseSpeedY = qMax(axis->getPAxisButton()->getMouseSpeedY(), axis->getNAxisButton()->getMouseSpeedY()); ui->horizontalSpinBox->setValue(tempMouseSpeedX); ui->verticalSpinBox->setValue(tempMouseSpeedY); } void MouseAxisSettingsDialog::updateSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->setButtonsSensitivity(value); } void MouseAxisSettingsDialog::updateAccelerationCurvePresetComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = axis->getButtonsPresetMouseCurve(); MouseSettingsDialog::updateAccelerationCurvePresetComboBox(temp); } void MouseAxisSettingsDialog::calculateWheelSpeedPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *paxisbutton = axis->getPAxisButton(); JoyAxisButton *naxisbutton = axis->getNAxisButton(); int tempWheelSpeedX = qMax(paxisbutton->getWheelSpeedX(), naxisbutton->getWheelSpeedX()); int tempWheelSpeedY = qMax(paxisbutton->getWheelSpeedY(), naxisbutton->getWheelSpeedY()); ui->wheelHoriSpeedSpinBox->setValue(tempWheelSpeedX); ui->wheelVertSpeedSpinBox->setValue(tempWheelSpeedY); } void MouseAxisSettingsDialog::updateWheelSpeedHorizontalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->setButtonsWheelSpeedX(value); } void MouseAxisSettingsDialog::updateWheelSpeedVerticalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->setButtonsWheelSpeedY(value); } void MouseAxisSettingsDialog::updateSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->setButtonsSpringRelativeStatus(value); } void MouseAxisSettingsDialog::updateWindowTitleAxisName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); temp.append(tr("Mouse Settings - ")); if (!axis->getAxisName().isEmpty()) { temp.append(axis->getPartialName(false, true)); } else { temp.append(axis->getPartialName()); } if (axis->getParentSet()->getIndex() != 0) { int setIndex = axis->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = axis->getParentSet()->getName(); if (!setName.isEmpty()) { temp.append(": ").append(setName); } temp.append("]"); } setWindowTitle(temp); } void MouseAxisSettingsDialog::calculateExtraAccelrationStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((axis->getPAxisButton()->isExtraAccelerationEnabled()) && (axis->getNAxisButton()->isExtraAccelerationEnabled())) { ui->extraAccelerationGroupBox->setChecked(true); } else { ui->extraAccelerationGroupBox->setChecked(false); } } void MouseAxisSettingsDialog::calculateExtraAccelerationMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (qFuzzyCompare(axis->getPAxisButton()->getExtraAccelerationMultiplier(), axis->getNAxisButton()->getExtraAccelerationMultiplier())) { double temp = axis->getPAxisButton()->getExtraAccelerationMultiplier(); ui->extraAccelDoubleSpinBox->setValue(temp); } } void MouseAxisSettingsDialog::calculateStartAccelerationMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (qFuzzyCompare(axis->getPAxisButton()->getStartAccelMultiplier(), axis->getNAxisButton()->getStartAccelMultiplier())) { double temp = axis->getPAxisButton()->getStartAccelMultiplier(); ui->minMultiDoubleSpinBox->setValue(temp); } } void MouseAxisSettingsDialog::calculateMinAccelerationThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (qFuzzyCompare(axis->getPAxisButton()->getMinAccelThreshold(), axis->getNAxisButton()->getMinAccelThreshold())) { double temp = axis->getPAxisButton()->getMinAccelThreshold(); ui->minThresholdDoubleSpinBox->setValue(temp); } } void MouseAxisSettingsDialog::calculateMaxAccelerationThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (qFuzzyCompare(axis->getPAxisButton()->getMaxAccelThreshold(), axis->getNAxisButton()->getMaxAccelThreshold())) { double temp = axis->getPAxisButton()->getMaxAccelThreshold(); ui->maxThresholdDoubleSpinBox->setValue(temp); } } void MouseAxisSettingsDialog::calculateAccelExtraDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (qFuzzyCompare(axis->getPAxisButton()->getAccelExtraDuration(), axis->getNAxisButton()->getAccelExtraDuration())) { double temp = axis->getPAxisButton()->getAccelExtraDuration(); ui->accelExtraDurationDoubleSpinBox->setValue(temp); } } void MouseAxisSettingsDialog::calculateReleaseSpringRadius() { qInstallMessageHandler(MessageHandler::myMessageOutput); int result = 0; if ((axis->getPAxisButton()->getSpringDeadCircleMultiplier()) == (axis->getNAxisButton()->getSpringDeadCircleMultiplier())) { result = axis->getPAxisButton()->getSpringDeadCircleMultiplier(); } ui->releaseSpringRadiusspinBox->setValue(result); } void MouseAxisSettingsDialog::updateExtraAccelerationCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve temp = getExtraAccelCurveForIndex(index); if (index > 0) { PadderCommon::inputDaemonMutex.lock(); axis->getPAxisButton()->setExtraAccelerationCurve(temp); axis->getNAxisButton()->setExtraAccelerationCurve(temp); PadderCommon::inputDaemonMutex.unlock(); } } void MouseAxisSettingsDialog::calculateExtraAccelerationCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (axis->getPAxisButton()->getExtraAccelerationCurve() == axis->getNAxisButton()->getExtraAccelerationCurve()) { JoyButton::JoyExtraAccelerationCurve temp = axis->getPAxisButton()->getExtraAccelerationCurve(); updateExtraAccelerationCurvePresetComboBox(temp); } } JoyAxis *MouseAxisSettingsDialog::getAxis() const { return axis; } SpringModeRegionPreview *MouseAxisSettingsDialog::getSpringPreviewWidget() const { return springPreviewWidget; } MouseAxisSettingsDialogHelper const &MouseAxisSettingsDialog::getHelper() { return helper; } MouseAxisSettingsDialogHelper &MouseAxisSettingsDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/mouseaxissettingsdialog.h000066400000000000000000000052531377703515000265160ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSEAXISSETTINGSDIALOG_H #define MOUSEAXISSETTINGSDIALOG_H #include "ui_mousesettingsdialog.h" #include "mousesettingsdialog.h" #include "uihelpers/mouseaxissettingsdialoghelper.h" class JoyAxis; class SpringModeRegionPreview; class MouseAxisSettingsDialog : public MouseSettingsDialog { Q_OBJECT public: explicit MouseAxisSettingsDialog(JoyAxis *axis, QWidget *parent = nullptr); JoyAxis *getAxis() const; SpringModeRegionPreview *getSpringPreviewWidget() const; MouseAxisSettingsDialogHelper const &getHelper(); protected: void selectCurrentMouseModePreset(); void calculateSpringPreset(); void calculateMouseSpeedPreset(); void calculateWheelSpeedPreset(); void updateWindowTitleAxisName(); void calculateExtraAccelrationStatus(); void calculateExtraAccelerationMultiplier(); void calculateStartAccelerationMultiplier(); void calculateMinAccelerationThreshold(); void calculateMaxAccelerationThreshold(); void calculateAccelExtraDuration(); void calculateReleaseSpringRadius(); void calculateExtraAccelerationCurve(); public slots: void changeMouseMode(int index); void changeMouseCurve(int index); void updateConfigHorizontalSpeed(int value); void updateConfigVerticalSpeed(int value); void updateSpringWidth(int value); void updateSpringHeight(int value); void updateSensitivity(double value); void updateAccelerationCurvePresetComboBox(); void updateWheelSpeedHorizontalSpeed(int value); void updateWheelSpeedVerticalSpeed(int value); void updateSpringRelativeStatus(bool value); private slots: void updateExtraAccelerationCurve(int index); private: MouseAxisSettingsDialogHelper &getHelperLocal(); JoyAxis *axis; SpringModeRegionPreview *springPreviewWidget; MouseAxisSettingsDialogHelper helper; }; #endif // MOUSEAXISSETTINGSDIALOG_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/mousebuttonsettingsdialog.cpp000066400000000000000000000302551377703515000274200ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousebuttonsettingsdialog.h" #include "common.h" #include "inputdevice.h" #include "joybutton.h" #include "messagehandler.h" #include "setjoystick.h" #include "springmoderegionpreview.h" #include #include #include #include #include MouseButtonSettingsDialog::MouseButtonSettingsDialog(JoyButton *button, QWidget *parent) : MouseSettingsDialog(parent) , helper(button) { qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); resize(size().width(), 450); this->button = button; getHelperLocal().moveToThread(button->thread()); calculateMouseSpeedPreset(); selectCurrentMouseModePreset(); calculateSpringPreset(); if (button->getSensitivity() > 0.0) { ui->sensitivityDoubleSpinBox->setValue(button->getSensitivity()); } updateAccelerationCurvePresetComboBox(); updateWindowTitleButtonName(); if (ui->mouseModeComboBox->currentIndex() == 2) { springPreviewWidget = new SpringModeRegionPreview(ui->springWidthSpinBox->value(), ui->springHeightSpinBox->value()); } else { springPreviewWidget = new SpringModeRegionPreview(0, 0); } ui->wheelHoriSpeedSpinBox->setValue(button->getWheelSpeedX()); ui->wheelVertSpeedSpinBox->setValue(button->getWheelSpeedY()); if (button->isRelativeSpring()) { ui->relativeSpringCheckBox->setChecked(true); } double easingDuration = button->getEasingDuration(); ui->easingDoubleSpinBox->setValue(easingDuration); if (button->isPartRealAxis()) { ui->extraAccelerationGroupBox->setChecked(button->isExtraAccelerationEnabled()); ui->extraAccelDoubleSpinBox->setValue(button->getExtraAccelerationMultiplier()); ui->minMultiDoubleSpinBox->setValue(button->getStartAccelMultiplier()); ui->minThresholdDoubleSpinBox->setValue(button->getMinAccelThreshold()); ui->maxThresholdDoubleSpinBox->setValue(button->getMaxAccelThreshold()); ui->accelExtraDurationDoubleSpinBox->setValue(button->getAccelExtraDuration()); } else { ui->extraAccelerationGroupBox->setVisible(false); } ui->releaseSpringRadiusspinBox->setValue(button->getSpringDeadCircleMultiplier()); calculateExtraAccelerationCurve(); changeSpringSectionStatus(ui->mouseModeComboBox->currentIndex()); changeSettingsWidgetStatus(ui->accelerationComboBox->currentIndex()); connect(this, &MouseButtonSettingsDialog::finished, springPreviewWidget, &SpringModeRegionPreview::deleteLater); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseButtonSettingsDialog::changeMouseMode); connect(ui->accelerationComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseButtonSettingsDialog::changeMouseCurve); connect(ui->horizontalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseButtonSettingsDialog::updateConfigHorizontalSpeed); connect(ui->verticalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseButtonSettingsDialog::updateConfigVerticalSpeed); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseButtonSettingsDialog::updateSpringWidth); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringWidth); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseButtonSettingsDialog::updateSpringHeight); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringHeight); connect(ui->relativeSpringCheckBox, &QCheckBox::clicked, &helper, &MouseButtonSettingsDialogHelper::updateSpringRelativeStatus); connect(ui->sensitivityDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &MouseButtonSettingsDialog::updateSensitivity); QChar x = 'X'; QChar y = 'Y'; connect(ui->wheelHoriSpeedSpinBox, static_cast(&QSpinBox::valueChanged), button, [button, x](int value) { button->setWheelSpeed(value, x); }); connect(ui->wheelVertSpeedSpinBox, static_cast(&QSpinBox::valueChanged), button, [button, y](int value) { button->setWheelSpeed(value, y); }); connect(ui->easingDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), button, &JoyButton::setEasingDuration); connect(ui->extraAccelerationGroupBox, &QGroupBox::clicked, &helper, &MouseButtonSettingsDialogHelper::updateExtraAccelerationStatus); connect(ui->extraAccelDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseButtonSettingsDialogHelper::updateExtraAccelerationMultiplier); connect(ui->minMultiDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseButtonSettingsDialogHelper::updateStartMultiPercentage); connect(ui->minThresholdDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseButtonSettingsDialogHelper::updateMinAccelThreshold); connect(ui->maxThresholdDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseButtonSettingsDialogHelper::updateMaxAccelThreshold); connect(ui->accelExtraDurationDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseButtonSettingsDialogHelper::updateAccelExtraDuration); connect(ui->releaseSpringRadiusspinBox, static_cast(&QSpinBox::valueChanged), &helper, &MouseButtonSettingsDialogHelper::updateReleaseSpringRadius); connect(ui->extraAccelCurveComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseButtonSettingsDialog::updateExtraAccelerationCurve); } void MouseButtonSettingsDialog::changeMouseMode(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 1) { button->setMouseMode(JoyButton::MouseCursor); if (springPreviewWidget->isVisible()) { springPreviewWidget->hide(); } } else if (index == 2) { button->setMouseMode(JoyButton::MouseSpring); if (!springPreviewWidget->isVisible()) { springPreviewWidget->setSpringWidth(ui->springWidthSpinBox->value()); springPreviewWidget->setSpringHeight(ui->springHeightSpinBox->value()); } if (button->isPartRealAxis()) { button->setExtraAccelerationStatus(false); } } } void MouseButtonSettingsDialog::changeMouseCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = MouseSettingsDialog::getMouseCurveForIndex(index); button->setMouseCurve(temp); } void MouseButtonSettingsDialog::updateConfigHorizontalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QMetaObject::invokeMethod(button, "setMouseSpeedX", Q_ARG(int, value)); } void MouseButtonSettingsDialog::updateConfigVerticalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QMetaObject::invokeMethod(button, "setMouseSpeedY", Q_ARG(int, value)); } void MouseButtonSettingsDialog::updateSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QMetaObject::invokeMethod(button, "setSpringWidth", Q_ARG(int, value)); } void MouseButtonSettingsDialog::updateSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QMetaObject::invokeMethod(button, "setSpringHeight", Q_ARG(int, value)); } void MouseButtonSettingsDialog::selectCurrentMouseModePreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseMovementMode mode = button->getMouseMode(); if (mode == JoyButton::MouseCursor) { ui->mouseModeComboBox->setCurrentIndex(1); } else if (mode == JoyButton::MouseSpring) { ui->mouseModeComboBox->setCurrentIndex(2); } } void MouseButtonSettingsDialog::calculateSpringPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempWidth = button->getSpringWidth(); int tempHeight = button->getSpringHeight(); if (tempWidth > 0) { ui->springWidthSpinBox->setValue(tempWidth); } if (tempHeight > 0) { ui->springHeightSpinBox->setValue(tempHeight); } } void MouseButtonSettingsDialog::calculateMouseSpeedPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempMouseSpeedX = button->getMouseSpeedX(); int tempMouseSpeedY = button->getMouseSpeedY(); ui->horizontalSpinBox->setValue(tempMouseSpeedX); ui->verticalSpinBox->setValue(tempMouseSpeedY); } void MouseButtonSettingsDialog::updateSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setSensitivity(value); } void MouseButtonSettingsDialog::updateAccelerationCurvePresetComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = button->getMouseCurve(); MouseSettingsDialog::updateAccelerationCurvePresetComboBox(temp); } void MouseButtonSettingsDialog::updateWindowTitleButtonName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); temp.append(tr("Mouse Settings - ")).append(button->getPartialName(false, true)); if (button->getParentSet()->getIndex() != 0) { int setIndex = button->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = button->getParentSet()->getName(); if (!setName.isEmpty()) { temp.append(": ").append(setName); } temp.append("]"); } setWindowTitle(temp); } void MouseButtonSettingsDialog::calculateExtraAccelerationCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve temp = button->getExtraAccelerationCurve(); updateExtraAccelerationCurvePresetComboBox(temp); } void MouseButtonSettingsDialog::updateExtraAccelerationCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve temp = getExtraAccelCurveForIndex(index); if (index > 0) { PadderCommon::inputDaemonMutex.lock(); button->setExtraAccelerationCurve(temp); button->setExtraAccelerationCurve(temp); PadderCommon::inputDaemonMutex.unlock(); } } JoyButton *MouseButtonSettingsDialog::getButton() const { return button; } SpringModeRegionPreview *MouseButtonSettingsDialog::getSpringPreviewWidget() const { return springPreviewWidget; } MouseButtonSettingsDialogHelper const &MouseButtonSettingsDialog::getHelper() { return helper; } MouseButtonSettingsDialogHelper &MouseButtonSettingsDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/mousebuttonsettingsdialog.h000066400000000000000000000043221377703515000270610ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSEBUTTONSETTINGSDIALOG_H #define MOUSEBUTTONSETTINGSDIALOG_H #include "ui_mousesettingsdialog.h" #include "mousesettingsdialog.h" #include "uihelpers/mousebuttonsettingsdialoghelper.h" class JoyButton; class SpringModeRegionPreview; class MouseButtonSettingsDialog : public MouseSettingsDialog { Q_OBJECT public: explicit MouseButtonSettingsDialog(JoyButton *button, QWidget *parent = nullptr); JoyButton *getButton() const; SpringModeRegionPreview *getSpringPreviewWidget() const; MouseButtonSettingsDialogHelper const &getHelper(); protected: void selectCurrentMouseModePreset(); void calculateSpringPreset(); void calculateMouseSpeedPreset(); void updateWindowTitleButtonName(); void calculateExtraAccelerationCurve(); public slots: void changeMouseMode(int index); void changeMouseCurve(int index); void updateConfigHorizontalSpeed(int value); void updateConfigVerticalSpeed(int value); void updateSpringWidth(int value); void updateSpringHeight(int value); void updateSensitivity(double value); void updateAccelerationCurvePresetComboBox(); private slots: void updateExtraAccelerationCurve(int index); private: MouseButtonSettingsDialogHelper &getHelperLocal(); JoyButton *button; SpringModeRegionPreview *springPreviewWidget; MouseButtonSettingsDialogHelper helper; }; #endif // MOUSEBUTTONSETTINGSDIALOG_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/mousecontrolsticksettingsdialog.cpp000066400000000000000000000372571377703515000306340ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousecontrolsticksettingsdialog.h" #include "common.h" #include "inputdevice.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joycontrolstick.h" #include "messagehandler.h" #include "setjoystick.h" #include "springmoderegionpreview.h" #include #include #include #include MouseControlStickSettingsDialog::MouseControlStickSettingsDialog(JoyControlStick *stick, QWidget *parent) : MouseSettingsDialog(parent) , helper(stick) { qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->stick = stick; getHelperLocal().moveToThread(stick->thread()); calculateMouseSpeedPreset(); selectCurrentMouseModePreset(); calculateSpringPreset(); if (stick->getButtonsPresetSensitivity() > 0.0) { ui->sensitivityDoubleSpinBox->setValue(stick->getButtonsPresetSensitivity()); } updateAccelerationCurvePresetComboBox(); updateWindowTitleStickName(); if (ui->mouseModeComboBox->currentIndex() == 2) { springPreviewWidget = new SpringModeRegionPreview(ui->springWidthSpinBox->value(), ui->springHeightSpinBox->value()); } else { springPreviewWidget = new SpringModeRegionPreview(0, 0); } calculateWheelSpeedPreset(); if (stick->isRelativeSpring()) { ui->relativeSpringCheckBox->setChecked(true); } double easingDuration = stick->getButtonsEasingDuration(); ui->easingDoubleSpinBox->setValue(easingDuration); calculateExtraAccelrationStatus(); calculateExtraAccelerationMultiplier(); calculateStartAccelerationMultiplier(); calculateMinAccelerationThreshold(); calculateMaxAccelerationThreshold(); calculateAccelExtraDuration(); calculateReleaseSpringRadius(); calculateExtraAccelerationCurve(); changeSpringSectionStatus(ui->mouseModeComboBox->currentIndex()); changeSettingsWidgetStatus(ui->accelerationComboBox->currentIndex()); connect(this, &MouseControlStickSettingsDialog::finished, springPreviewWidget, &SpringModeRegionPreview::deleteLater); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseControlStickSettingsDialog::changeMouseMode); connect(ui->accelerationComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseControlStickSettingsDialog::changeMouseCurve); connect(ui->horizontalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseControlStickSettingsDialog::updateConfigHorizontalSpeed); connect(ui->verticalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseControlStickSettingsDialog::updateConfigVerticalSpeed); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseControlStickSettingsDialog::updateSpringWidth); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringWidth); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseControlStickSettingsDialog::updateSpringHeight); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringHeight); connect(ui->relativeSpringCheckBox, &QCheckBox::clicked, this, &MouseControlStickSettingsDialog::updateSpringRelativeStatus); connect(ui->sensitivityDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &MouseControlStickSettingsDialog::updateSensitivity); connect(ui->wheelHoriSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseControlStickSettingsDialog::updateWheelSpeedHorizontalSpeed); connect(ui->wheelVertSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseControlStickSettingsDialog::updateWheelSpeedVerticalSpeed); connect(ui->easingDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), stick, &JoyControlStick::setButtonsEasingDuration); connect(ui->extraAccelerationGroupBox, &QGroupBox::clicked, &helper, &MouseControlStickSettingsDialogHelper::updateExtraAccelerationStatus); connect(ui->extraAccelDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseControlStickSettingsDialogHelper::updateExtraAccelerationMultiplier); connect(ui->minMultiDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseControlStickSettingsDialogHelper::updateStartMultiPercentage); connect(ui->minThresholdDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseControlStickSettingsDialogHelper::updateMinAccelThreshold); connect(ui->maxThresholdDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseControlStickSettingsDialogHelper::updateMaxAccelThreshold); connect(ui->accelExtraDurationDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), &helper, &MouseControlStickSettingsDialogHelper::updateAccelExtraDuration); connect(ui->releaseSpringRadiusspinBox, static_cast(&QSpinBox::valueChanged), &helper, &MouseControlStickSettingsDialogHelper::updateReleaseSpringRadius); connect(ui->extraAccelCurveComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseControlStickSettingsDialog::updateExtraAccelerationCurve); } void MouseControlStickSettingsDialog::changeMouseMode(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 1) { stick->setButtonsMouseMode(JoyButton::MouseCursor); if (springPreviewWidget->isVisible()) { springPreviewWidget->hide(); } } else if (index == 2) { stick->setButtonsMouseMode(JoyButton::MouseSpring); if (!springPreviewWidget->isVisible()) { springPreviewWidget->setSpringWidth(ui->springWidthSpinBox->value()); springPreviewWidget->setSpringHeight(ui->springHeightSpinBox->value()); } stick->setButtonsExtraAccelerationStatus(false); } } void MouseControlStickSettingsDialog::changeMouseCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = MouseSettingsDialog::getMouseCurveForIndex(index); stick->setButtonsMouseCurve(temp); } void MouseControlStickSettingsDialog::updateConfigHorizontalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*stick->getButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setMouseSpeedX(value); } } void MouseControlStickSettingsDialog::updateConfigVerticalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*stick->getButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); button->setMouseSpeedY(value); } } void MouseControlStickSettingsDialog::updateSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsSpringWidth(value); } void MouseControlStickSettingsDialog::updateSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsSpringHeight(value); } void MouseControlStickSettingsDialog::selectCurrentMouseModePreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool presetDefined = stick->hasSameButtonsMouseMode(); if (presetDefined) { JoyButton::JoyMouseMovementMode mode = stick->getButtonsPresetMouseMode(); if (mode == JoyButton::MouseCursor) { ui->mouseModeComboBox->setCurrentIndex(1); } else if (mode == JoyButton::MouseSpring) { ui->mouseModeComboBox->setCurrentIndex(2); } } else { ui->mouseModeComboBox->setCurrentIndex(0); } } void MouseControlStickSettingsDialog::calculateSpringPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempWidth = stick->getButtonsPresetSpringWidth(); int tempHeight = stick->getButtonsPresetSpringHeight(); if (tempWidth > 0) { ui->springWidthSpinBox->setValue(tempWidth); } if (tempHeight > 0) { ui->springHeightSpinBox->setValue(tempHeight); } } void MouseControlStickSettingsDialog::calculateMouseSpeedPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*stick->getButtons()); int tempMouseSpeedX = 0; while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); tempMouseSpeedX = qMax(tempMouseSpeedX, button->getMouseSpeedX()); } iter.toFront(); int tempMouseSpeedY = 0; while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); tempMouseSpeedY = qMax(tempMouseSpeedY, button->getMouseSpeedY()); } ui->horizontalSpinBox->setValue(tempMouseSpeedX); ui->verticalSpinBox->setValue(tempMouseSpeedY); } void MouseControlStickSettingsDialog::updateSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsSensitivity(value); } void MouseControlStickSettingsDialog::updateAccelerationCurvePresetComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = stick->getButtonsPresetMouseCurve(); MouseSettingsDialog::updateAccelerationCurvePresetComboBox(temp); } void MouseControlStickSettingsDialog::calculateWheelSpeedPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*stick->getButtons()); int tempWheelSpeedX = 0; int tempWheelSpeedY = 0; while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); tempWheelSpeedX = qMax(tempWheelSpeedX, button->getWheelSpeedX()); tempWheelSpeedY = qMax(tempWheelSpeedY, button->getWheelSpeedY()); } ui->wheelHoriSpeedSpinBox->setValue(tempWheelSpeedX); ui->wheelVertSpeedSpinBox->setValue(tempWheelSpeedY); } void MouseControlStickSettingsDialog::updateWheelSpeedHorizontalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsWheelSpeedX(value); } void MouseControlStickSettingsDialog::updateWheelSpeedVerticalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsWheelSpeedY(value); } void MouseControlStickSettingsDialog::updateSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsSpringRelativeStatus(value); } void MouseControlStickSettingsDialog::updateWindowTitleStickName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(tr("Mouse Settings")).append(" - "); if (!stick->getStickName().isEmpty()) { temp.append(stick->getPartialName(false, true)); } else { temp.append(stick->getPartialName()); } if (stick->getParentSet()->getIndex() != 0) { int setIndex = stick->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = stick->getParentSet()->getName(); if (!setName.isEmpty()) { temp.append(": ").append(setName); } temp.append("]"); } setWindowTitle(temp); } void MouseControlStickSettingsDialog::calculateExtraAccelrationStatus() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (stick->getButtonsExtraAccelerationStatus()) { ui->extraAccelerationGroupBox->setChecked(true); } } void MouseControlStickSettingsDialog::calculateExtraAccelerationMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->extraAccelDoubleSpinBox->setValue(stick->getButtonsExtraAccelerationMultiplier()); } void MouseControlStickSettingsDialog::calculateStartAccelerationMultiplier() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->minMultiDoubleSpinBox->setValue(stick->getButtonsStartAccelerationMultiplier()); } void MouseControlStickSettingsDialog::calculateMinAccelerationThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->minThresholdDoubleSpinBox->setValue(stick->getButtonsMinAccelerationThreshold()); } void MouseControlStickSettingsDialog::calculateMaxAccelerationThreshold() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->maxThresholdDoubleSpinBox->setValue(stick->getButtonsMaxAccelerationThreshold()); } void MouseControlStickSettingsDialog::calculateAccelExtraDuration() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->accelExtraDurationDoubleSpinBox->setValue(stick->getButtonsAccelerationEasingDuration()); } void MouseControlStickSettingsDialog::calculateReleaseSpringRadius() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->releaseSpringRadiusspinBox->setValue(stick->getButtonsSpringDeadCircleMultiplier()); } void MouseControlStickSettingsDialog::calculateExtraAccelerationCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve curve = stick->getButtonsExtraAccelerationCurve(); updateExtraAccelerationCurvePresetComboBox(curve); } void MouseControlStickSettingsDialog::updateExtraAccelerationCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve temp = getExtraAccelCurveForIndex(index); if (index > 0) { PadderCommon::inputDaemonMutex.lock(); stick->setButtonsExtraAccelCurve(temp); PadderCommon::inputDaemonMutex.unlock(); } } JoyControlStick *MouseControlStickSettingsDialog::getStick() const { return stick; } SpringModeRegionPreview *MouseControlStickSettingsDialog::getSpringPreviewWidget() const { return springPreviewWidget; } MouseControlStickSettingsDialogHelper const &MouseControlStickSettingsDialog::getHelper() { return helper; } MouseControlStickSettingsDialogHelper &MouseControlStickSettingsDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/mousecontrolsticksettingsdialog.h000066400000000000000000000054231377703515000302670ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSECONTROLSTICKSETTINGSDIALOG_H #define MOUSECONTROLSTICKSETTINGSDIALOG_H #include "ui_mousesettingsdialog.h" #include "mousesettingsdialog.h" #include "uihelpers/mousecontrolsticksettingsdialoghelper.h" class JoyControlStick; class SpringModeRegionPreview; class MouseControlStickSettingsDialog : public MouseSettingsDialog { Q_OBJECT public: explicit MouseControlStickSettingsDialog(JoyControlStick *stick, QWidget *parent = 0); JoyControlStick *getStick() const; SpringModeRegionPreview *getSpringPreviewWidget() const; MouseControlStickSettingsDialogHelper const &getHelper(); protected: void selectCurrentMouseModePreset(); void calculateSpringPreset(); void calculateMouseSpeedPreset(); void calculateWheelSpeedPreset(); void updateWindowTitleStickName(); void calculateExtraAccelrationStatus(); void calculateExtraAccelerationMultiplier(); void calculateStartAccelerationMultiplier(); void calculateMinAccelerationThreshold(); void calculateMaxAccelerationThreshold(); void calculateAccelExtraDuration(); void calculateReleaseSpringRadius(); void calculateExtraAccelerationCurve(); public slots: void changeMouseMode(int index); void changeMouseCurve(int index); void updateConfigHorizontalSpeed(int value); void updateConfigVerticalSpeed(int value); void updateSpringWidth(int value); void updateSpringHeight(int value); void updateSensitivity(double value); void updateAccelerationCurvePresetComboBox(); void updateWheelSpeedHorizontalSpeed(int value); void updateWheelSpeedVerticalSpeed(int value); void updateSpringRelativeStatus(bool value); private slots: void updateExtraAccelerationCurve(int index); private: MouseControlStickSettingsDialogHelper &getHelperLocal(); JoyControlStick *stick; SpringModeRegionPreview *springPreviewWidget; MouseControlStickSettingsDialogHelper helper; }; #endif // MOUSECONTROLSTICKSETTINGSDIALOG_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/mousedpadsettingsdialog.cpp000066400000000000000000000316761377703515000270250ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousedpadsettingsdialog.h" #include "joydpad.h" #include "messagehandler.h" #include "springmoderegionpreview.h" #include "common.h" #include "inputdevice.h" #include "setjoystick.h" #include #include #include MouseDPadSettingsDialog::MouseDPadSettingsDialog(JoyDPad *dpad, QWidget *parent) : MouseSettingsDialog(parent) , helper(dpad) { qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); resize(size().width(), 450); this->dpad = dpad; helper.moveToThread(dpad->thread()); calculateMouseSpeedPreset(); selectCurrentMouseModePreset(); calculateSpringPreset(); if (dpad->getButtonsPresetSensitivity() > 0.0) { ui->sensitivityDoubleSpinBox->setValue(dpad->getButtonsPresetSensitivity()); } updateAccelerationCurvePresetComboBox(); updateWindowTitleDPadName(); if (ui->mouseModeComboBox->currentIndex() == 2) { springPreviewWidget = new SpringModeRegionPreview(ui->springWidthSpinBox->value(), ui->springHeightSpinBox->value()); } else { springPreviewWidget = new SpringModeRegionPreview(0, 0); } calculateWheelSpeedPreset(); if (dpad->isRelativeSpring()) { ui->relativeSpringCheckBox->setChecked(true); } double easingDuration = dpad->getButtonsEasingDuration(); ui->easingDoubleSpinBox->setValue(easingDuration); ui->extraAccelerationGroupBox->setVisible(false); calculateReleaseSpringRadius(); calculateExtraAccelerationCurve(); changeSpringSectionStatus(ui->mouseModeComboBox->currentIndex()); changeSettingsWidgetStatus(ui->accelerationComboBox->currentIndex()); connect(this, &MouseDPadSettingsDialog::finished, springPreviewWidget, &SpringModeRegionPreview::deleteLater); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseDPadSettingsDialog::changeMouseMode); connect(ui->accelerationComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseDPadSettingsDialog::changeMouseCurve); connect(ui->horizontalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateConfigHorizontalSpeed); connect(ui->verticalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateConfigVerticalSpeed); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateSpringWidth); connect(ui->springWidthSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringWidth); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateSpringHeight); connect(ui->springHeightSpinBox, static_cast(&QSpinBox::valueChanged), springPreviewWidget, &SpringModeRegionPreview::setSpringHeight); connect(ui->relativeSpringCheckBox, &QCheckBox::clicked, this, &MouseDPadSettingsDialog::updateSpringRelativeStatus); connect(ui->sensitivityDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateSensitivity); connect(ui->wheelHoriSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateWheelSpeedHorizontalSpeed); connect(ui->wheelVertSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateWheelSpeedVerticalSpeed); connect(ui->easingDoubleSpinBox, static_cast(&QDoubleSpinBox::valueChanged), dpad, &JoyDPad::setButtonsEasingDuration); connect(ui->releaseSpringRadiusspinBox, static_cast(&QSpinBox::valueChanged), this, &MouseDPadSettingsDialog::updateReleaseSpringRadius); connect(ui->extraAccelCurveComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseDPadSettingsDialog::updateExtraAccelerationCurve); JoyButtonMouseHelper *mouseHelper = JoyButton::getMouseHelper(); connect(mouseHelper, &JoyButtonMouseHelper::mouseCursorMoved, this, &MouseDPadSettingsDialog::updateMouseCursorStatusLabels); connect(mouseHelper, &JoyButtonMouseHelper::mouseSpringMoved, this, &MouseDPadSettingsDialog::updateMouseSpringStatusLabels); lastMouseStatUpdate.start(); } void MouseDPadSettingsDialog::changeMouseMode(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 1) { dpad->setButtonsMouseMode(JoyButton::MouseCursor); if (springPreviewWidget->isVisible()) { springPreviewWidget->hide(); } } else if (index == 2) { dpad->setButtonsMouseMode(JoyButton::MouseSpring); if (!springPreviewWidget->isVisible()) { springPreviewWidget->setSpringWidth(ui->springWidthSpinBox->value()); springPreviewWidget->setSpringHeight(ui->springHeightSpinBox->value()); } } } void MouseDPadSettingsDialog::changeMouseCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = MouseSettingsDialog::getMouseCurveForIndex(index); dpad->setButtonsMouseCurve(temp); } void MouseDPadSettingsDialog::updateConfigHorizontalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*dpad->getButtons()); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setMouseSpeedX(value); } } void MouseDPadSettingsDialog::updateConfigVerticalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*dpad->getButtons()); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->setMouseSpeedY(value); } } void MouseDPadSettingsDialog::updateSpringWidth(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); dpad->setButtonsSpringWidth(value); } void MouseDPadSettingsDialog::updateSpringHeight(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); dpad->setButtonsSpringHeight(value); } void MouseDPadSettingsDialog::selectCurrentMouseModePreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool presetDefined = dpad->hasSameButtonsMouseMode(); if (presetDefined) { JoyButton::JoyMouseMovementMode mode = dpad->getButtonsPresetMouseMode(); if (mode == JoyButton::MouseCursor) { ui->mouseModeComboBox->setCurrentIndex(1); } else if (mode == JoyButton::MouseSpring) { ui->mouseModeComboBox->setCurrentIndex(2); } } else { ui->mouseModeComboBox->setCurrentIndex(0); } } void MouseDPadSettingsDialog::calculateSpringPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempWidth = dpad->getButtonsPresetSpringWidth(); int tempHeight = dpad->getButtonsPresetSpringHeight(); if (tempWidth > 0) { ui->springWidthSpinBox->setValue(tempWidth); } if (tempHeight > 0) { ui->springHeightSpinBox->setValue(tempHeight); } } void MouseDPadSettingsDialog::calculateMouseSpeedPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*dpad->getButtons()); int tempMouseSpeedX = 0; while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); tempMouseSpeedX = qMax(tempMouseSpeedX, button->getMouseSpeedX()); } iter.toFront(); int tempMouseSpeedY = 0; while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); tempMouseSpeedY = qMax(tempMouseSpeedY, button->getMouseSpeedY()); } ui->horizontalSpinBox->setValue(tempMouseSpeedX); ui->verticalSpinBox->setValue(tempMouseSpeedY); } void MouseDPadSettingsDialog::updateSensitivity(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); dpad->setButtonsSensitivity(value); } void MouseDPadSettingsDialog::updateAccelerationCurvePresetComboBox() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = dpad->getButtonsPresetMouseCurve(); MouseSettingsDialog::updateAccelerationCurvePresetComboBox(temp); } void MouseDPadSettingsDialog::calculateWheelSpeedPreset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(*dpad->getButtons()); int tempWheelSpeedX = 0; int tempWheelSpeedY = 0; while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); tempWheelSpeedX = qMax(tempWheelSpeedX, button->getWheelSpeedX()); tempWheelSpeedY = qMax(tempWheelSpeedY, button->getWheelSpeedY()); } ui->wheelHoriSpeedSpinBox->setValue(tempWheelSpeedX); ui->wheelVertSpeedSpinBox->setValue(tempWheelSpeedY); } void MouseDPadSettingsDialog::updateWheelSpeedHorizontalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); dpad->setButtonsWheelSpeedX(value); } void MouseDPadSettingsDialog::updateWheelSpeedVerticalSpeed(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); dpad->setButtonsWheelSpeedY(value); } void MouseDPadSettingsDialog::updateSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); dpad->setButtonsSpringRelativeStatus(value); } void MouseDPadSettingsDialog::updateWindowTitleDPadName() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(tr("Mouse Settings")).append(" - "); if (!dpad->getDpadName().isEmpty()) { temp.append(dpad->getName(false, true)); } else { temp.append(dpad->getName()); } if (dpad->getParentSet()->getIndex() != 0) { int setIndex = dpad->getParentSet()->getRealIndex(); temp.append(" [").append(tr("Set %1").arg(setIndex)); QString setName = dpad->getParentSet()->getName(); if (!setName.isEmpty()) { temp.append(": ").append(setName); } temp.append("]"); } setWindowTitle(temp); } void MouseDPadSettingsDialog::updateReleaseSpringRadius(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); dpad->setButtonsSpringDeadCircleMultiplier(value); } void MouseDPadSettingsDialog::calculateReleaseSpringRadius() { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->releaseSpringRadiusspinBox->setValue(dpad->getButtonsSpringDeadCircleMultiplier()); } void MouseDPadSettingsDialog::calculateExtraAccelerationCurve() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve curve = dpad->getButtonsExtraAccelerationCurve(); updateExtraAccelerationCurvePresetComboBox(curve); } void MouseDPadSettingsDialog::updateExtraAccelerationCurve(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve temp = JoyButton::LinearAccelCurve; if (index > 0) { InputDevice *device = dpad->getParentSet()->getInputDevice(); PadderCommon::lockInputDevices(); QMetaObject::invokeMethod(device, "haltServices", Qt::BlockingQueuedConnection); temp = getExtraAccelCurveForIndex(index); dpad->setButtonsExtraAccelerationCurve(temp); PadderCommon::unlockInputDevices(); } } JoyDPad *MouseDPadSettingsDialog::getDPad() const { return dpad; } SpringModeRegionPreview *MouseDPadSettingsDialog::getSpringPreviewWidget() const { return springPreviewWidget; } MouseDpadSettingsDialogHelper const &MouseDPadSettingsDialog::getHelper() { return helper; } MouseDpadSettingsDialogHelper &MouseDPadSettingsDialog::getHelperLocal() { return helper; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/mousedpadsettingsdialog.h000066400000000000000000000047071377703515000264650ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSEDPADSETTINGSDIALOG_H #define MOUSEDPADSETTINGSDIALOG_H #include "ui_mousesettingsdialog.h" #include "mousesettingsdialog.h" #include "uihelpers/mousedpadsettingsdialoghelper.h" class JoyDPad; class SpringModeRegionPreview; class MouseDPadSettingsDialog : public MouseSettingsDialog { Q_OBJECT public: explicit MouseDPadSettingsDialog(JoyDPad *dpad, QWidget *parent = nullptr); JoyDPad *getDPad() const; SpringModeRegionPreview *getSpringPreviewWidget() const; MouseDpadSettingsDialogHelper const &getHelper(); protected: void selectCurrentMouseModePreset(); void calculateSpringPreset(); void calculateMouseSpeedPreset(); void calculateWheelSpeedPreset(); void updateWindowTitleDPadName(); void calculateReleaseSpringRadius(); void calculateExtraAccelerationCurve(); public slots: void changeMouseMode(int index); void changeMouseCurve(int index); void updateConfigHorizontalSpeed(int value); void updateConfigVerticalSpeed(int value); void updateSpringWidth(int value); void updateSpringHeight(int value); void updateSensitivity(double value); void updateAccelerationCurvePresetComboBox(); void updateWheelSpeedHorizontalSpeed(int value); void updateWheelSpeedVerticalSpeed(int value); void updateSpringRelativeStatus(bool value); private slots: void updateReleaseSpringRadius(int value); void updateExtraAccelerationCurve(int index); private: MouseDpadSettingsDialogHelper &getHelperLocal(); JoyDPad *dpad; SpringModeRegionPreview *springPreviewWidget; MouseDpadSettingsDialogHelper helper; }; #endif // MOUSEDPADSETTINGSDIALOG_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/springmoderegionpreview.cpp000066400000000000000000000103631377703515000270460ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "springmoderegionpreview.h" #include "messagehandler.h" #include #include #include #include #include SpringModeRegionPreview::SpringModeRegionPreview(int width, int height, QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempwidth = adjustSpringSizeWidth(width); int tempheight = adjustSpringSizeHeight(height); setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_ShowWithoutActivating); setWindowTitle(tr("Spring Mode Preview")); if ((tempwidth >= 2) && (tempheight >= 2)) { int cw = (qApp->desktop()->width() / 2) - (tempwidth / 2); int ch = (qApp->desktop()->height() / 2) - (tempheight / 2); setGeometry(cw, ch, tempwidth, tempheight); show(); } else { resize(0, 0); move(0, 0); } } void SpringModeRegionPreview::paintEvent(QPaintEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(event); QPainter p(this); QPen border; border.setWidth(3); border.setColor(Qt::black); p.setPen(border); p.drawRect(1, 1, width() - 3, height() - 3); } int SpringModeRegionPreview::adjustSpringSizeWidth(int width) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempwidth = size().width(); if (width >= 2) { tempwidth = width; } else { tempwidth = 0; } return tempwidth; } int SpringModeRegionPreview::adjustSpringSizeHeight(int height) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempheight = size().height(); if (height >= 2) { tempheight = height; } else { tempheight = 0; } return tempheight; } void SpringModeRegionPreview::setSpringWidth(int width) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempwidth = adjustSpringSizeWidth(width); int height = size().height(); hide(); if ((tempwidth >= 2) && (height >= 2)) { int cw = (qApp->desktop()->width() / 2) - (tempwidth / 2); int ch = (qApp->desktop()->height() / 2) - (height / 2); setGeometry(cw, ch, tempwidth, height); if (!isVisible()) { show(); } } else { resize(tempwidth, height); move(0, 0); } } void SpringModeRegionPreview::setSpringHeight(int height) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempheight = adjustSpringSizeHeight(height); int width = size().width(); hide(); if ((width >= 2) && (tempheight >= 2)) { int cw = (qApp->desktop()->width() / 2) - (width / 2); int ch = (qApp->desktop()->height() / 2) - (tempheight / 2); setGeometry(cw, ch, width, tempheight); if (!isVisible()) { show(); } } else { resize(width, tempheight); move(0, 0); } } void SpringModeRegionPreview::setSpringSize(int width, int height) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempwidth = adjustSpringSizeWidth(width); int tempheight = adjustSpringSizeHeight(height); int cw = (qApp->desktop()->width() / 2) - (tempwidth / 2); int ch = (qApp->desktop()->height() / 2) - (height / 2); resize(tempwidth, tempheight); move(cw, ch); } AntiMicroX-antimicrox-2888bf6/src/mousedialog/springmoderegionpreview.h000066400000000000000000000026121377703515000265110ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SPRINGMODEREGIONPREVIEW_H #define SPRINGMODEREGIONPREVIEW_H #include class QPaintEvent; class SpringModeRegionPreview : public QWidget { Q_OBJECT public: explicit SpringModeRegionPreview(int width = 0, int height = 0, QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *event); int adjustSpringSizeWidth(int width); int adjustSpringSizeHeight(int height); public slots: void setSpringWidth(int width); void setSpringHeight(int height); void setSpringSize(int width, int height); }; #endif // SPRINGMODEREGIONPREVIEW_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/000077500000000000000000000000001377703515000233625ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mouseaxissettingsdialoghelper.cpp000066400000000000000000000060321377703515000322450ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mouseaxissettingsdialoghelper.h" #include "joyaxis.h" #include "messagehandler.h" #include MouseAxisSettingsDialogHelper::MouseAxisSettingsDialogHelper(JoyAxis *axis, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(axis); this->axis = axis; } void MouseAxisSettingsDialogHelper::updateExtraAccelerationStatus(bool checked) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setExtraAccelerationStatus(checked); axis->getNAxisButton()->setExtraAccelerationStatus(checked); } void MouseAxisSettingsDialogHelper::updateExtraAccelerationMultiplier(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setExtraAccelerationMultiplier(value); axis->getNAxisButton()->setExtraAccelerationMultiplier(value); } void MouseAxisSettingsDialogHelper::updateStartMultiPercentage(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setStartAccelMultiplier(value); axis->getNAxisButton()->setStartAccelMultiplier(value); } void MouseAxisSettingsDialogHelper::updateMinAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setMinAccelThreshold(value); axis->getNAxisButton()->setMinAccelThreshold(value); } void MouseAxisSettingsDialogHelper::updateMaxAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setMaxAccelThreshold(value); axis->getNAxisButton()->setMaxAccelThreshold(value); } void MouseAxisSettingsDialogHelper::updateAccelExtraDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setAccelExtraDuration(value); axis->getNAxisButton()->setAccelExtraDuration(value); } void MouseAxisSettingsDialogHelper::updateReleaseSpringRadius(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); axis->getPAxisButton()->setSpringDeadCircleMultiplier(value); axis->getNAxisButton()->setSpringDeadCircleMultiplier(value); } JoyAxis *MouseAxisSettingsDialogHelper::getAxis() const { return axis; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mouseaxissettingsdialoghelper.h000066400000000000000000000030571377703515000317160ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSEAXISSETTINGSDIALOGHELPER_H #define MOUSEAXISSETTINGSDIALOGHELPER_H #include class JoyAxis; class MouseAxisSettingsDialogHelper : public QObject { Q_OBJECT public: explicit MouseAxisSettingsDialogHelper(JoyAxis *axis, QObject *parent = nullptr); JoyAxis *getAxis() const; public slots: void updateExtraAccelerationStatus(bool checked); void updateExtraAccelerationMultiplier(double value); void updateStartMultiPercentage(double value); void updateMinAccelThreshold(double value); void updateMaxAccelThreshold(double value); void updateAccelExtraDuration(double value); void updateReleaseSpringRadius(int value); private: JoyAxis *axis; }; #endif // MOUSEAXISSETTINGSDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mousebuttonsettingsdialoghelper.cpp000066400000000000000000000053731377703515000326230ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousebuttonsettingsdialoghelper.h" #include "joybutton.h" #include "joybuttonslot.h" #include "messagehandler.h" #include MouseButtonSettingsDialogHelper::MouseButtonSettingsDialogHelper(JoyButton *button, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(button); this->button = button; } void MouseButtonSettingsDialogHelper::updateExtraAccelerationStatus(bool checked) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setExtraAccelerationStatus(checked); } void MouseButtonSettingsDialogHelper::updateExtraAccelerationMultiplier(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setExtraAccelerationMultiplier(value); } void MouseButtonSettingsDialogHelper::updateStartMultiPercentage(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setStartAccelMultiplier(value); } void MouseButtonSettingsDialogHelper::updateMinAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setMinAccelThreshold(value); } void MouseButtonSettingsDialogHelper::updateMaxAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setMaxAccelThreshold(value); } void MouseButtonSettingsDialogHelper::updateAccelExtraDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setAccelExtraDuration(value); } void MouseButtonSettingsDialogHelper::updateReleaseSpringRadius(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setSpringDeadCircleMultiplier(value); } void MouseButtonSettingsDialogHelper::updateSpringRelativeStatus(bool value) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setSpringRelativeStatus(value); } JoyButton *MouseButtonSettingsDialogHelper::getButton() const { return button; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mousebuttonsettingsdialoghelper.h000066400000000000000000000031671377703515000322670ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSEBUTTONSETTINGSDIALOGHELPER_H #define MOUSEBUTTONSETTINGSDIALOGHELPER_H #include class JoyButton; class MouseButtonSettingsDialogHelper : public QObject { Q_OBJECT public: explicit MouseButtonSettingsDialogHelper(JoyButton *button, QObject *parent = nullptr); JoyButton *getButton() const; public slots: void updateExtraAccelerationStatus(bool checked); void updateExtraAccelerationMultiplier(double value); void updateStartMultiPercentage(double value); void updateMinAccelThreshold(double value); void updateMaxAccelThreshold(double value); void updateAccelExtraDuration(double value); void updateReleaseSpringRadius(int value); void updateSpringRelativeStatus(bool value); private: JoyButton *button; }; #endif // MOUSEBUTTONSETTINGSDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mousecontrolsticksettingsdialoghelper.cpp000066400000000000000000000052701377703515000340220ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousecontrolsticksettingsdialoghelper.h" #include "joycontrolstick.h" #include "messagehandler.h" #include MouseControlStickSettingsDialogHelper::MouseControlStickSettingsDialogHelper(JoyControlStick *stick, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(stick); this->stick = stick; } void MouseControlStickSettingsDialogHelper::updateExtraAccelerationStatus(bool checked) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsExtraAccelerationStatus(checked); } void MouseControlStickSettingsDialogHelper::updateExtraAccelerationMultiplier(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsExtraAccelerationMultiplier(value); } void MouseControlStickSettingsDialogHelper::updateStartMultiPercentage(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsStartAccelerationMultiplier(value); } void MouseControlStickSettingsDialogHelper::updateMinAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsMinAccelerationThreshold(value); } void MouseControlStickSettingsDialogHelper::updateMaxAccelThreshold(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsMaxAccelerationThreshold(value); } void MouseControlStickSettingsDialogHelper::updateAccelExtraDuration(double value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsAccelerationExtraDuration(value); } void MouseControlStickSettingsDialogHelper::updateReleaseSpringRadius(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); stick->setButtonsSpringDeadCircleMultiplier(value); } JoyControlStick *MouseControlStickSettingsDialogHelper::getStick() const { return stick; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mousecontrolsticksettingsdialoghelper.h000066400000000000000000000031711377703515000334650ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSECONTROLSTICKSETTINGSDIALOGHELPER_H #define MOUSECONTROLSTICKSETTINGSDIALOGHELPER_H #include class JoyControlStick; class MouseControlStickSettingsDialogHelper : public QObject { Q_OBJECT public: explicit MouseControlStickSettingsDialogHelper(JoyControlStick *stick, QObject *parent = nullptr); JoyControlStick *getStick() const; public slots: void updateExtraAccelerationStatus(bool checked); void updateExtraAccelerationMultiplier(double value); void updateStartMultiPercentage(double value); void updateMinAccelThreshold(double value); void updateMaxAccelThreshold(double value); void updateAccelExtraDuration(double value); void updateReleaseSpringRadius(int value); private: JoyControlStick *stick; }; #endif // MOUSECONTROLSTICKSETTINGSDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mousedpadsettingsdialoghelper.cpp000066400000000000000000000023611377703515000322120ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousedpadsettingsdialoghelper.h" #include "joydpad.h" #include "joydpadbuttonwidget.h" #include "messagehandler.h" #include MouseDpadSettingsDialogHelper::MouseDpadSettingsDialogHelper(JoyDPad *dpad, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(dpad); this->dpad = dpad; } JoyDPad *MouseDpadSettingsDialogHelper::getDPad() const { return dpad; } AntiMicroX-antimicrox-2888bf6/src/mousedialog/uihelpers/mousedpadsettingsdialoghelper.h000066400000000000000000000022721377703515000316600ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSEDPADSETTINGSDIALOGHELPER_H #define MOUSEDPADSETTINGSDIALOGHELPER_H #include class JoyDPad; class MouseDpadSettingsDialogHelper : public QObject { Q_OBJECT public: explicit MouseDpadSettingsDialogHelper(JoyDPad *dpad, QObject *parent = nullptr); JoyDPad *getDPad() const; private: JoyDPad *dpad; }; #endif // MOUSEDPADSETTINGSDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/mousehelper.cpp000066400000000000000000000037231377703515000221130ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousehelper.h" #include "messagehandler.h" #include #include MouseHelper::MouseHelper(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); springMouseMoving = false; previousCursorLocation[0] = 0; previousCursorLocation[1] = 0; pivotPoint[0] = -1; pivotPoint[1] = -1; mouseTimer.setParent(this); mouseTimer.setSingleShot(true); QObject::connect(&mouseTimer, &QTimer::timeout, this, &MouseHelper::resetSpringMouseMoving); } void MouseHelper::resetSpringMouseMoving() { qInstallMessageHandler(MessageHandler::myMessageOutput); springMouseMoving = false; } void MouseHelper::initDeskWid() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (deskWid == nullptr) deskWid = new QDesktopWidget; } void MouseHelper::deleteDeskWid() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (deskWid != nullptr) { delete deskWid; deskWid = nullptr; } } QDesktopWidget *MouseHelper::getDesktopWidget() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return deskWid; } AntiMicroX-antimicrox-2888bf6/src/mousehelper.h000066400000000000000000000025501377703515000215550ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSEHELPER_H #define MOUSEHELPER_H #include #include class QDesktopWidget; class MouseHelper : public QObject { Q_OBJECT public: explicit MouseHelper(QObject *parent = nullptr); QDesktopWidget *getDesktopWidget() const; bool springMouseMoving; int previousCursorLocation[2]; int pivotPoint[2]; QTimer mouseTimer; public slots: void deleteDeskWid(); void initDeskWid(); private slots: void resetSpringMouseMoving(); private: QDesktopWidget *deskWid; }; #endif // MOUSEHELPER_H AntiMicroX-antimicrox-2888bf6/src/mousesettingsdialog.cpp000066400000000000000000000347341377703515000236620ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mousesettingsdialog.h" #include "ui_mousesettingsdialog.h" #include "globalvariables.h" #include "messagehandler.h" #include #include #include #include #include #include #include MouseSettingsDialog::MouseSettingsDialog(QWidget *parent) : QDialog(parent, Qt::Window) , ui(new Ui::MouseSettingsDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); JoyButtonMouseHelper *mouseHelper = JoyButton::getMouseHelper(); connect(mouseHelper, &JoyButtonMouseHelper::mouseCursorMoved, this, &MouseSettingsDialog::updateMouseCursorStatusLabels); connect(mouseHelper, &JoyButtonMouseHelper::mouseSpringMoved, this, &MouseSettingsDialog::updateMouseSpringStatusLabels); lastMouseStatUpdate.start(); connect(ui->accelerationComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseSettingsDialog::changeSettingsWidgetStatus); connect(ui->accelerationComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseSettingsDialog::refreshMouseCursorSpeedValues); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseSettingsDialog::changeSpringSectionStatus); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseSettingsDialog::changeMouseSpeedBoxStatus); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseSettingsDialog::changeWheelSpeedBoxStatus); connect(ui->mouseModeComboBox, static_cast(&QComboBox::currentIndexChanged), this, &MouseSettingsDialog::changeSensitivityStatusForMouseMode); connect(ui->horizontalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseSettingsDialog::updateHorizontalSpeedConvertLabel); connect(ui->horizontalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseSettingsDialog::moveSpeedsTogether); connect(ui->verticalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseSettingsDialog::updateVerticalSpeedConvertLabel); connect(ui->verticalSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseSettingsDialog::moveSpeedsTogether); connect(ui->wheelVertSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseSettingsDialog::updateWheelVerticalSpeedLabel); connect(ui->wheelHoriSpeedSpinBox, static_cast(&QSpinBox::valueChanged), this, &MouseSettingsDialog::updateWheelHorizontalSpeedLabel); connect(ui->relativeSpringCheckBox, &QCheckBox::clicked, this, &MouseSettingsDialog::disableReleaseSpringBox); connect(ui->relativeSpringCheckBox, &QCheckBox::clicked, this, &MouseSettingsDialog::resetReleaseRadius); } MouseSettingsDialog::~MouseSettingsDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void MouseSettingsDialog::changeSettingsWidgetStatus(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = getMouseCurveForIndex(index); int currentMouseMode = ui->mouseModeComboBox->currentIndex(); if ((currentMouseMode == 1) && (temp == JoyButton::PowerCurve)) { ui->sensitivityDoubleSpinBox->setEnabled(true); } else { ui->sensitivityDoubleSpinBox->setEnabled(false); } if ((currentMouseMode == 1) && ((temp == JoyButton::EasingQuadraticCurve) || (temp == JoyButton::EasingCubicCurve))) { ui->easingDoubleSpinBox->setEnabled(true); } else { ui->easingDoubleSpinBox->setEnabled(false); } } void MouseSettingsDialog::changeSpringSectionStatus(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 2) { ui->springWidthSpinBox->setEnabled(true); ui->springHeightSpinBox->setEnabled(true); ui->relativeSpringCheckBox->setEnabled(true); bool enableSpringRadiusBox = !ui->relativeSpringCheckBox->isChecked(); ui->releaseSpringRadiusspinBox->setEnabled(enableSpringRadiusBox); } else { ui->springWidthSpinBox->setEnabled(false); ui->springHeightSpinBox->setEnabled(false); ui->relativeSpringCheckBox->setEnabled(false); ui->releaseSpringRadiusspinBox->setEnabled(false); } } void MouseSettingsDialog::updateHorizontalSpeedConvertLabel(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(QString::number(value)); int currentCurveIndex = ui->accelerationComboBox->currentIndex(); JoyButton::JoyMouseCurve tempCurve = getMouseCurveForIndex(currentCurveIndex); int finalSpeed = JoyButton::calculateFinalMouseSpeed(tempCurve, value, GlobalVariables::JoyAxis::JOYSPEED); label = label.append(" = ").append(QString::number(finalSpeed)).append(" pps"); ui->horizontalSpeedLabel->setText(label); } void MouseSettingsDialog::updateVerticalSpeedConvertLabel(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(QString::number(value)); int currentCurveIndex = ui->accelerationComboBox->currentIndex(); JoyButton::JoyMouseCurve tempCurve = getMouseCurveForIndex(currentCurveIndex); int finalSpeed = JoyButton::calculateFinalMouseSpeed(tempCurve, value, GlobalVariables::JoyAxis::JOYSPEED); label = label.append(" = ").append(QString::number(finalSpeed)).append(" pps"); ui->verticalSpeedLabel->setText(label); } void MouseSettingsDialog::moveSpeedsTogether(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (ui->changeMouseSpeedsTogetherCheckBox->isChecked()) { ui->horizontalSpinBox->setValue(value); ui->verticalSpinBox->setValue(value); } } void MouseSettingsDialog::changeMouseSpeedBoxStatus(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 2) { ui->horizontalSpinBox->setEnabled(false); ui->verticalSpinBox->setEnabled(false); ui->changeMouseSpeedsTogetherCheckBox->setEnabled(false); ui->extraAccelerationGroupBox->setChecked(false); ui->extraAccelerationGroupBox->setEnabled(false); } else { ui->horizontalSpinBox->setEnabled(true); ui->verticalSpinBox->setEnabled(true); ui->changeMouseSpeedsTogetherCheckBox->setEnabled(true); ui->extraAccelerationGroupBox->setEnabled(true); if (ui->extraAccelerationGroupBox->isChecked()) ui->extraAccelerationGroupBox->setEnabled(true); } } void MouseSettingsDialog::changeWheelSpeedBoxStatus(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 2) { ui->wheelHoriSpeedSpinBox->setEnabled(false); ui->wheelVertSpeedSpinBox->setEnabled(false); } else { ui->wheelHoriSpeedSpinBox->setEnabled(true); ui->wheelVertSpeedSpinBox->setEnabled(true); } } void MouseSettingsDialog::updateWheelVerticalSpeedLabel(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(QString::number(value)); label.append(" = "); label.append(tr("%n notch(es)/s", "", value)); ui->wheelVertSpeedUnitsLabel->setText(label); } void MouseSettingsDialog::updateWheelHorizontalSpeedLabel(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(QString::number(value)); label.append(" = "); label.append(tr("%n notch(es)/s", "", value)); ui->wheelHoriSpeedUnitsLabel->setText(label); } void MouseSettingsDialog::updateAccelerationCurvePresetComboBox(JoyButton::JoyMouseCurve mouseCurve) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (mouseCurve) { case JoyButton::EnhancedPrecisionCurve: { ui->accelerationComboBox->setCurrentIndex(1); break; } case JoyButton::LinearCurve: { ui->accelerationComboBox->setCurrentIndex(2); break; } case JoyButton::QuadraticCurve: { ui->accelerationComboBox->setCurrentIndex(3); break; } case JoyButton::CubicCurve: { ui->accelerationComboBox->setCurrentIndex(4); break; } case JoyButton::QuadraticExtremeCurve: { ui->accelerationComboBox->setCurrentIndex(5); break; } case JoyButton::PowerCurve: { ui->accelerationComboBox->setCurrentIndex(6); break; } case JoyButton::EasingQuadraticCurve: { ui->accelerationComboBox->setCurrentIndex(7); break; } case JoyButton::EasingCubicCurve: { ui->accelerationComboBox->setCurrentIndex(8); break; } } } JoyButton::JoyMouseCurve MouseSettingsDialog::getMouseCurveForIndex(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyMouseCurve temp = JoyButton::DEFAULTMOUSECURVE; switch (index) { case 1: { temp = JoyButton::EnhancedPrecisionCurve; break; } case 2: { temp = JoyButton::LinearCurve; break; } case 3: { temp = JoyButton::QuadraticCurve; break; } case 4: { temp = JoyButton::CubicCurve; break; } case 5: { temp = JoyButton::QuadraticExtremeCurve; break; } case 6: { temp = JoyButton::PowerCurve; break; } case 7: { temp = JoyButton::EasingQuadraticCurve; break; } case 8: { temp = JoyButton::EasingCubicCurve; break; } } return temp; } void MouseSettingsDialog::changeSensitivityStatusForMouseMode(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (index == 2) { ui->sensitivityDoubleSpinBox->setEnabled(false); } else if (index == 1) { int currentCurveIndex = ui->accelerationComboBox->currentIndex(); JoyButton::JoyMouseCurve temp = getMouseCurveForIndex(currentCurveIndex); if (temp == JoyButton::PowerCurve) ui->sensitivityDoubleSpinBox->setEnabled(true); } else { ui->sensitivityDoubleSpinBox->setEnabled(false); } } /** * @brief Update mouse status labels with cursor mouse information provided by * an InputDevice. * @param X distance in pixels * @param Y distance in pixels * @param Time elapsed for generated event */ void MouseSettingsDialog::updateMouseCursorStatusLabels(int mouseX, int mouseY, int elapsed) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((lastMouseStatUpdate.elapsed() >= 100) && (elapsed > 0)) { QString tempX("%1 (%2 pps) (%3 ms)"); QString tempY("%1 (%2 pps) (%3 ms)"); ui->mouseStatusXLabel->setText(tempX.arg(mouseX).arg(mouseX * (1000 / elapsed)).arg(elapsed)); ui->mouseStatusYLabel->setText(tempY.arg(mouseY).arg(mouseY * (1000 / elapsed)).arg(elapsed)); lastMouseStatUpdate.start(); } } /** * @brief Update mouse status labels with spring mouse information * provided by an InputDevice. * @param X coordinate of cursor * @param Y coordinate of cursor */ void MouseSettingsDialog::updateMouseSpringStatusLabels(int coordX, int coordY) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (lastMouseStatUpdate.elapsed() >= 100) { QString tempX("%1"); QString tempY("%1"); ui->mouseStatusXLabel->setText(tempX.arg(coordX)); ui->mouseStatusYLabel->setText(tempY.arg(coordY)); lastMouseStatUpdate.start(); } } void MouseSettingsDialog::refreshMouseCursorSpeedValues(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(index); updateHorizontalSpeedConvertLabel(ui->horizontalSpinBox->value()); updateVerticalSpeedConvertLabel(ui->verticalSpinBox->value()); } void MouseSettingsDialog::disableReleaseSpringBox(bool enable) { qInstallMessageHandler(MessageHandler::myMessageOutput); ui->releaseSpringRadiusspinBox->setEnabled(!enable); } void MouseSettingsDialog::resetReleaseRadius(bool enabled) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (enabled && (ui->releaseSpringRadiusspinBox->value() > 0)) { ui->releaseSpringRadiusspinBox->setValue(0); } } JoyButton::JoyExtraAccelerationCurve MouseSettingsDialog::getExtraAccelCurveForIndex(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton::JoyExtraAccelerationCurve temp = JoyButton::LinearAccelCurve; switch (index) { case 1: { temp = JoyButton::LinearAccelCurve; break; } case 2: { temp = JoyButton::EaseOutSineCurve; break; } case 3: { temp = JoyButton::EaseOutQuadAccelCurve; break; } case 4: { temp = JoyButton::EaseOutCubicAccelCurve; break; } } return temp; } void MouseSettingsDialog::updateExtraAccelerationCurvePresetComboBox(JoyButton::JoyExtraAccelerationCurve curve) { qInstallMessageHandler(MessageHandler::myMessageOutput); int temp = 0; switch (curve) { case JoyButton::LinearAccelCurve: { temp = 1; break; } case JoyButton::EaseOutSineCurve: { temp = 2; break; } case JoyButton::EaseOutQuadAccelCurve: { temp = 3; break; } case JoyButton::EaseOutCubicAccelCurve: { temp = 4; break; } } ui->extraAccelCurveComboBox->setCurrentIndex(temp); } AntiMicroX-antimicrox-2888bf6/src/mousesettingsdialog.h000066400000000000000000000046631377703515000233250ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MOUSESETTINGSDIALOG_H #define MOUSESETTINGSDIALOG_H #include "joybutton.h" #include namespace Ui { class MouseSettingsDialog; } class MouseSettingsDialog : public QDialog { Q_OBJECT public: explicit MouseSettingsDialog(QWidget *parent = nullptr); ~MouseSettingsDialog(); protected: void updateAccelerationCurvePresetComboBox(JoyButton::JoyMouseCurve mouseCurve); void updateExtraAccelerationCurvePresetComboBox(JoyButton::JoyExtraAccelerationCurve curve); JoyButton::JoyMouseCurve getMouseCurveForIndex(int index); JoyButton::JoyExtraAccelerationCurve getExtraAccelCurveForIndex(int index); Ui::MouseSettingsDialog *ui; QTime lastMouseStatUpdate; public slots: void changeSettingsWidgetStatus(int index); void changeSpringSectionStatus(int index); void changeMouseSpeedBoxStatus(int index); void changeWheelSpeedBoxStatus(int index); void updateHorizontalSpeedConvertLabel(int value); void updateVerticalSpeedConvertLabel(int value); void moveSpeedsTogether(int value); void updateWheelVerticalSpeedLabel(int value); void updateWheelHorizontalSpeedLabel(int value); void changeSensitivityStatusForMouseMode(int index); void updateMouseCursorStatusLabels(int mouseX, int mouseY, int elapsed); void updateMouseSpringStatusLabels(int coordX, int coordY); virtual void changeMouseMode(int index) = 0; virtual void changeMouseCurve(int index) = 0; private slots: void refreshMouseCursorSpeedValues(int index); void disableReleaseSpringBox(bool enable); void resetReleaseRadius(bool enabled); }; #endif // MOUSESETTINGSDIALOG_H AntiMicroX-antimicrox-2888bf6/src/mousesettingsdialog.ui000066400000000000000000001014061377703515000235040ustar00rootroot00000000000000 MouseSettingsDialog Qt::WindowModal 0 0 587 612 Mouse Settings Mouse Mode: Cursor mode is used to move the mouse cursor around the screen relative to its current position depending on how much you move an axis or if a button is pressed. Spring mode is used to move the mouse cursor from the center of the screen depending on how much you move an axis. The mouse cursor will be returned to the center of the screen when the axis is moved back to the dead zone. Cursor Spring 160 0 Acceleration: Enhanced: Three tier curve that makes the mouse move slow on the low end of an axis and fast on the high end. Linear: Mouse moves proportionally to axis. Quadratic: Mouse accelerates slowly on low end. Cubic: Mouse accelerates slower than Quadratic. Quadratic Extreme: Raises mouse speed 1.5 times once 95% axis travel has been reached. Power Function: Allows for a more custom curve option. Easing Quadratic: Axis high end is gradually accelerated over a period of time using a Quadratic curve. Easing Cubic: Axis high end is gradually accelerated over a period of time using a Cubic curve. Enhanced Precision Linear Quadratic Cubic Quadratic Extreme Power Function Easing Quadratic Easing Cubic Qt::Vertical QSizePolicy::Fixed 20 10 Mouse Speed Settings false false true Enable to change the horizontal and vertical speed boxes at the same time. Change Together 16 10 10 10 Hori&zontal Speed: horizontalSpinBox true 1 300 1 1 = 20 pps 10 10 &Vertical Speed: verticalSpinBox true 1 300 1 1 = 20 pps 16 10 10 Wheel Hori. Speed: wheelHoriSpeedSpinBox Set the speed used for horizontal mouse wheel movement according to number of simulated notches per second. 1 100 1 1 1 = 1 notch(es)/s 10 Wheel Vert. Speed: wheelVertSpeedSpinBox Set the speed used for vertical mouse wheel movement according to number of simulated notches per second. 1 100 1 = 1 notch(es)/s Sensitivit&y: sensitivityDoubleSpinBox false For Power Function acceleration curve. Specifies the factor to use for curve sensitivity. When the value is above 1.0, the mouse movement will be accelerated faster at the low end of an axis. 3 0.001000000000000 1000.000000000000000 0.100000000000000 1.000000000000000 Easing Duration: sensitivityDoubleSpinBox false Specifies the amount of time (in seconds) that will be required before the mouse is fully accelerated after reaching the high end of an axis. s 2 0.000000000000000 5.000000000000000 0.100000000000000 0.500000000000000 Qt::Vertical QSizePolicy::Fixed 20 10 true Options for adding more acceleration to the mouse movement beyond what the acceleration curve would produce. Acceleration is added based on how quickly an axis is moved in one gamepad poll. This is meant to help work around some of the issues of the very limited input range available using typical gamepad analog sticks. Delta Acceleration false true false &Multiplier: extraAccelDoubleSpinBox Highest value to accelerate mouse movement by x 1.000000000000000 200.000000000000000 2.000000000000000 Start %: minMultiDoubleSpinBox Acceleration begins at this percentage of the base multiplier % 0.000000000000000 100.000000000000000 1.000000000000000 0.000000000000000 Mi&n Threshold: minThresholdDoubleSpinBox Minimum amount of axis travel required for acceleration to begin % 100.000000000000000 10.000000000000000 Max Threshold: maxThresholdDoubleSpinBox Maximum axis travel before acceleration has reached the multiplier value % 100.000000000000000 100.000000000000000 E&xtra Duration: accelExtraDurationDoubleSpinBox Extend the time that extra acceleration is applied. Axis travel will be taken into account. A slower flick will decrease the actual time that extra acceleration will be applied. s 0.000000000000000 5.000000000000000 0.050000000000000 Curve: Linear Ease Out Sine Ease Out Quad Ease Out Cubic 10 Spring Settings Spring Width: springWidthSpinBox false Changes the width of the region that the cursor can move in spring mode. 0 will use the entire width of your screen. 16777215 Spring Height: springHeightSpinBox false Changes the height of the region that the cursor can move in spring mode. 0 will use the entire height of your screen. 16777215 Release Radius: releaseSpringRadiusspinBox false % 100 false Specifies that the spring area will be relative to the mouse position set by a non-relative spring. Relative Qt::Vertical 20 40 Mouse Status X: 0 (0 pps) Y: 0 (0 pps) Qt::Vertical QSizePolicy::Fixed 20 10 Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() MouseSettingsDialog accept() 248 254 157 274 buttonBox rejected() MouseSettingsDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/profileimporter.cpp000066400000000000000000000300141377703515000227760ustar00rootroot00000000000000#include "profileimporter.h" #include "ui_profileimporter.h" #include #include #include #include #include #include #include #include using namespace std; ProfileImporter::ProfileImporter(AntiMicroXSettings *settings, QWidget *parent) : QWidget(parent) , ui(new Ui::ProfileImporter) { ui->setupUi(this); this->settings = settings; rewriteButtonGroup(); } ProfileImporter::~ProfileImporter() { delete ui; } // Author: Lex Fridman // http://lexfridman.com/convert-string-to-qt-keycode-in-c/ int ProfileImporter::convertStringToQtKey(QString const &keyString) { QKeySequence seq(keyString); int keyCode; // We should only working with a single key here if (seq.count() == 1) keyCode = seq[0]; else { // Should be here only if a modifier key (e.g. Ctrl, Alt) is pressed. assert(seq.count() == 0); // Add a non-modifier key "A" to the picture because QKeySequence // seems to need that to acknowledge the modifier. We know that A has // a keyCode of 65 (or 0x41 in hex) seq = QKeySequence(keyString + "+A"); assert(seq.count() == 1); assert(seq[0] > 65); keyCode = seq[0] - 65; } return keyCode; } // http://programmingknowledgeblog.blogspot.com/2013/05/c-program-to-convert-hex-to-ascii-string.html QChar ProfileImporter::convertHexToString_QChar(QString const &hexValue) { std::istringstream iss(hexValue.toStdString()); iss.flags(std::ios::hex); int i; iss >> i; return QChar(i); } char ProfileImporter::convertHexToString_char(string const &hexValue) { std::istringstream iss(hexValue); iss.flags(std::ios::hex); int i; iss >> i; return static_cast(i); } void ProfileImporter::putGamecontrMapping() { /* QString mappingString = generateSDLMappingString(); settings->getLock()->lock(); settings->setValue(QString("Mappings/").append(device->getGUIDString()), mappingString); settings->setValue(QString("Mappings/%1%2").arg(device->getGUIDString()).arg("Disable"), "0"); settings->sync(); bool displayMapping = settings->runtimeValue("DisplaySDLMapping", false).toBool(); settings->getLock()->unlock(); if (displayMapping) { QTextStream out(stdout); out << generateSDLMappingString(); } emit mappingUpdate(mappingString, device); */ } void ProfileImporter::putSettingsToApp() { // general data - GUID and full name (if ui->importSameCheckbox was checked before) // complex data - app settings as additional settings (if ui->fullSettCheckBox was checked before) // data for gamecontroller mapping // data for mapping from keyboard/mouse to gamecontroller } /* // rough draft QStringList templist = QStringList(); templist.append(device->getGUIDString()); templist.append(device->getSDLName()); templist.append(QString("platform:").append(device->getSDLPlatform())); for (int i=0; i < ui->buttonMappingTableWidget->rowCount(); i++) { QTableWidgetItem *item = ui->buttonMappingTableWidget->item(i, 0); if (item != nullptr) { QString mapNative = QString(); QList tempassociation = item->data(Qt::UserRole).toList(); if (tempassociation.size() == 2) { int bindingType = tempassociation.value(0).toInt(); if (bindingType == 0) { mapNative.append("b"); mapNative.append(QString::number(tempassociation.value(1).toInt())); } else if (bindingType > 0) { mapNative.append("a"); mapNative.append(QString::number(tempassociation.value(0).toInt()-1)); } else if (bindingType < 0) { mapNative.append("h"); mapNative.append(QString::number(tempassociation.value(0).toInt()+1)); mapNative.append(".").append(QString::number(tempassociation.value(1).toInt())); } } if (!mapNative.isEmpty()) { QString sdlButtonName = tempaliases.value(i); QString temp = QString("%1:%2").arg(sdlButtonName).arg(mapNative); templist.append(temp); } } } return templist.join(",").append(","); */ bool ProfileImporter::allFilled() { if ((!ui->profileLineEdit->text().isEmpty()) && (radioBtnProfiles.checkedButton() != nullptr)) { if (ui->fullSettCheckBox->isChecked()) { if (ui->configLineEdit->text().isEmpty()) return false; else return true; } else { return true; } } else { return false; } } void ProfileImporter::changeExtensionFile(QString filePath) { QFileInfo info(filePath); if (properExtension(filePath)) { if ((radioBtnProfiles.checkedButton()->text().remove('&') == "JoyToKey")) { QString strNewName = info.path() + "/" + info.completeBaseName() + ".ini"; QFile renamed(filePath); renamed.rename(filePath, strNewName); } } else { QMessageBox box; box.setText(trUtf8("Extension of file is incorrect. Choose one type of profile and define full path of file.")); box.setWindowTitle(trUtf8("Incorrect extension")); box.setStandardButtons(QMessageBox::Close); box.raise(); box.exec(); } } void ProfileImporter::backExtensionFile(QString filePath) { QFileInfo info(filePath); QString strNewName = info.path() + "/" + info.completeBaseName() + "." + extensionProfile(); QFile renamed(filePath); renamed.rename(filePath, strNewName); } QString ProfileImporter::extensionProfile() { if ((radioBtnProfiles.checkedButton()->text().remove('&') == "JoyToKey")) return QString("cfg"); else if ((radioBtnProfiles.checkedButton()->text().remove('&') == "XPadder")) return QString("xpaddercontroller"); else if ((radioBtnProfiles.checkedButton()->text().remove('&') == "Pinnacle Game Profiler")) return QString("pin"); return QString("cfg"); } bool ProfileImporter::properExtension(const QString &profilePath) { QFileInfo info(profilePath); if ((radioBtnProfiles.checkedButton()->text().remove('&') == "JoyToKey") && (info.completeSuffix() == "cfg")) { return true; } else if ((radioBtnProfiles.checkedButton()->text().remove('&') == "XPadder") && (info.completeSuffix() == "xpaddercontroller")) { return true; } else if ((radioBtnProfiles.checkedButton()->text().remove('&') == "Pinnacle Game Profiler") && (info.completeSuffix() == "pin")) { return true; } return false; } bool ProfileImporter::properExtensionSett(const QString &settfilePath) { QFileInfo info(settfilePath); if (info.completeSuffix() == "ini") return true; return false; } void ProfileImporter::openFile(QString importedFilePath) { QSettings settings(importedFilePath, QSettings::NativeFormat); } void ProfileImporter::readSettGroups() {} const QString ProfileImporter::displayModeJoyToKey() { return displayedModeJoyToKey; } void ProfileImporter::setDisplayModeJoyToKey(QString const &displayMode) { displayedModeJoyToKey = displayMode; } QString ProfileImporter::filedialogDescExt() { if (radioBtnProfiles.checkedButton()->text().remove('&') == "JoyToKey") return trUtf8("JoyToKey profiles (*.cfg)"); else if (radioBtnProfiles.checkedButton()->text().remove('&') == "XPadder") return trUtf8("XPadder profiles (*.xpaddercontroller)"); else if (radioBtnProfiles.checkedButton()->text().remove('&') == "Pinnacle Game Profiler") return trUtf8("Pinnacle Game profiles (*.pin)"); return ""; } const QString ProfileImporter::importedFilePath(QString title, QString extensionFile) { QString fileName = QFileDialog::getOpenFileName( this, title, QFileDialog::getExistingDirectory(this, trUtf8("Find"), QDir::currentPath()), extensionFile); return fileName; } void ProfileImporter::rewriteButtonGroup() { QList allButtons = ui->groupBox->findChildren(); qDebug() << allButtons.size(); for (int i = 0; i < allButtons.size(); ++i) { radioBtnProfiles.addButton(allButtons[i], i); } qDebug() << radioBtnProfiles.checkedId(); qDebug() << radioBtnProfiles.checkedButton(); } void ProfileImporter::putSettingsFromJoyToKey() {} void ProfileImporter::putSettingsFromXPadder() {} void ProfileImporter::putSettingsFromPinnacle() {} // ----------------------------- SLOTS ------------------------------------- // // 0 - unchecked // 2 - checked void ProfileImporter::on_fullSettCheckBox_stateChanged(int state) { switch (state) { case 0: ui->configLineEdit->clear(); ui->configLabel->setDisabled(true); ui->configLineEdit->setDisabled(true); ui->findConfigBtn->setDisabled(true); break; case 2: ui->configLabel->setDisabled(false); ui->configLineEdit->setDisabled(false); ui->findConfigBtn->setDisabled(false); break; default: ui->configLineEdit->clear(); ui->configLabel->setDisabled(true); ui->configLineEdit->setDisabled(true); ui->findConfigBtn->setDisabled(true); break; } } void ProfileImporter::on_AcceptBtn_clicked() { if (!allFilled()) { QMessageBox box; box.setText(trUtf8("Could not import profile. Choose profile type and profile's file.")); box.setWindowTitle(trUtf8("Insufficient data")); box.setStandardButtons(QMessageBox::Close); box.raise(); box.exec(); } else { } } void ProfileImporter::on_cancelBtn_clicked() { close(); } void ProfileImporter::on_findProfileBtn_clicked() { if (radioBtnProfiles.checkedButton() == nullptr) { QMessageBox box; box.setText(trUtf8("Could not define file's extension. Choose profile's type first above.")); box.setWindowTitle(trUtf8("Insufficient data")); box.setStandardButtons(QMessageBox::Close); box.raise(); box.exec(); } else { QString profile = importedFilePath(trUtf8("Choose game profile"), filedialogDescExt()); if (!properExtension(profile)) { QMessageBox box; box.setText(trUtf8("Could not choose a file. Find a file with proper extension.")); box.setWindowTitle(trUtf8("Incorrect filename")); box.setStandardButtons(QMessageBox::Close); box.raise(); box.exec(); } else { ui->profileLineEdit->setText(profile); QFileInfo info(profile); chosenFile = info.completeBaseName(); } } } void ProfileImporter::on_findConfigBtn_clicked() { if (radioBtnProfiles.checkedButton() == nullptr) { QMessageBox box; box.setText(trUtf8("Could not define file's extension. Choose profile's type first above.")); box.setWindowTitle(trUtf8("Insufficient data")); box.setStandardButtons(QMessageBox::Close); box.raise(); box.exec(); } else { QString settingsFile = importedFilePath(trUtf8("Choose app settings file"), trUtf8("Settings file (*.ini)")); if (!properExtensionSett(settingsFile)) { QMessageBox box; box.setText(trUtf8("Could not choose a file. Find a file with proper extension.")); box.setWindowTitle(trUtf8("Incorrect filename")); box.setStandardButtons(QMessageBox::Close); box.raise(); box.exec(); } else { ui->configLineEdit->setText(settingsFile); QFileInfo info(settingsFile); chosenFileSett = info.completeBaseName(); } } } AntiMicroX-antimicrox-2888bf6/src/profileimporter.h000066400000000000000000000134421377703515000224510ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEIMPORTER_H #define PROFILEIMPORTER_H #include #include #include class AntiMicroSettings; namespace Ui { class ProfileImporter; } namespace Converters { const QHash joyToKeyForAntimicroX{ {"Axis1n", 11}, // left (left-stick) {"Axis1p", 11}, // right (left-stick) {"Axis2n", 12}, // up (left-stick) {"Axis2p", 12}, // down (left-stick) {"Axis3n", 13}, // left (right-stick) {"Axis3p", 13}, // right (right-stick) {"Axis4n", 14}, // up (right-stick) {"Axis4p", 14}, // down (right-stick) /* { "Axis5n", }, { "Axis5p", }, { "Axis6n", }, { "Axis6p", }, { "Axis7n", }, { "Axis7p", }, { "Axis8n", }, { "Axis8p", }, { "Up-Right", }, { "Up- Left", }, { "Dn- Left", }, { "Dn-Right", }, { "Up-Right2", }, { "Up- Left2", }, { "Dn- Left2", }, { "Dn-Right2", }, */ {"POV1-1", 17}, // arrow up // { "POV1-2", }, {"POV1-3", 20}, // arrow right // { "POV1-4", }, {"POV1-5", 19}, // arrow down // { "POV1-6", }, {"POV1-7", 18}, // arrow left /* { "POV1-8", }, { "POV2-1", }, { "POV2-2", }, { "POV2-3", }, { "POV2-4", }, { "POV2-5", }, { "POV2-6", }, { "POV2-7", }, { "POV2-8", }, { "POV3-1", }, { "POV3-2", }, { "POV3-3", }, { "POV3-4", }, { "POV3-5", }, { "POV3-6", }, { "POV3-7", }, { "POV3-8", }, { "POV4-1", }, { "POV4-2", }, { "POV4-3", }, { "POV4-4", }, { "POV4-5", }, { "POV4-6", }, { "POV4-7", }, { "POV4-8", }, */ {"Button01", 2}, {"Button02", 0}, {"Button03", 1}, {"Button04", 3}, {"Button05", 7}, {"Button06", 8}, {"Button07", 15}, {"Button08", 16}, {"Button09", 4}, {"Button10", 5}, {"Button11", 9}, {"Button12", 10} /* { "Button13", }, { "Button14", }, { "Button15", }, { "Button16", }, { "Button17", }, { "Button18", }, { "Button19", }, { "Button20", }, { "Button21", }, { "Button22", }, { "Button23", }, { "Button24", }, { "Button25", }, { "Button26", }, { "Button27", }, { "Button28", }, { "Button29", }, { "Button30", }, { "Button31", }, { "Button32", } */ }; // temporarily blocked until it will appear an occasion for making tests /* const QHash xPadderForAntimicroX { { , }, { , }, { , } }; const QHash pinnacleForAntimicroX { { , }, { , }, { , } }; */ } // namespace Converters class ProfileImporter : public QWidget { Q_OBJECT public: explicit ProfileImporter(AntiMicroSettings *settings, QWidget *parent = 0); ~ProfileImporter(); void changeExtensionFile(QString filePath); void backExtensionFile(QString filePath); void openFile(QString importedFilePath); void readSettGroups(); const QString importedFilePath(QString title, QString extensionFile); const QString displayModeJoyToKey(); QChar convertHexToString_QChar(QString const &hexValue); char convertHexToString_char(std::string const &hexValue); int convertStringToQtKey(QString const &keyString); protected: bool allFilled(); bool properExtension(const QString &profilePath); bool properExtensionSett(const QString &settfilePath); void setDisplayModeJoyToKey(QString const &displayMode); QString extensionProfile(); private slots: void on_AcceptBtn_clicked(); void on_cancelBtn_clicked(); void on_findProfileBtn_clicked(); void on_fullSettCheckBox_stateChanged(int state); void on_findConfigBtn_clicked(); private: Ui::ProfileImporter *ui; QHash antToCurrGamepads; AntiMicroSettings *settings; QButtonGroup radioBtnProfiles; QString chosenFile; QString chosenFileSett; QString displayedModeJoyToKey; QString buttonMode; void putSettingsToApp(); void putGamecontrMapping(); void rewriteButtonGroup(); void putSettingsFromJoyToKey(); void putSettingsFromXPadder(); void putSettingsFromPinnacle(); QString filedialogDescExt(); }; #endif // PROFILEIMPORTER_H AntiMicroX-antimicrox-2888bf6/src/profileimporter.ui000066400000000000000000000202611377703515000226340ustar00rootroot00000000000000 ProfileImporter 0 0 457 555 Form 13 75 true Import profile from: Qt::AlignCenter 11 50 false &JoyToKey true false 11 50 false Pinnacle &Game Profiler false 11 50 false &XPadder 3 10 50 false Imported file 75 true Find profile file... Import settings for the same gamecontrollers not only from chosen profile Import full settings 5 5 5 5 false Imported settings false false 75 true Find configuration file... Qt::Vertical QSizePolicy::Fixed 20 200 75 true true Remember about connection of gamecontrollers before profiles importing true 6 Cancel Qt::Horizontal 40 20 OK AntiMicroX-antimicrox-2888bf6/src/qkeydisplaydialog.cpp000066400000000000000000000065121377703515000233010ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "qkeydisplaydialog.h" #include "ui_qkeydisplaydialog.h" #include "antkeymapper.h" #include "eventhandlerfactory.h" #include "messagehandler.h" #include #include #include #include #include #ifdef WITH_X11 #include "x11extras.h" #endif QKeyDisplayDialog::QKeyDisplayDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::QKeyDisplayDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->setFocus(); BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); ui->eventHandlerLabel->setText(handler->getName()); } QKeyDisplayDialog::~QKeyDisplayDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void QKeyDisplayDialog::keyPressEvent(QKeyEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (event->key()) { case Qt::Key_Escape: case Qt::Key_Enter: case Qt::Key_Return: break; default: QDialog::keyPressEvent(event); } } void QKeyDisplayDialog::keyReleaseEvent(QKeyEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); int scancode = event->nativeScanCode(); int virtualkey = event->nativeVirtualKey(); int finalvirtual = 0; #ifdef WITH_X11 if (QApplication::platformName() == QStringLiteral("xcb")) { // Obtain group 1 X11 keysym. Removes effects from modifiers. finalvirtual = X11Extras::getInstance()->getGroup1KeySym(virtualkey); #ifdef WITH_UINPUT QtKeyMapperBase *nativeKeyMapper = AntKeyMapper::getInstance()->getNativeKeyMapper(); if (nativeKeyMapper && (nativeKeyMapper->getIdentifier() == "xtest")) { int tempalias = nativeKeyMapper->returnQtKey(virtualkey); finalvirtual = AntKeyMapper::getInstance()->returnVirtualKey(tempalias); } #endif } else { finalvirtual = scancode; } #else if (QApplication::platformName() == QStringLiteral("xcb")) { finalvirtual = AntKeyMapper::getInstance()->returnVirtualKey(event->key()); } else { finalvirtual = scancode; } #endif ui->nativeKeyLabel->setText(QString("0x%1").arg(finalvirtual, 0, 16)); ui->qtKeyLabel->setText(QString("0x%1").arg(event->key(), 0, 16)); QString tempValue = QString("0x%1").arg(AntKeyMapper::getInstance()->returnQtKey(finalvirtual), 0, 16); ui->antimicroKeyLabel->setText(tempValue); } AntiMicroX-antimicrox-2888bf6/src/qkeydisplaydialog.h000066400000000000000000000024461377703515000227500ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QKEYDISPLAYDIALOG_H #define QKEYDISPLAYDIALOG_H #include class QKeyEvent; class QWidget; namespace Ui { class QKeyDisplayDialog; } class QKeyDisplayDialog : public QDialog { Q_OBJECT public: explicit QKeyDisplayDialog(QWidget *parent = nullptr); ~QKeyDisplayDialog(); protected: virtual void keyPressEvent(QKeyEvent *event); virtual void keyReleaseEvent(QKeyEvent *event); private: Ui::QKeyDisplayDialog *ui; }; #endif // QKEYDISPLAYDIALOG_H AntiMicroX-antimicrox-2888bf6/src/qkeydisplaydialog.ui000066400000000000000000000157241377703515000231410ustar00rootroot00000000000000 QKeyDisplayDialog Qt::ApplicationModal 0 0 597 428 0 0 Qt::StrongFocus Key Checker true 8 8 <html><head/><body><p>Press a key on your keyboard to see how the key is detected by this application. The window will show the system native key value, the original value given by Qt (if applicable), and the custom value used by AntiMicroX.</p><p>The AntiMicroX key value and the Qt key value will usually be the same. AntiMicroX tries to use the key values defined in Qt when possible. Check the page <a href="http://doc.qt.io/qt-5/qt.html#Key-enum"><span style=" text-decoration: underline; color:#0057ae;">http://doc.qt.io/qt-5/qt.html#Key-enum</span></a> for a list of values defined by Qt. If you discover that a key is not natively supported by this program, please report the problem to AntiMicroX's <a href="https://github.com/AntiMicroX/antimicrox/"><span style=" text-decoration: underline; color:#0057ae;">GitHub page</span></a> so that the program can be edited to support it directly. As it is, a custom prefix is added to unknown values so they can still be used; the main problem is that the profile will no longer be portable.</p></body></html> Qt::AutoText true true Qt::LinksAccessibleByMouse Qt::Vertical QSizePolicy::Fixed 20 10 QFormLayout::ExpandingFieldsGrow 20 10 6 10 75 true Event Handler: 75 true Native Key Value: 0x00000000 Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse 75 true Qt Key Value: 0x00000000 Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse 75 true antimicro Key Value: 0x00000000 Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse Qt::NoFocus Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() QKeyDisplayDialog accept() 248 254 157 274 buttonBox rejected() QKeyDisplayDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/qtkeymapperbase.cpp000066400000000000000000000051221377703515000227530ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "qtkeymapperbase.h" #include "messagehandler.h" #include const int QtKeyMapperBase::customQtKeyPrefix; const int QtKeyMapperBase::customKeyPrefix; const int QtKeyMapperBase::nativeKeyPrefix; QtKeyMapperBase::QtKeyMapperBase(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } int QtKeyMapperBase::returnQtKey(int key, int scancode) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(scancode); return virtKeyToQtKeyHash.value(key); } int QtKeyMapperBase::returnVirtualKey(int qkey) { qInstallMessageHandler(MessageHandler::myMessageOutput); return qtKeyToVirtKeyHash.value(qkey); } bool QtKeyMapperBase::isModifier(int qkey) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool modifier = false; int qtKeyValue = qkey & 0x0FFFFFFF; switch (qtKeyValue) { case Qt::Key_Shift: { modifier = true; break; } case Qt::Key_Control: { modifier = true; break; } case Qt::Key_Alt: { modifier = true; break; } case Qt::Key_Meta: { modifier = true; break; } } return modifier; } QtKeyMapperBase::charKeyInformation QtKeyMapperBase::getCharKeyInformation(QChar value) { qInstallMessageHandler(MessageHandler::myMessageOutput); charKeyInformation temp; temp.virtualkey = 0; temp.modifiers = Qt::NoModifier; if (virtkeyToCharKeyInfo.contains(value.unicode())) temp = virtkeyToCharKeyInfo.value(value.unicode()); return temp; } /** * @brief Obtain identifier string for key mapper. * @return Identifier string. */ QString QtKeyMapperBase::getIdentifier() { qInstallMessageHandler(MessageHandler::myMessageOutput); return identifier; } AntiMicroX-antimicrox-2888bf6/src/qtkeymapperbase.h000066400000000000000000000073461377703515000224320ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QTKEYMAPPERBASE_H #define QTKEYMAPPERBASE_H #include #include class QtKeyMapperBase : public QObject { Q_OBJECT public: explicit QtKeyMapperBase(QObject *parent = nullptr); typedef struct _charKeyInformation { Qt::KeyboardModifiers modifiers; int virtualkey; } charKeyInformation; virtual int returnVirtualKey(int qkey); virtual int returnQtKey(int key, int scancode = 0); virtual bool isModifier(int qkey); charKeyInformation getCharKeyInformation(QChar value); QString getIdentifier(); static const int customQtKeyPrefix = 0x10000000; static const int customKeyPrefix = 0x20000000; static const int nativeKeyPrefix = 0x60000000; enum { AntKey_Shift_R = Qt::Key_Shift | customQtKeyPrefix, AntKey_Control_R = Qt::Key_Control | customQtKeyPrefix, AntKey_Shift_Lock = 0xffe6 | customKeyPrefix, // XK_Shift_Lock | 0x20000000 AntKey_Meta_R = Qt::Key_Meta | customQtKeyPrefix, AntKey_Alt_R = Qt::Key_Alt | customQtKeyPrefix, AntKey_KP_Divide = Qt::Key_Slash | customQtKeyPrefix, AntKey_KP_Multiply = Qt::Key_Asterisk | customQtKeyPrefix, AntKey_KP_Subtract = Qt::Key_Minus | customQtKeyPrefix, AntKey_KP_Add = Qt::Key_Plus | customQtKeyPrefix, AntKey_KP_Decimal = Qt::Key_Period | customQtKeyPrefix, AntKey_KP_Insert = Qt::Key_Insert | customQtKeyPrefix, AntKey_Delete = Qt::Key_Delete | customQtKeyPrefix, AntKey_KP_Delete = 0xff9f | customKeyPrefix, AntKey_KP_End = Qt::Key_End | customQtKeyPrefix, AntKey_KP_Down = Qt::Key_Down | customQtKeyPrefix, AntKey_KP_Prior = Qt::Key_PageUp | customQtKeyPrefix, AntKey_KP_Left = Qt::Key_Left | customQtKeyPrefix, AntKey_KP_Begin = Qt::Key_Clear | customQtKeyPrefix, AntKey_KP_Right = Qt::Key_Right | customQtKeyPrefix, AntKey_KP_Home = Qt::Key_Home | customQtKeyPrefix, AntKey_KP_Up = Qt::Key_Up | customQtKeyPrefix, AntKey_KP_Next = Qt::Key_PageDown | customQtKeyPrefix, AntKey_KP_Enter = 0xff8d | customKeyPrefix, AntKey_KP_0 = 0xffb0 | customKeyPrefix, AntKey_KP_1 = 0xffb1 | customKeyPrefix, AntKey_KP_2 = 0xffb2 | customKeyPrefix, AntKey_KP_3 = 0xffb3 | customKeyPrefix, AntKey_KP_4 = 0xffb4 | customKeyPrefix, AntKey_KP_5 = 0xffb5 | customKeyPrefix, AntKey_KP_6 = 0xffb6 | customKeyPrefix, AntKey_KP_7 = 0xffb7 | customKeyPrefix, AntKey_KP_8 = 0xffb8 | customKeyPrefix, AntKey_KP_9 = 0xffb9 | customKeyPrefix }; protected: virtual void populateMappingHashes() = 0; virtual void populateCharKeyInformation() = 0; QHash qtKeyToVirtKeyHash; QHash virtKeyToQtKeyHash; QHash virtkeyToCharKeyInfo; // Unicode representation -> VK+Modifier information QString identifier; }; #endif // QTKEYMAPPERBASE_H AntiMicroX-antimicrox-2888bf6/src/qtuinputkeymapper.cpp000066400000000000000000000440001377703515000233630ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include //#include #include #include #include #include "messagehandler.h" #include "qtuinputkeymapper.h" QtUInputKeyMapper::QtUInputKeyMapper(QObject *parent) : QtKeyMapperBase(parent) { identifier = "uinput"; populateMappingHashes(); populateCharKeyInformation(); } void QtUInputKeyMapper::populateAlphaHashes() { // Map lowercase alpha keys qtKeyToVirtKeyHash[Qt::Key_A] = KEY_A; qtKeyToVirtKeyHash[Qt::Key_B] = KEY_B; qtKeyToVirtKeyHash[Qt::Key_C] = KEY_C; qtKeyToVirtKeyHash[Qt::Key_D] = KEY_D; qtKeyToVirtKeyHash[Qt::Key_E] = KEY_E; qtKeyToVirtKeyHash[Qt::Key_F] = KEY_F; qtKeyToVirtKeyHash[Qt::Key_G] = KEY_G; qtKeyToVirtKeyHash[Qt::Key_H] = KEY_H; qtKeyToVirtKeyHash[Qt::Key_I] = KEY_I; qtKeyToVirtKeyHash[Qt::Key_J] = KEY_J; qtKeyToVirtKeyHash[Qt::Key_K] = KEY_K; qtKeyToVirtKeyHash[Qt::Key_L] = KEY_L; qtKeyToVirtKeyHash[Qt::Key_M] = KEY_M; qtKeyToVirtKeyHash[Qt::Key_N] = KEY_N; qtKeyToVirtKeyHash[Qt::Key_O] = KEY_O; qtKeyToVirtKeyHash[Qt::Key_P] = KEY_P; qtKeyToVirtKeyHash[Qt::Key_Q] = KEY_Q; qtKeyToVirtKeyHash[Qt::Key_R] = KEY_R; qtKeyToVirtKeyHash[Qt::Key_S] = KEY_S; qtKeyToVirtKeyHash[Qt::Key_T] = KEY_T; qtKeyToVirtKeyHash[Qt::Key_U] = KEY_U; qtKeyToVirtKeyHash[Qt::Key_V] = KEY_V; qtKeyToVirtKeyHash[Qt::Key_W] = KEY_W; qtKeyToVirtKeyHash[Qt::Key_X] = KEY_X; qtKeyToVirtKeyHash[Qt::Key_Y] = KEY_Y; qtKeyToVirtKeyHash[Qt::Key_Z] = KEY_Z; } void QtUInputKeyMapper::populateFKeyHashes() { // Map F1 - F10 for (int i = 0; i <= (KEY_F10 - KEY_F1); i++) qtKeyToVirtKeyHash[Qt::Key_F1 + i] = KEY_F1 + i; // Map F11 and F12 for (int i = 0; i <= (KEY_F12 - KEY_F11); i++) qtKeyToVirtKeyHash[Qt::Key_F11 + i] = KEY_F11 + i; // Map F13 - F24 for (int i = 0; i <= (KEY_F24 - KEY_F13); i++) qtKeyToVirtKeyHash[Qt::Key_F13 + i] = KEY_F13 + i; } void QtUInputKeyMapper::populateNumPadHashes() { // Map Numpad 0 qtKeyToVirtKeyHash[AntKey_KP_0] = KEY_KP0; // Map Numpad 1 - 3 for (int i = 0; i <= (KEY_KP3 - KEY_KP1); i++) qtKeyToVirtKeyHash[AntKey_KP_1 + i] = KEY_KP1 + i; // Map Numpad 4 - 6 for (int i = 0; i <= (KEY_KP6 - KEY_KP4); i++) qtKeyToVirtKeyHash[AntKey_KP_4 + i] = KEY_KP4 + i; // Map Numpad 7 - 9 for (int i = 0; i <= (KEY_KP9 - KEY_KP7); i++) qtKeyToVirtKeyHash[AntKey_KP_7 + i] = KEY_KP7 + i; } void QtUInputKeyMapper::populateSpecialCharHashes() { qtKeyToVirtKeyHash[Qt::Key_QuoteLeft] = KEY_GRAVE; qtKeyToVirtKeyHash[Qt::Key_Minus] = KEY_MINUS; qtKeyToVirtKeyHash[Qt::Key_Equal] = KEY_EQUAL; qtKeyToVirtKeyHash[Qt::Key_BracketLeft] = KEY_LEFTBRACE; qtKeyToVirtKeyHash[Qt::Key_BracketRight] = KEY_RIGHTBRACE; qtKeyToVirtKeyHash[Qt::Key_Semicolon] = KEY_SEMICOLON; qtKeyToVirtKeyHash[Qt::Key_Apostrophe] = KEY_APOSTROPHE; qtKeyToVirtKeyHash[Qt::Key_Comma] = KEY_COMMA; qtKeyToVirtKeyHash[Qt::Key_Period] = KEY_DOT; qtKeyToVirtKeyHash[Qt::Key_Slash] = KEY_SLASH; qtKeyToVirtKeyHash[Qt::Key_Backslash] = KEY_BACKSLASH; } void QtUInputKeyMapper::populateMappingHashes() { if (qtKeyToVirtKeyHash.isEmpty()) { mapMiscKeysQtUinput(qtKeyToVirtKeyHash); mapCursorMovesKeysQtUinput(qtKeyToVirtKeyHash); mapModifiersKeysQtUinput(qtKeyToVirtKeyHash); mapMediaKeysQtUinput(qtKeyToVirtKeyHash); // Map 0-9 keys for (int i = 0; i <= (KEY_9 - KEY_1); i++) qtKeyToVirtKeyHash[Qt::Key_1 + i] = KEY_1 + i; qtKeyToVirtKeyHash[Qt::Key_0] = KEY_0; populateSpecialCharHashes(); populateAlphaHashes(); populateFKeyHashes(); populateNumPadHashes(); // Map custom defined keys qtKeyToVirtKeyHash[AntKey_Shift_R] = KEY_RIGHTSHIFT; qtKeyToVirtKeyHash[AntKey_Control_R] = KEY_RIGHTCTRL; qtKeyToVirtKeyHash[AntKey_Alt_R] = KEY_RIGHTALT; qtKeyToVirtKeyHash[AntKey_KP_Multiply] = KEY_KPASTERISK; mapKeypadKeysQtUinput(qtKeyToVirtKeyHash); // International input method support keys // Misc Functions qtKeyToVirtKeyHash[Qt::Key_Mode_switch] = KEY_SWITCHVIDEOMODE; mapJapanKeysQtUinput(qtKeyToVirtKeyHash); #ifdef XK_KOREAN mapKoreanKeysQtUinput(qtKeyToVirtKeyHash); #endif // XK_KOREAN // Populate other hash. Flip key and value so mapping // goes VK -> Qt Key. QHashIterator iter(qtKeyToVirtKeyHash); while (iter.hasNext()) { iter.next(); virtKeyToQtKeyHash[iter.value()] = iter.key(); } // Override some entries. virtKeyToQtKeyHash[KEY_KP0] = AntKey_KP_0; virtKeyToQtKeyHash[KEY_KP1] = AntKey_KP_1; virtKeyToQtKeyHash[KEY_KP2] = AntKey_KP_2; virtKeyToQtKeyHash[KEY_KP3] = AntKey_KP_3; virtKeyToQtKeyHash[KEY_KP4] = AntKey_KP_4; virtKeyToQtKeyHash[KEY_KP5] = AntKey_KP_5; virtKeyToQtKeyHash[KEY_KP6] = AntKey_KP_6; virtKeyToQtKeyHash[KEY_KP7] = AntKey_KP_7; virtKeyToQtKeyHash[KEY_KP8] = AntKey_KP_8; virtKeyToQtKeyHash[KEY_KP9] = AntKey_KP_9; virtKeyToQtKeyHash[KEY_CALC] = Qt::Key_Launch1; } } void QtUInputKeyMapper::populateCharKeyInformation() { virtkeyToCharKeyInfo.clear(); int unicodeTempValue = 0; int listIndex = 0; charKeyInformation charKeyInfo; charKeyInfo.modifiers = Qt::NoModifier; charKeyInfo.virtualkey = 0; // Map 0-9 keys for (int i = QChar('1').unicode(); i <= QChar('9').unicode(); i++) addVirtualKeyToHash(KEY_1 + i, i, charKeyInfo); addVirtualKeyToHash(KEY_0, QChar('0'), charKeyInfo); addVirtualKeyToHash(KEY_MINUS, QChar('-'), charKeyInfo); addVirtualKeyToHash(KEY_EQUAL, QChar('='), charKeyInfo); QList tempKeys; tempKeys.append(KEY_A); tempKeys.append(KEY_B); tempKeys.append(KEY_C); tempKeys.append(KEY_D); tempKeys.append(KEY_E); tempKeys.append(KEY_F); tempKeys.append(KEY_G); tempKeys.append(KEY_H); tempKeys.append(KEY_I); tempKeys.append(KEY_J); tempKeys.append(KEY_K); tempKeys.append(KEY_L); tempKeys.append(KEY_M); tempKeys.append(KEY_N); tempKeys.append(KEY_O); tempKeys.append(KEY_P); tempKeys.append(KEY_Q); tempKeys.append(KEY_R); tempKeys.append(KEY_S); tempKeys.append(KEY_T); tempKeys.append(KEY_U); tempKeys.append(KEY_V); tempKeys.append(KEY_W); tempKeys.append(KEY_X); tempKeys.append(KEY_Y); tempKeys.append(KEY_Z); unicodeTempValue = QChar('a').unicode(); QListIterator tempIter(tempKeys); while (tempIter.hasNext()) { addVirtualKeyToHash(tempIter.next(), unicodeTempValue, charKeyInfo); unicodeTempValue++; } tempIter.toFront(); charKeyInfo.modifiers = Qt::ShiftModifier; unicodeTempValue = QChar('A').unicode(); while (tempIter.hasNext()) { addVirtualKeyToHash(tempIter.next(), unicodeTempValue, charKeyInfo); unicodeTempValue++; } tempKeys.clear(); charKeyInfo.modifiers = Qt::ShiftModifier; tempKeys.append(QChar('!').unicode()); tempKeys.append(QChar('@').unicode()); tempKeys.append(QChar('#').unicode()); tempKeys.append(QChar('$').unicode()); tempKeys.append(QChar('%').unicode()); tempKeys.append(QChar('^').unicode()); tempKeys.append(QChar('&').unicode()); tempKeys.append(QChar('*').unicode()); tempKeys.append(QChar('(').unicode()); tempKeys.append(QChar(')').unicode()); tempKeys.append(QChar('_').unicode()); tempKeys.append(QChar('+').unicode()); tempIter = QListIterator(tempKeys); listIndex = 0; while (tempIter.hasNext()) { addVirtualKeyToHash(KEY_1 + listIndex, tempIter.next(), charKeyInfo); listIndex++; } tempKeys.clear(); charKeyInfo.modifiers = Qt::NoModifier; addVirtualKeyToHash(KEY_SPACE, QChar(' '), charKeyInfo); addVirtualKeyToHash(KEY_LEFTBRACE, QChar('['), charKeyInfo); addVirtualKeyToHash(KEY_RIGHTBRACE, QChar(']'), charKeyInfo); addVirtualKeyToHash(KEY_BACKSLASH, QChar('\\'), charKeyInfo); addVirtualKeyToHash(KEY_SEMICOLON, QChar(';'), charKeyInfo); addVirtualKeyToHash(KEY_APOSTROPHE, QChar('\''), charKeyInfo); addVirtualKeyToHash(KEY_COMMA, QChar(','), charKeyInfo); addVirtualKeyToHash(KEY_DOT, QChar('.'), charKeyInfo); addVirtualKeyToHash(KEY_SLASH, QChar('/'), charKeyInfo); addVirtualKeyToHash(KEY_LEFTBRACE, QChar('{'), charKeyInfo); addVirtualKeyToHash(KEY_RIGHTBRACE, QChar('}'), charKeyInfo); addVirtualKeyToHash(KEY_BACKSLASH, QChar('|'), charKeyInfo); addVirtualKeyToHash(KEY_SEMICOLON, QChar(':'), charKeyInfo); addVirtualKeyToHash(KEY_APOSTROPHE, QChar('"'), charKeyInfo); addVirtualKeyToHash(KEY_COMMA, QChar('<'), charKeyInfo); addVirtualKeyToHash(KEY_DOT, QChar('>'), charKeyInfo); addVirtualKeyToHash(KEY_SLASH, QChar('?'), charKeyInfo); } void QtUInputKeyMapper::addVirtualKeyToHash(int key, QChar character, charKeyInformation &charKeyInfo) { charKeyInfo.virtualkey = key; virtkeyToCharKeyInfo.insert(character.unicode(), charKeyInfo); } void QtUInputKeyMapper::mapMiscKeysQtUinput(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Escape] = KEY_ESC; qtKeyToVirtKeyHash[Qt::Key_Tab] = KEY_TAB; qtKeyToVirtKeyHash[Qt::Key_Backspace] = KEY_BACKSPACE; qtKeyToVirtKeyHash[Qt::Key_Return] = KEY_ENTER; qtKeyToVirtKeyHash[Qt::Key_Insert] = KEY_INSERT; qtKeyToVirtKeyHash[Qt::Key_Delete] = KEY_DELETE; qtKeyToVirtKeyHash[Qt::Key_Pause] = KEY_PAUSE; qtKeyToVirtKeyHash[Qt::Key_Print] = KEY_PRINT; qtKeyToVirtKeyHash[Qt::Key_Space] = KEY_SPACE; qtKeyToVirtKeyHash[Qt::Key_SysReq] = KEY_SYSRQ; qtKeyToVirtKeyHash[Qt::Key_PowerOff] = KEY_POWER; qtKeyToVirtKeyHash[Qt::Key_Stop] = KEY_STOP; qtKeyToVirtKeyHash[Qt::Key_Refresh] = KEY_REFRESH; qtKeyToVirtKeyHash[Qt::Key_Copy] = KEY_COPY; qtKeyToVirtKeyHash[Qt::Key_Paste] = KEY_PASTE; // qtKeyToVirtKeyHash[Qt::Key_Search] = KEY_FIND; qtKeyToVirtKeyHash[Qt::Key_Cut] = KEY_CUT; qtKeyToVirtKeyHash[Qt::Key_Sleep] = KEY_SLEEP; qtKeyToVirtKeyHash[Qt::Key_Calculator] = KEY_CALC; qtKeyToVirtKeyHash[Qt::Key_Launch0] = KEY_COMPUTER; qtKeyToVirtKeyHash[Qt::Key_Launch1] = KEY_CALC; qtKeyToVirtKeyHash[Qt::Key_Launch2] = KEY_PROG1; qtKeyToVirtKeyHash[Qt::Key_Launch3] = KEY_PROG2; qtKeyToVirtKeyHash[Qt::Key_Launch4] = KEY_PROG3; qtKeyToVirtKeyHash[Qt::Key_Launch5] = KEY_PROG4; qtKeyToVirtKeyHash[Qt::Key_HomePage] = KEY_HOMEPAGE; qtKeyToVirtKeyHash[Qt::Key_LaunchMail] = KEY_MAIL; qtKeyToVirtKeyHash[Qt::Key_Back] = KEY_BACK; qtKeyToVirtKeyHash[Qt::Key_Favorites] = KEY_FAVORITES; qtKeyToVirtKeyHash[Qt::Key_Forward] = KEY_FORWARD; qtKeyToVirtKeyHash[Qt::Key_Suspend] = KEY_SUSPEND; qtKeyToVirtKeyHash[Qt::Key_Close] = KEY_CLOSE; // qtKeyToVirtKeyHash[Qt::Key_Search] = KEY_SEARCH; qtKeyToVirtKeyHash[Qt::Key_Camera] = KEY_CAMERA; qtKeyToVirtKeyHash[Qt::Key_MonBrightnessUp] = KEY_BRIGHTNESSUP; qtKeyToVirtKeyHash[Qt::Key_MonBrightnessDown] = KEY_BRIGHTNESSDOWN; qtKeyToVirtKeyHash[Qt::Key_Send] = KEY_SEND; qtKeyToVirtKeyHash[Qt::Key_Reply] = KEY_REPLY; qtKeyToVirtKeyHash[Qt::Key_Forward] = KEY_FORWARDMAIL; qtKeyToVirtKeyHash[Qt::Key_Save] = KEY_SAVE; qtKeyToVirtKeyHash[Qt::Key_Documents] = KEY_DOCUMENTS; qtKeyToVirtKeyHash[Qt::Key_Battery] = KEY_BATTERY; qtKeyToVirtKeyHash[Qt::Key_Bluetooth] = KEY_BLUETOOTH; qtKeyToVirtKeyHash[Qt::Key_WLAN] = KEY_WLAN; qtKeyToVirtKeyHash[Qt::Key_Cancel] = KEY_CANCEL; qtKeyToVirtKeyHash[Qt::Key_Shop] = KEY_SHOP; qtKeyToVirtKeyHash[Qt::Key_Finance] = KEY_FINANCE; qtKeyToVirtKeyHash[Qt::Key_Question] = KEY_QUESTION; qtKeyToVirtKeyHash[Qt::Key_BassBoost] = KEY_BASSBOOST; } void QtUInputKeyMapper::mapCursorMovesKeysQtUinput(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Home] = KEY_HOME; qtKeyToVirtKeyHash[Qt::Key_End] = KEY_END; qtKeyToVirtKeyHash[Qt::Key_Left] = KEY_LEFT; qtKeyToVirtKeyHash[Qt::Key_Up] = KEY_UP; qtKeyToVirtKeyHash[Qt::Key_Right] = KEY_RIGHT; qtKeyToVirtKeyHash[Qt::Key_Down] = KEY_DOWN; qtKeyToVirtKeyHash[Qt::Key_PageUp] = KEY_PAGEUP; qtKeyToVirtKeyHash[Qt::Key_PageDown] = KEY_PAGEDOWN; } void QtUInputKeyMapper::mapModifiersKeysQtUinput(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Shift] = KEY_LEFTSHIFT; qtKeyToVirtKeyHash[Qt::Key_Control] = KEY_LEFTCTRL; qtKeyToVirtKeyHash[Qt::Key_Alt] = KEY_LEFTALT; qtKeyToVirtKeyHash[Qt::Key_CapsLock] = KEY_CAPSLOCK; qtKeyToVirtKeyHash[Qt::Key_NumLock] = KEY_NUMLOCK; qtKeyToVirtKeyHash[Qt::Key_ScrollLock] = KEY_SCROLLLOCK; qtKeyToVirtKeyHash[Qt::Key_Meta] = KEY_LEFTMETA; qtKeyToVirtKeyHash[AntKey_Meta_R] = KEY_RIGHTMETA; qtKeyToVirtKeyHash[Qt::Key_Menu] = KEY_COMPOSE; qtKeyToVirtKeyHash[Qt::Key_Help] = KEY_HELP; } void QtUInputKeyMapper::mapKeypadKeysQtUinput(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[AntKey_KP_Enter] = KEY_KPENTER; qtKeyToVirtKeyHash[AntKey_KP_Home] = KEY_HOME; qtKeyToVirtKeyHash[AntKey_KP_Left] = KEY_LEFT; qtKeyToVirtKeyHash[AntKey_KP_Up] = KEY_UP; qtKeyToVirtKeyHash[AntKey_KP_Right] = KEY_RIGHT; qtKeyToVirtKeyHash[AntKey_KP_Down] = KEY_DOWN; qtKeyToVirtKeyHash[AntKey_KP_Prior] = KEY_PAGEUP; qtKeyToVirtKeyHash[AntKey_KP_Next] = KEY_PAGEDOWN; qtKeyToVirtKeyHash[AntKey_KP_End] = KEY_END; qtKeyToVirtKeyHash[AntKey_KP_Begin] = KEY_LEFTMETA; qtKeyToVirtKeyHash[AntKey_KP_Insert] = KEY_INSERT; qtKeyToVirtKeyHash[AntKey_KP_Add] = KEY_KPPLUS; qtKeyToVirtKeyHash[AntKey_KP_Subtract] = KEY_KPMINUS; qtKeyToVirtKeyHash[AntKey_KP_Delete] = KEY_KPDOT; qtKeyToVirtKeyHash[AntKey_KP_Decimal] = KEY_KPDOT; qtKeyToVirtKeyHash[AntKey_KP_Divide] = KEY_KPSLASH; qtKeyToVirtKeyHash[AntKey_KP_1] = KEY_KP1; qtKeyToVirtKeyHash[AntKey_KP_2] = KEY_KP2; qtKeyToVirtKeyHash[AntKey_KP_3] = KEY_KP3; qtKeyToVirtKeyHash[AntKey_KP_4] = KEY_KP4; qtKeyToVirtKeyHash[AntKey_KP_5] = KEY_KP5; qtKeyToVirtKeyHash[AntKey_KP_6] = KEY_KP6; qtKeyToVirtKeyHash[AntKey_KP_7] = KEY_KP7; qtKeyToVirtKeyHash[AntKey_KP_8] = KEY_KP8; qtKeyToVirtKeyHash[AntKey_KP_9] = KEY_KP9; qtKeyToVirtKeyHash[AntKey_KP_0] = KEY_KP0; } void QtUInputKeyMapper::mapJapanKeysQtUinput(QHash &qtKeyToVirtKeyHash) { // qtKeyToVirtKeyHash[Qt::Key_Kanji] = XK_Kanji; qtKeyToVirtKeyHash[Qt::Key_Muhenkan] = KEY_MUHENKAN; qtKeyToVirtKeyHash[Qt::Key_Henkan] = KEY_HENKAN; qtKeyToVirtKeyHash[Qt::Key_Romaji] = KEY_RO; qtKeyToVirtKeyHash[Qt::Key_Hiragana] = KEY_HIRAGANA; qtKeyToVirtKeyHash[Qt::Key_Katakana] = KEY_KATAKANA; qtKeyToVirtKeyHash[Qt::Key_Hiragana_Katakana] = KEY_KATAKANAHIRAGANA; // qtKeyToVirtKeyHash[Qt::Key_Zenkaku] = XK_Zenkaku; // qtKeyToVirtKeyHash[Qt::Key_Hankaku] = XK_Hankaku; qtKeyToVirtKeyHash[Qt::Key_Zenkaku_Hankaku] = KEY_ZENKAKUHANKAKU; /* qtKeyToVirtKeyHash[Qt::Key_Touroku] = XK_Touroku; qtKeyToVirtKeyHash[Qt::Key_Massyo] = XK_Massyo; qtKeyToVirtKeyHash[Qt::Key_Kana_Lock] = XK_Kana_Lock; qtKeyToVirtKeyHash[Qt::Key_Kana_Shift] = XK_Kana_Shift; qtKeyToVirtKeyHash[Qt::Key_Eisu_Shift] = XK_Eisu_Shift; qtKeyToVirtKeyHash[Qt::Key_Eisu_toggle] = XK_Eisu_toggle; qtKeyToVirtKeyHash[Qt::Key_Codeinput] = XK_Kanji_Bangou; qtKeyToX11KeySym[Qt::Key_MultipleCandidate] = XK_Zen_Koho; qtKeyToX11KeySym[Qt::Key_PreviousCandidate] = XK_Mae_Koho;*/ } void QtUInputKeyMapper::mapKoreanKeysQtUinput(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Hangul] = KEY_HANGEUL; /* qtKeyToVirtKeyHash[Qt::Key_Hangul_Start] = XK_Hangul_Start; qtKeyToVirtKeyHash[Qt::Key_Hangul_End] = XK_Hangul_End; qtKeyToVirtKeyHash[Qt::Key_Hangul_Hanja] = KEY_HANJA; qtKeyToVirtKeyHash[Qt::Key_Hangul_Jamo] = XK_Hangul_Jamo; qtKeyToVirtKeyHash[Qt::Key_Hangul_Romaja] = XK_Hangul_Romaja; //qtKeyToX11KeySym[Qt::Key_Codeinput] = XK_Hangul_Codeinput; qtKeyToVirtKeyHash[Qt::Key_Hangul_Jeonja] = XK_Hangul_Jeonja; qtKeyToVirtKeyHash[Qt::Key_Hangul_Banja] = XK_Hangul_Banja; qtKeyToVirtKeyHash[Qt::Key_Hangul_PreHanja] = XK_Hangul_PreHanja; qtKeyToVirtKeyHash[Qt::Key_Hangul_PostHanja] = XK_Hangul_PostHanja; //qtKeyToX11KeySym[Qt::Key_SingleCandidate] = XK_Hangul_SingleCandidate; //qtKeyToX11KeySym[Qt::Key_MultipleCandidate] = XK_Hangul_MultipleCandidate; //qtKeyToX11KeySym[Qt::Key_PreviousCandidate] = XK_Hangul_PreviousCandidate; qtKeyToVirtKeyHash[Qt::Key_Hangul_Special] = XK_Hangul_Special; //qtKeyToX11KeySym[Qt::Key_Mode_switch] = XK_Hangul_switch;*/ } void QtUInputKeyMapper::mapMediaKeysQtUinput(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_VolumeDown] = KEY_VOLUMEDOWN; qtKeyToVirtKeyHash[Qt::Key_VolumeMute] = KEY_MUTE; qtKeyToVirtKeyHash[Qt::Key_VolumeUp] = KEY_VOLUMEUP; qtKeyToVirtKeyHash[Qt::Key_MediaPlay] = KEY_PLAYPAUSE; qtKeyToVirtKeyHash[Qt::Key_MediaStop] = KEY_STOPCD; qtKeyToVirtKeyHash[Qt::Key_MediaPrevious] = KEY_PREVIOUSSONG; qtKeyToVirtKeyHash[Qt::Key_MediaNext] = KEY_NEXTSONG; qtKeyToVirtKeyHash[Qt::Key_MediaRecord] = KEY_RECORD; qtKeyToVirtKeyHash[Qt::Key_LaunchMedia] = KEY_MEDIA; } AntiMicroX-antimicrox-2888bf6/src/qtuinputkeymapper.h000066400000000000000000000035571377703515000230440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QTUINPUTKEYMAPPER_H #define QTUINPUTKEYMAPPER_H #include "qtkeymapperbase.h" class QtUInputKeyMapper : public QtKeyMapperBase { Q_OBJECT public: explicit QtUInputKeyMapper(QObject *parent = nullptr); protected: void populateMappingHashes() override; void populateCharKeyInformation() override; void populateAlphaHashes(); void populateFKeyHashes(); void populateNumPadHashes(); void populateSpecialCharHashes(); private: void addVirtualKeyToHash(int key, QChar character, charKeyInformation &charKeyInfo); void mapMiscKeysQtUinput(QHash &qtKeyToVirtKeyHash); void mapCursorMovesKeysQtUinput(QHash &qtKeyToVirtKeyHash); void mapModifiersKeysQtUinput(QHash &qtKeyToVirtKeyHash); void mapKeypadKeysQtUinput(QHash &qtKeyToVirtKeyHash); void mapJapanKeysQtUinput(QHash &qtKeyToVirtKeyHash); void mapKoreanKeysQtUinput(QHash &qtKeyToVirtKeyHash); void mapMediaKeysQtUinput(QHash &qtKeyToVirtKeyHash); }; #endif // QTUINPUTKEYMAPPER_H AntiMicroX-antimicrox-2888bf6/src/qtvmultikeymapper.cpp000066400000000000000000000162151377703515000233660ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "qtvmultikeymapper.h" QtVMultiKeyMapper::QtVMultiKeyMapper(QObject *parent) : QtKeyMapperBase(parent) { identifier = "vmulti"; populateMappingHashes(); } void QtVMultiKeyMapper::populateMappingHashes() { if (qtKeyToVirtualKey.isEmpty()) { // Map A - Z keys for (int i = 0; i <= (Qt::Key_Z - Qt::Key_A); i++) { qtKeyToVirtualKey[Qt::Key_A + i] = 0x04 + i; } // Map 1 - 9 numeric keys for (int i = 0; i <= (Qt::Key_9 - Qt::Key_1); i++) { qtKeyToVirtualKey[Qt::Key_1 + i] = 0x1E + i; } // Map 0 numeric key qtKeyToVirtualKey[Qt::Key_0] = 0x27; qtKeyToVirtualKey[Qt::Key_Return] = 0x28; qtKeyToVirtualKey[Qt::Key_Escape] = 0x29; qtKeyToVirtualKey[Qt::Key_Backspace] = 0x2A; qtKeyToVirtualKey[Qt::Key_Tab] = 0x2B; qtKeyToVirtualKey[Qt::Key_Space] = 0x2C; qtKeyToVirtualKey[Qt::Key_Minus] = 0x2D; qtKeyToVirtualKey[Qt::Key_Equal] = 0x2E; qtKeyToVirtualKey[Qt::Key_BracketLeft] = 0x2F; qtKeyToVirtualKey[Qt::Key_BracketRight] = 0x30; qtKeyToVirtualKey[Qt::Key_Backslash] = 0x31; qtKeyToVirtualKey[Qt::Key_NumberSign] = 0x32; qtKeyToVirtualKey[Qt::Key_Semicolon] = 0x33; qtKeyToVirtualKey[Qt::Key_Apostrophe] = 0x34; qtKeyToVirtualKey[Qt::Key_QuoteLeft] = 0x35; qtKeyToVirtualKey[Qt::Key_Comma] = 0x36; qtKeyToVirtualKey[Qt::Key_Period] = 0x37; qtKeyToVirtualKey[Qt::Key_Slash] = 0x38; qtKeyToVirtualKey[Qt::Key_CapsLock] = 0x39; // Map F1 - F12 keys for (int i = 0; i <= (Qt::Key_F12 - Qt::Key_F1); i++) { qtKeyToVirtualKey[Qt::Key_F1 + i] = 0x3A + i; } qtKeyToVirtualKey[Qt::Key_Print] = 0x46; qtKeyToVirtualKey[Qt::Key_ScrollLock] = 0x47; qtKeyToVirtualKey[Qt::Key_Pause] = 0x48; qtKeyToVirtualKey[Qt::Key_Insert] = 0x49; qtKeyToVirtualKey[Qt::Key_Home] = 0x4A; qtKeyToVirtualKey[Qt::Key_PageUp] = 0x4B; qtKeyToVirtualKey[Qt::Key_Delete] = 0x4C; qtKeyToVirtualKey[Qt::Key_End] = 0x4D; qtKeyToVirtualKey[Qt::Key_PageDown] = 0x4E; qtKeyToVirtualKey[Qt::Key_Right] = 0x4F; qtKeyToVirtualKey[Qt::Key_Left] = 0x50; qtKeyToVirtualKey[Qt::Key_Down] = 0x51; qtKeyToVirtualKey[Qt::Key_Up] = 0x52; qtKeyToVirtualKey[Qt::Key_NumLock] = 0x53; qtKeyToVirtualKey[AntKey_KP_Divide] = 0x54; qtKeyToVirtualKey[AntKey_KP_Multiply] = 0x55; qtKeyToVirtualKey[AntKey_KP_Subtract] = 0x56; qtKeyToVirtualKey[AntKey_KP_Add] = 0x57; qtKeyToVirtualKey[Qt::Key_Enter] = 0x58; // Map Numpad 1 - 9 keys for (int i = 0; i <= (AntKey_KP_9 - AntKey_KP_1); i++) { qtKeyToVirtualKey[AntKey_KP_1 + i] = 0x59 + i; } // Map Numpad 0 key qtKeyToVirtualKey[AntKey_KP_0] = 0x62; qtKeyToVirtualKey[AntKey_KP_Decimal] = 0x63; // qtKeyToVirtualKey[Qt::Key_Backslash] = 0x64; qtKeyToVirtualKey[Qt::Key_ApplicationLeft] = 0x65; qtKeyToVirtualKey[Qt::Key_PowerOff] = 0x66; // qtKeyToVirtualKey[] = 0x67; for (int i = 0; i <= (Qt::Key_F24 - Qt::Key_F13); i++) { qtKeyToVirtualKey[Qt::Key_F13 + i] = 0x68 + i; } qtKeyToVirtualKey[Qt::Key_Execute] = 0x74; qtKeyToVirtualKey[Qt::Key_Help] = 0x75; qtKeyToVirtualKey[Qt::Key_Menu] = 0x76; qtKeyToVirtualKey[Qt::Key_Select] = 0x77; qtKeyToVirtualKey[Qt::Key_Stop] = 0x78; // qtKeyToVirtualKey[] = 0x79; qtKeyToVirtualKey[Qt::Key_Undo] = 0x7A; qtKeyToVirtualKey[Qt::Key_Cut] = 0x7B; qtKeyToVirtualKey[Qt::Key_Copy] = 0x7C; qtKeyToVirtualKey[Qt::Key_Paste] = 0x7D; qtKeyToVirtualKey[Qt::Key_Find] = 0x7E; qtKeyToVirtualKey[Qt::Key_VolumeMute] = 0x7F; qtKeyToVirtualKey[Qt::Key_VolumeUp] = 0x80; qtKeyToVirtualKey[Qt::Key_VolumeDown] = 0x81; // qtKeyToVirtualKey[] = 0x82; // qtKeyToVirtualKey[] = 0x83; // qtKeyToVirtualKey[] = 0x84; // qtKeyToVirtualKey[] = 0x85; // International Keys? // qtKeyToVirtualKey[] = 0x87; // qtKeyToVirtualKey[] = 0x88; // qtKeyToVirtualKey[] = 0x89; // qtKeyToVirtualKey[] = 0x8A; // qtKeyToVirtualKey[] = 0x8B; // qtKeyToVirtualKey[] = 0x8C; // qtKeyToVirtualKey[] = 0x8D; // qtKeyToVirtualKey[] = 0x8E; // qtKeyToVirtualKey[] = 0x8F; qtKeyToVirtualKey[Qt::Key_Control] = 0xE0; qtKeyToVirtualKey[Qt::Key_Shift] = 0xE1; qtKeyToVirtualKey[Qt::Key_Alt] = 0xE2; qtKeyToVirtualKey[Qt::Key_Meta] = 0xE3; qtKeyToVirtualKey[AntKey_Control_R] = 0xE4; qtKeyToVirtualKey[AntKey_Shift_R] = 0xE5; qtKeyToVirtualKey[AntKey_Meta_R] = 0xE7; qtKeyToVirtualKey[Qt::Key_MediaPause] = 0xB1 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_MediaNext] = 0xB5 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_MediaPrevious] = 0xB6 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_MediaStop] = 0xB7 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_HomePage] = 0x189 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_Launch0] = 0x194 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_Calculator] = 0x192 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_Favorites] = 0x22a | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_Search] = 0x221 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_Stop] = 0x226 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_Back] = 0x224 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_LaunchMedia] = 0x87 | consumerUsagePagePrefix; qtKeyToVirtualKey[Qt::Key_LaunchMail] = 0x18a | consumerUsagePagePrefix; // Populate other hash. Flip key and value so mapping // goes VK -> Qt Key. QHashIterator iter(qtKeyToVirtualKey); while (iter.hasNext()) { iter.next(); virtualKeyToQtKey[iter.value()] = iter.key(); } } } void QtVMultiKeyMapper::populateCharKeyInformation() {} AntiMicroX-antimicrox-2888bf6/src/qtvmultikeymapper.h000066400000000000000000000023551377703515000230330ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QTVMULTIKEYMAPPER_H #define QTVMULTIKEYMAPPER_H #include "qtkeymapperbase.h" class QtVMultiKeyMapper : public QtKeyMapperBase { public: explicit QtVMultiKeyMapper(QObject *parent = nullptr); static const int consumerUsagePagePrefix = 0x12000; protected: void populateMappingHashes() override; void populateCharKeyInformation() override; }; #endif // QTVMULTIKEYMAPPER_H AntiMicroX-antimicrox-2888bf6/src/qtwinkeymapper.cpp000066400000000000000000000376031377703515000226470ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include //#include #include #include "qtwinkeymapper.h" #include "winextras.h" static QHash initDynamicKeyMapping() { QHash temp; temp[VK_OEM_1] = 0; // temp[VK_OEM_PLUS] = 0; // temp[VK_OEM_COMMA] = 0; // temp[VK_OEM_MINUS] = 0; // temp[VK_OEM_PERIOD] = 0; temp[VK_OEM_2] = 0; temp[VK_OEM_3] = 0; temp[VK_OEM_4] = 0; temp[VK_OEM_5] = 0; temp[VK_OEM_6] = 0; temp[VK_OEM_7] = 0; temp[VK_OEM_8] = 0; temp[VK_OEM_102] = 0; return temp; } static QHash intCharToQtKey() { QHash temp; temp.insert(QString('!'), Qt::Key_Exclam); temp.insert(QString('"'), Qt::Key_QuoteDbl); temp.insert(QString('#'), Qt::Key_NumberSign); temp.insert(QString('$'), Qt::Key_Dollar); temp.insert(QString('\''), Qt::Key_Apostrophe); temp.insert(QString('('), Qt::Key_ParenLeft); temp.insert(QString(')'), Qt::Key_ParenRight); temp.insert(QString('*'), Qt::Key_Asterisk); temp.insert(QString('+'), Qt::Key_Plus); temp.insert(QString(','), Qt::Key_Comma); temp.insert(QString('-'), Qt::Key_Minus); temp.insert(QString('.'), Qt::Key_Period); temp.insert(QString('/'), Qt::Key_Slash); temp.insert(QString(':'), Qt::Key_Colon); temp.insert(QString(';'), Qt::Key_Semicolon); temp.insert(QString('<'), Qt::Key_Less); temp.insert(QString('='), Qt::Key_Equal); temp.insert(QString('>'), Qt::Key_Greater); temp.insert(QString('@'), Qt::Key_At); temp.insert(QString('['), Qt::Key_BracketLeft); temp.insert(QString('\\'), Qt::Key_Backslash); temp.insert(QString(']'), Qt::Key_BracketRight); temp.insert(QString('^'), Qt::Key_AsciiCircum); temp.insert(QString('_'), Qt::Key_Underscore); temp.insert(QString('`'), Qt::Key_QuoteLeft); temp.insert(QString('{'), Qt::Key_BraceLeft); temp.insert(QString('}'), Qt::Key_BraceRight); temp.insert(QString::fromUtf8("\u00A1"), Qt::Key_exclamdown); temp.insert(QString('~'), Qt::Key_AsciiTilde); // temp.insert(QString::fromUtf8("\u20A0"), Qt::Key_) return temp; } static QHash initDeadKeyToQtKey() { QHash temp; // temp.insert(QString('`'), Qt::Key_Dead_Grave); // temp.insert(QString('\''), Qt::Key_Dead_Acute); temp.insert(QString::fromUtf8("\u00B4"), Qt::Key_Dead_Grave); // temp.insert(QString('^'), Qt::Key_Dead_Circumflex); // temp.insert(QString('~'), Qt::Key_Dead_Tilde); temp.insert(QString::fromUtf8("\u02DC"), Qt::Key_Dead_Tilde); temp.insert(QString::fromUtf8("\u00AF"), Qt::Key_Dead_Macron); temp.insert(QString::fromUtf8("\u02D8"), Qt::Key_Dead_Breve); temp.insert(QString::fromUtf8("\u02D9"), Qt::Key_Dead_Abovedot); // temp.insert(QString('"'), Qt::Key_Dead_Diaeresis); temp.insert(QString::fromUtf8("\u00A8"), Qt::Key_Dead_Diaeresis); temp.insert(QString::fromUtf8("\u02DA"), Qt::Key_Dead_Abovering); temp.insert(QString::fromUtf8("\u02DD"), Qt::Key_Dead_Doubleacute); temp.insert(QString::fromUtf8("\u02C7"), Qt::Key_Dead_Caron); // temp.insert(QString(','), Qt::Key_Dead_Cedilla); temp.insert(QString::fromUtf8("\u00B8"), Qt::Key_Dead_Cedilla); temp.insert(QString::fromUtf8("\u02DB"), Qt::Key_Dead_Ogonek); temp.insert(QString::fromUtf8("\u037A"), Qt::Key_Dead_Iota); temp.insert(QString::fromUtf8("\u309B"), Qt::Key_Dead_Voiced_Sound); temp.insert(QString::fromUtf8("\u309C"), Qt::Key_Dead_Semivoiced_Sound); return temp; } static QHash dynamicOEMToQtKeyHash = initDynamicKeyMapping(); static QHash charToQtKeyHash = intCharToQtKey(); static QHash deadKeyToQtKeyHash = initDeadKeyToQtKey(); QtWinKeyMapper::QtWinKeyMapper(QObject *parent) : QtKeyMapperBase(parent) { identifier = "sendinput"; populateMappingHashes(); populateCharKeyInformation(); } void QtWinKeyMapper::populateMappingHashes() { if (qtKeyToVirtualKey.isEmpty()) { qtKeyToVirtualKey[Qt::Key_Cancel] = VK_CANCEL; qtKeyToVirtualKey[Qt::Key_Backspace] = VK_BACK; qtKeyToVirtualKey[Qt::Key_Tab] = VK_TAB; qtKeyToVirtualKey[Qt::Key_Clear] = VK_CLEAR; qtKeyToVirtualKey[Qt::Key_Return] = VK_RETURN; qtKeyToVirtualKey[Qt::Key_Enter] = VK_RETURN; // qtKeyToWinVirtualKey[Qt::Key_Shift] = VK_SHIFT; // qtKeyToWinVirtualKey[Qt::Key_Control] = VK_CONTROL; // qtKeyToWinVirtualKey[Qt::Key_Alt] = VK_MENU; qtKeyToVirtualKey[Qt::Key_Pause] = VK_PAUSE; qtKeyToVirtualKey[Qt::Key_CapsLock] = VK_CAPITAL; qtKeyToVirtualKey[Qt::Key_Escape] = VK_ESCAPE; qtKeyToVirtualKey[Qt::Key_Mode_switch] = VK_MODECHANGE; qtKeyToVirtualKey[Qt::Key_Space] = VK_SPACE; qtKeyToVirtualKey[Qt::Key_PageUp] = VK_PRIOR; qtKeyToVirtualKey[Qt::Key_PageDown] = VK_NEXT; qtKeyToVirtualKey[Qt::Key_End] = VK_END; qtKeyToVirtualKey[Qt::Key_Home] = VK_HOME; qtKeyToVirtualKey[Qt::Key_Left] = VK_LEFT; qtKeyToVirtualKey[Qt::Key_Up] = VK_UP; qtKeyToVirtualKey[Qt::Key_Right] = VK_RIGHT; qtKeyToVirtualKey[Qt::Key_Down] = VK_DOWN; qtKeyToVirtualKey[Qt::Key_Select] = VK_SELECT; qtKeyToVirtualKey[Qt::Key_Printer] = VK_PRINT; qtKeyToVirtualKey[Qt::Key_Execute] = VK_EXECUTE; qtKeyToVirtualKey[Qt::Key_Print] = VK_SNAPSHOT; qtKeyToVirtualKey[Qt::Key_Insert] = VK_INSERT; qtKeyToVirtualKey[Qt::Key_Delete] = VK_DELETE; qtKeyToVirtualKey[Qt::Key_Help] = VK_HELP; qtKeyToVirtualKey[Qt::Key_Meta] = VK_LWIN; // qtKeyToWinVirtualKey[Qt::Key_Meta] = VK_RWIN; qtKeyToVirtualKey[Qt::Key_Menu] = VK_APPS; qtKeyToVirtualKey[Qt::Key_Sleep] = VK_SLEEP; qtKeyToVirtualKey[AntKey_KP_Multiply] = VK_MULTIPLY; // qtKeyToVirtualKey[Qt::Key_Asterisk] = VK_MULTIPLY; qtKeyToVirtualKey[AntKey_KP_Add] = VK_ADD; // qtKeyToVirtualKey[Qt::Key_Comma] = VK_SEPARATOR; qtKeyToVirtualKey[AntKey_KP_Subtract] = VK_SUBTRACT; qtKeyToVirtualKey[AntKey_KP_Decimal] = VK_DECIMAL; qtKeyToVirtualKey[AntKey_KP_Divide] = VK_DIVIDE; qtKeyToVirtualKey[Qt::Key_NumLock] = VK_NUMLOCK; qtKeyToVirtualKey[Qt::Key_ScrollLock] = VK_SCROLL; qtKeyToVirtualKey[Qt::Key_Massyo] = VK_OEM_FJ_MASSHOU; qtKeyToVirtualKey[Qt::Key_Touroku] = VK_OEM_FJ_TOUROKU; qtKeyToVirtualKey[Qt::Key_Shift] = VK_LSHIFT; // qtKeyToWinVirtualKey[Qt::Key_Shift] = VK_RSHIFT; qtKeyToVirtualKey[Qt::Key_Control] = VK_LCONTROL; // qtKeyToWinVirtualKey[Qt::Key_Control] = VK_RCONTROL; qtKeyToVirtualKey[Qt::Key_Alt] = VK_LMENU; // qtKeyToWinVirtualKey[Qt::Key_Alt] = VK_RMENU; qtKeyToVirtualKey[Qt::Key_Back] = VK_BROWSER_BACK; qtKeyToVirtualKey[Qt::Key_Forward] = VK_BROWSER_FORWARD; qtKeyToVirtualKey[Qt::Key_Refresh] = VK_BROWSER_REFRESH; qtKeyToVirtualKey[Qt::Key_Stop] = VK_BROWSER_STOP; qtKeyToVirtualKey[Qt::Key_Search] = VK_BROWSER_SEARCH; qtKeyToVirtualKey[Qt::Key_Favorites] = VK_BROWSER_FAVORITES; qtKeyToVirtualKey[Qt::Key_HomePage] = VK_BROWSER_HOME; qtKeyToVirtualKey[Qt::Key_VolumeMute] = VK_VOLUME_MUTE; qtKeyToVirtualKey[Qt::Key_VolumeDown] = VK_VOLUME_DOWN; qtKeyToVirtualKey[Qt::Key_VolumeUp] = VK_VOLUME_UP; qtKeyToVirtualKey[Qt::Key_MediaNext] = VK_MEDIA_NEXT_TRACK; qtKeyToVirtualKey[Qt::Key_MediaPrevious] = VK_MEDIA_PREV_TRACK; qtKeyToVirtualKey[Qt::Key_MediaStop] = VK_MEDIA_STOP; qtKeyToVirtualKey[Qt::Key_MediaPlay] = VK_MEDIA_PLAY_PAUSE; qtKeyToVirtualKey[Qt::Key_LaunchMail] = VK_LAUNCH_MAIL; qtKeyToVirtualKey[Qt::Key_LaunchMedia] = VK_LAUNCH_MEDIA_SELECT; qtKeyToVirtualKey[Qt::Key_Launch0] = VK_LAUNCH_APP1; qtKeyToVirtualKey[Qt::Key_Launch1] = VK_LAUNCH_APP2; qtKeyToVirtualKey[Qt::Key_Kanji] = VK_KANJI; // The following VK_OEM_* keys are consistent across all // keyboard layouts. qtKeyToVirtualKey[Qt::Key_Equal] = VK_OEM_PLUS; qtKeyToVirtualKey[Qt::Key_Minus] = VK_OEM_MINUS; qtKeyToVirtualKey[Qt::Key_Period] = VK_OEM_PERIOD; qtKeyToVirtualKey[Qt::Key_Comma] = VK_OEM_COMMA; /*qtKeyToVirtualKey[Qt::Key_Semicolon] = VK_OEM_1; qtKeyToVirtualKey[Qt::Key_Slash] = VK_OEM_2; qtKeyToVirtualKey[Qt::Key_Equal] = VK_OEM_PLUS; qtKeyToVirtualKey[Qt::Key_Minus] = VK_OEM_MINUS; qtKeyToVirtualKey[Qt::Key_Period] = VK_OEM_PERIOD; qtKeyToVirtualKey[Qt::Key_QuoteLeft] = VK_OEM_3; qtKeyToVirtualKey[Qt::Key_BracketLeft] = VK_OEM_4; qtKeyToVirtualKey[Qt::Key_Backslash] = VK_OEM_5; qtKeyToVirtualKey[Qt::Key_BracketRight] = VK_OEM_6; qtKeyToVirtualKey[Qt::Key_Apostrophe] = VK_OEM_7;*/ qtKeyToVirtualKey[Qt::Key_Play] = VK_PLAY; qtKeyToVirtualKey[Qt::Key_Zoom] = VK_ZOOM; // qtKeyToWinVirtualKey[Qt::Key_Clear] = VK_OEM_CLEAR; // Map 0-9 ASCII codes for (int i = 0; i <= (0x39 - 0x30); i++) { qtKeyToVirtualKey[Qt::Key_0 + i] = 0x30 + i; } // Map A-Z ASCII codes for (int i = 0; i <= (0x5a - 0x41); i++) { qtKeyToVirtualKey[Qt::Key_A + i] = 0x41 + i; } // Map function keys for (int i = 0; i <= (VK_F24 - VK_F1); i++) { qtKeyToVirtualKey[Qt::Key_F1 + i] = VK_F1 + i; } // Map numpad keys for (int i = 0; i <= (VK_NUMPAD9 - VK_NUMPAD0); i++) { qtKeyToVirtualKey[AntKey_KP_0 + i] = VK_NUMPAD0 + i; } // Map custom keys qtKeyToVirtualKey[AntKey_Alt_R] = VK_RMENU; qtKeyToVirtualKey[AntKey_Meta_R] = VK_RWIN; qtKeyToVirtualKey[AntKey_Shift_R] = VK_RSHIFT; qtKeyToVirtualKey[AntKey_Control_R] = VK_RCONTROL; // Go through VK_OEM_* values and find the appropriate association // with a key defined in Qt. Association is decided based on char // returned from Windows for the VK_OEM_* key. QHashIterator iterDynamic(dynamicOEMToQtKeyHash); while (iterDynamic.hasNext()) { iterDynamic.next(); byte ks[256]; char cbuf[2] = {'\0', '\0'}; GetKeyboardState(ks); unsigned int oemkey = iterDynamic.key(); unsigned int scancode = MapVirtualKey(oemkey, 0); int charlength = ToAscii(oemkey, scancode, ks, (WORD *)cbuf, 0); if (charlength < 0) { charlength = ToAscii(VK_SPACE, scancode, ks, (WORD *)cbuf, 0); QString temp = QString::fromUtf8(cbuf); if (temp.length() > 0) { QHashIterator tempiter(charToQtKeyHash); while (tempiter.hasNext()) { tempiter.next(); QString currentChar = tempiter.key(); if (currentChar == temp) { dynamicOEMToQtKeyHash[oemkey] = tempiter.value(); tempiter.toBack(); } } } } else if (charlength == 1) { QString temp = QString::fromUtf8(cbuf); QHashIterator tempiter(charToQtKeyHash); while (tempiter.hasNext()) { tempiter.next(); QString currentChar = tempiter.key(); if (currentChar == temp) { dynamicOEMToQtKeyHash[oemkey] = tempiter.value(); tempiter.toBack(); } } } } // Populate hash with values found for the VK_OEM_* keys. // Values will likely be different across various keyboard // layouts. iterDynamic = QHashIterator(dynamicOEMToQtKeyHash); while (iterDynamic.hasNext()) { iterDynamic.next(); unsigned int tempvalue = iterDynamic.value(); if (tempvalue != 0 && !qtKeyToVirtualKey.contains(tempvalue)) { qtKeyToVirtualKey.insert(tempvalue, iterDynamic.key()); } } // Populate other hash. Flip key and value so mapping // goes VK -> Qt Key. QHashIterator iter(qtKeyToVirtualKey); while (iter.hasNext()) { iter.next(); virtualKeyToQtKey[iter.value()] = iter.key(); } // Override current item for VK_RETURN virtualKeyToQtKey[VK_RETURN] = Qt::Key_Return; // Insert more aliases that would have resulted in // overwrites in other hash. virtualKeyToQtKey[VK_SHIFT] = Qt::Key_Shift; virtualKeyToQtKey[VK_CONTROL] = Qt::Key_Control; virtualKeyToQtKey[VK_MENU] = Qt::Key_Alt; } } int QtWinKeyMapper::returnQtKey(int key, int scancode) { int tempkey = virtualKeyToQtKey.value(key); int extended = scancode & WinExtras::EXTENDED_FLAG; if (key == VK_RETURN && extended) { tempkey = Qt::Key_Enter; } return tempkey; } void QtWinKeyMapper::populateCharKeyInformation() { virtualkeyToCharKeyInformation.clear(); unsigned int total = 0; // BYTE ks[256]; // GetKeyboardState(ks); /*for (int x=0; x <= 255; x++) { if (ks[x] != 0) { qDebug() << "TEST: " << QString::number(x) << " | " << QString::number(ks[x]); } } */ for (int i = VK_SPACE; i <= VK_OEM_CLEAR; i++) { unsigned int scancode = MapVirtualKey(i, 0); for (int j = 0; j <= 3; j++) { WCHAR cbuf[256]; BYTE tempks[256]; memset(tempks, 0, sizeof(tempks)); Qt::KeyboardModifiers dicis; if (j >= 2) { dicis |= Qt::MetaModifier; tempks[VK_LWIN] = 1 << 7; // tempks[VK_RWIN] = 1 << 7; } if (j == 1 || j == 3) { dicis |= Qt::ShiftModifier; tempks[VK_LSHIFT] = 1 << 7; tempks[VK_SHIFT] = 1 << 7; // qDebug() << "NEVER ME: "; } int charlength = ToUnicode(i, scancode, tempks, cbuf, 255, 0); if (charlength == 1 || charlength < 0) { QString temp = QString::fromWCharArray(cbuf); if (temp.size() > 0) { QChar tempchar(temp.at(0)); charKeyInformation tempinfo; tempinfo.modifiers = dicis; tempinfo.virtualkey = i; if (!virtualkeyToCharKeyInformation.contains(tempchar.unicode())) { virtualkeyToCharKeyInformation.insert(tempchar.unicode(), tempinfo); total++; } } } } } qDebug() << "TOTAL: " << total; } AntiMicroX-antimicrox-2888bf6/src/qtwinkeymapper.h000066400000000000000000000023171377703515000223060ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QTWINKEYMAPPER_H #define QTWINKEYMAPPER_H #include "qtkeymapperbase.h" class QtWinKeyMapper : public QtKeyMapperBase { Q_OBJECT public: explicit QtWinKeyMapper(QObject *parent = nullptr); virtual int returnQtKey(int key, int scancode = 0) override; protected: void populateMappingHashes() override; void populateCharKeyInformation() override; }; #endif // QTWINKEYMAPPER_H AntiMicroX-antimicrox-2888bf6/src/qtx11keymapper.cpp000066400000000000000000000417111377703515000224560ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define XK_MISCELLANY #define XK_LATIN1 #define XK_KOREAN #define XK_XKB_KEYS #include "qtx11keymapper.h" #include #include #include #include #include #include #include #include #include #include "messagehandler.h" #include "x11extras.h" QtX11KeyMapper::QtX11KeyMapper(QObject *parent) : QtKeyMapperBase(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); identifier = "xtest"; populateMappingHashes(); populateCharKeyInformation(); } /* * The following mappings are mainly taken from qkeymapper_x11.cpp. * There are portions of the mapping that are customized to work around * some of the ambiguity introduced with some Qt keys * (XK_Alt_L and XK_Alt_R become Qt::Key_Alt in Qt). */ void QtX11KeyMapper::populateMappingHashes() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (qtKeyToVirtKeyHash.isEmpty()) { mapMiscKeysQtX11(qtKeyToVirtKeyHash); mapCursorMovesKeysQtX11(qtKeyToVirtKeyHash); mapModifiersKeysQtX11(qtKeyToVirtKeyHash); mapAdditionalKeysQtX11(qtKeyToVirtKeyHash); mapKeypadKeysQtX11(qtKeyToVirtKeyHash); mapInternationKeysQtX11(qtKeyToVirtKeyHash); // Misc Functions qtKeyToVirtKeyHash[Qt::Key_Mode_switch] = XK_Mode_switch; // qtKeyToX11KeySym[Qt::Key_Mode_switch] = XK_script_switch; mapJapanKeysQtX11(qtKeyToVirtKeyHash); #ifdef XK_KOREAN mapKoreanKeysQtX11(qtKeyToVirtKeyHash); #endif // XK_KOREAN mapDeadKeysQtX11(qtKeyToVirtKeyHash); mapBrowseKeysQtX11(qtKeyToVirtKeyHash); mapMediaKeysQtX11(qtKeyToVirtKeyHash); mapLaunchKeysQtX11(qtKeyToVirtKeyHash); // Map initial ASCII keys for (int i = 0; i <= (XK_at - XK_space); i++) qtKeyToVirtKeyHash[Qt::Key_Space + i] = XK_space + i; // Map lowercase alpha keys for (int i = 0; i <= (XK_z - XK_a); i++) qtKeyToVirtKeyHash[Qt::Key_A + i] = XK_a + i; // Map [ to ` ASCII keys for (int i = 0; i <= (XK_grave - XK_bracketleft); i++) qtKeyToVirtKeyHash[Qt::Key_BracketLeft + i] = XK_bracketleft + i; // Map { to ~ ASCII keys for (int i = 0; i <= (XK_asciitilde - XK_braceleft); i++) qtKeyToVirtKeyHash[Qt::Key_BraceLeft + i] = XK_braceleft + i; // Map function keys for (int i = 0; i <= (XK_F35 - XK_F1); i++) qtKeyToVirtKeyHash[Qt::Key_F1 + i] = XK_F1 + i; // Misc // qtKeyToVirtKeyHash[Qt::KeyBri] // Map custom defined keys qtKeyToVirtKeyHash[AntKey_Shift_R] = XK_Shift_R; qtKeyToVirtKeyHash[AntKey_Control_R] = XK_Control_R; // qtKeyToX11KeySym[AntKey_Shift_Lock] = XK_Shift_Lock; // qtKeyToVirtKeyHash[AntKey_Meta_R] = XK_Meta_R; qtKeyToVirtKeyHash[AntKey_Alt_R] = XK_Alt_R; qtKeyToVirtKeyHash[AntKey_KP_Multiply] = XK_KP_Multiply; // Map 0 to 9 for (int i = 0; i <= (XK_KP_9 - XK_KP_0); i++) qtKeyToVirtKeyHash[AntKey_KP_0 + i] = XK_KP_0 + i; // Map lower-case latin characters to their capital equivalents for (int i = 0; i <= (XK_odiaeresis - XK_agrave); i++) qtKeyToVirtKeyHash[Qt::Key_Agrave + i] = XK_agrave + i; for (int i = 0; i <= (XK_thorn - XK_oslash); i++) qtKeyToVirtKeyHash[Qt::Key_Ooblique + i] = XK_oslash + i; QHashIterator iter(qtKeyToVirtKeyHash); while (iter.hasNext()) { iter.next(); virtKeyToQtKeyHash[iter.value()] = iter.key(); } } } void QtX11KeyMapper::populateCharKeyInformation() { qInstallMessageHandler(MessageHandler::myMessageOutput); virtkeyToCharKeyInfo.clear(); Display *display = X11Extras::getInstance()->display(); int total = 0; for (int i = 8; i <= 255; i++) { for (int j = 0; j <= 3; j++) { Qt::KeyboardModifiers dicis; if (j >= 2) dicis |= Qt::MetaModifier; if ((j == 1) || (j == 3)) dicis |= Qt::ShiftModifier; int testsym = XkbKeycodeToKeysym(display, i, (dicis & Qt::MetaModifier) ? 1 : 0, (dicis & Qt::ShiftModifier) ? 1 : 0); if (testsym != NoSymbol) { XKeyPressedEvent tempevent; tempevent.keycode = i; tempevent.type = KeyPress; tempevent.display = display; tempevent.state = 0; if (dicis & Qt::ShiftModifier) tempevent.state |= ShiftMask; if (dicis & Qt::MetaModifier) tempevent.state |= Mod1Mask; char returnstring[256]; memset(returnstring, 0, sizeof(returnstring)); int bitestoreturn = sizeof(returnstring) - 1; int numchars = XLookupString(&tempevent, returnstring, bitestoreturn, nullptr, nullptr); if (numchars > 0) { returnstring[numchars] = '\0'; QString tempstring = QString::fromUtf8(returnstring); if (tempstring.length() == 1) { QChar tempchar(tempstring.at(0)); charKeyInformation testKeyInformation; testKeyInformation.modifiers = dicis; testKeyInformation.virtualkey = testsym; if (!virtkeyToCharKeyInfo.contains(tempchar.unicode())) { virtkeyToCharKeyInfo.insert(tempchar.unicode(), testKeyInformation); total++; } } } } } } qDebug() << "TOTAL: " << total; } void QtX11KeyMapper::mapMiscKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Escape] = XK_Escape; qtKeyToVirtKeyHash[Qt::Key_Tab] = XK_Tab; qtKeyToVirtKeyHash[Qt::Key_Backtab] = XK_ISO_Left_Tab; qtKeyToVirtKeyHash[Qt::Key_Backspace] = XK_BackSpace; qtKeyToVirtKeyHash[Qt::Key_Return] = XK_Return; qtKeyToVirtKeyHash[Qt::Key_Insert] = XK_Insert; qtKeyToVirtKeyHash[Qt::Key_Delete] = XK_Delete; // qtKeyToX11KeySym[Qt::Key_Delete] = XK_Clear; qtKeyToVirtKeyHash[Qt::Key_Pause] = XK_Pause; qtKeyToVirtKeyHash[Qt::Key_Print] = XK_Print; } void QtX11KeyMapper::mapCursorMovesKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Home] = XK_Home; qtKeyToVirtKeyHash[Qt::Key_End] = XK_End; qtKeyToVirtKeyHash[Qt::Key_Left] = XK_Left; qtKeyToVirtKeyHash[Qt::Key_Up] = XK_Up; qtKeyToVirtKeyHash[Qt::Key_Right] = XK_Right; qtKeyToVirtKeyHash[Qt::Key_Down] = XK_Down; qtKeyToVirtKeyHash[Qt::Key_PageUp] = XK_Prior; qtKeyToVirtKeyHash[Qt::Key_PageDown] = XK_Next; } void QtX11KeyMapper::mapModifiersKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Shift] = XK_Shift_L; // qtKeyToX11KeySym[Qt::Key_Shift] = XK_Shift_R; // qtKeyToX11KeySym[Qt::Key_Shift] = XK_Shift_Lock; qtKeyToVirtKeyHash[Qt::Key_Control] = XK_Control_L; // qtKeyToX11KeySym[Qt::Key_Control] = XK_Control_R; // qtKeyToVirtKeyHash[Qt::Key_Meta] = XK_Meta_L; // qtKeyToX11KeySym[Qt::Key_Meta] = XK_Meta_R; qtKeyToVirtKeyHash[Qt::Key_Alt] = XK_Alt_L; // qtKeyToX11KeySym[Qt::Key_Alt] = XK_Alt_R; } void QtX11KeyMapper::mapAdditionalKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_CapsLock] = XK_Caps_Lock; qtKeyToVirtKeyHash[Qt::Key_NumLock] = XK_Num_Lock; qtKeyToVirtKeyHash[Qt::Key_ScrollLock] = XK_Scroll_Lock; qtKeyToVirtKeyHash[Qt::Key_Meta] = XK_Super_L; qtKeyToVirtKeyHash[AntKey_Meta_R] = XK_Super_R; // qtKeyToVirtKeyHash[Qt::Key_Super_L] = XK_Super_L; // qtKeyToVirtKeyHash[Qt::Key_Super_R] = XK_Super_R; qtKeyToVirtKeyHash[Qt::Key_Menu] = XK_Menu; qtKeyToVirtKeyHash[Qt::Key_Hyper_L] = XK_Hyper_L; qtKeyToVirtKeyHash[Qt::Key_Hyper_R] = XK_Hyper_R; qtKeyToVirtKeyHash[Qt::Key_Help] = XK_Help; } void QtX11KeyMapper::mapKeypadKeysQtX11(QHash &qtKeyToVirtKeyHash) { // qtKeyToVirtKeyHash[Qt::Key_Space] = XK_KP_Space; // qtKeyToX11KeySym[Qt::Key_Tab] = XK_KP_Tab; qtKeyToVirtKeyHash[AntKey_KP_Enter] = XK_KP_Enter; qtKeyToVirtKeyHash[AntKey_KP_Home] = XK_KP_Home; // qtKeyToX11KeySym[Qt::Key_Home] = XK_KP_Home; qtKeyToVirtKeyHash[AntKey_KP_Left] = XK_KP_Left; qtKeyToVirtKeyHash[AntKey_KP_Up] = XK_KP_Up; qtKeyToVirtKeyHash[AntKey_KP_Right] = XK_KP_Right; qtKeyToVirtKeyHash[AntKey_KP_Down] = XK_KP_Down; qtKeyToVirtKeyHash[AntKey_KP_Prior] = XK_KP_Prior; qtKeyToVirtKeyHash[AntKey_KP_Next] = XK_KP_Next; qtKeyToVirtKeyHash[AntKey_KP_End] = XK_KP_End; qtKeyToVirtKeyHash[AntKey_KP_Begin] = XK_KP_Begin; qtKeyToVirtKeyHash[AntKey_KP_Insert] = XK_KP_Insert; qtKeyToVirtKeyHash[AntKey_KP_Delete] = XK_KP_Delete; // qtKeyToX11KeySym[AntKey_KP_Equal] = XK_KP_Equal; qtKeyToVirtKeyHash[AntKey_KP_Add] = XK_KP_Add; // qtKeyToX11KeySym[AntKey_KP_Separator] = XK_KP_Separator; qtKeyToVirtKeyHash[AntKey_KP_Subtract] = XK_KP_Subtract; qtKeyToVirtKeyHash[AntKey_KP_Decimal] = XK_KP_Decimal; qtKeyToVirtKeyHash[AntKey_KP_Divide] = XK_KP_Divide; qtKeyToVirtKeyHash[AntKey_KP_1] = XK_KP_1; qtKeyToVirtKeyHash[AntKey_KP_2] = XK_KP_2; qtKeyToVirtKeyHash[AntKey_KP_3] = XK_KP_3; qtKeyToVirtKeyHash[AntKey_KP_4] = XK_KP_4; qtKeyToVirtKeyHash[AntKey_KP_5] = XK_KP_5; qtKeyToVirtKeyHash[AntKey_KP_6] = XK_KP_6; qtKeyToVirtKeyHash[AntKey_KP_7] = XK_KP_7; qtKeyToVirtKeyHash[AntKey_KP_8] = XK_KP_8; qtKeyToVirtKeyHash[AntKey_KP_9] = XK_KP_9; qtKeyToVirtKeyHash[AntKey_KP_0] = XK_KP_0; } void QtX11KeyMapper::mapInternationKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_AltGr] = XK_ISO_Level3_Shift; qtKeyToVirtKeyHash[Qt::Key_Multi_key] = XK_Multi_key; qtKeyToVirtKeyHash[Qt::Key_Codeinput] = XK_Codeinput; qtKeyToVirtKeyHash[Qt::Key_SingleCandidate] = XK_SingleCandidate; qtKeyToVirtKeyHash[Qt::Key_MultipleCandidate] = XK_MultipleCandidate; qtKeyToVirtKeyHash[Qt::Key_PreviousCandidate] = XK_PreviousCandidate; } void QtX11KeyMapper::mapJapanKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Kanji] = XK_Kanji; qtKeyToVirtKeyHash[Qt::Key_Muhenkan] = XK_Muhenkan; qtKeyToVirtKeyHash[Qt::Key_Henkan] = XK_Henkan_Mode; // qtKeyToX11KeySym[Qt::Key_Henkan] = XK_Henkan; qtKeyToVirtKeyHash[Qt::Key_Romaji] = XK_Romaji; qtKeyToVirtKeyHash[Qt::Key_Hiragana] = XK_Hiragana; qtKeyToVirtKeyHash[Qt::Key_Katakana] = XK_Katakana; qtKeyToVirtKeyHash[Qt::Key_Hiragana_Katakana] = XK_Hiragana_Katakana; qtKeyToVirtKeyHash[Qt::Key_Zenkaku] = XK_Zenkaku; qtKeyToVirtKeyHash[Qt::Key_Hankaku] = XK_Hankaku; qtKeyToVirtKeyHash[Qt::Key_Zenkaku_Hankaku] = XK_Zenkaku_Hankaku; qtKeyToVirtKeyHash[Qt::Key_Touroku] = XK_Touroku; qtKeyToVirtKeyHash[Qt::Key_Massyo] = XK_Massyo; qtKeyToVirtKeyHash[Qt::Key_Kana_Lock] = XK_Kana_Lock; qtKeyToVirtKeyHash[Qt::Key_Kana_Shift] = XK_Kana_Shift; qtKeyToVirtKeyHash[Qt::Key_Eisu_Shift] = XK_Eisu_Shift; qtKeyToVirtKeyHash[Qt::Key_Eisu_toggle] = XK_Eisu_toggle; qtKeyToVirtKeyHash[Qt::Key_Codeinput] = XK_Kanji_Bangou; // qtKeyToX11KeySym[Qt::Key_MultipleCandidate] = XK_Zen_Koho; // qtKeyToX11KeySym[Qt::Key_PreviousCandidate] = XK_Mae_Koho; } void QtX11KeyMapper::mapKoreanKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Hangul] = XK_Hangul; qtKeyToVirtKeyHash[Qt::Key_Hangul_Start] = XK_Hangul_Start; qtKeyToVirtKeyHash[Qt::Key_Hangul_End] = XK_Hangul_End; qtKeyToVirtKeyHash[Qt::Key_Hangul_Hanja] = XK_Hangul_Hanja; qtKeyToVirtKeyHash[Qt::Key_Hangul_Jamo] = XK_Hangul_Jamo; qtKeyToVirtKeyHash[Qt::Key_Hangul_Romaja] = XK_Hangul_Romaja; // qtKeyToX11KeySym[Qt::Key_Codeinput] = XK_Hangul_Codeinput; qtKeyToVirtKeyHash[Qt::Key_Hangul_Jeonja] = XK_Hangul_Jeonja; qtKeyToVirtKeyHash[Qt::Key_Hangul_Banja] = XK_Hangul_Banja; qtKeyToVirtKeyHash[Qt::Key_Hangul_PreHanja] = XK_Hangul_PreHanja; qtKeyToVirtKeyHash[Qt::Key_Hangul_PostHanja] = XK_Hangul_PostHanja; // qtKeyToX11KeySym[Qt::Key_SingleCandidate] = XK_Hangul_SingleCandidate; // qtKeyToX11KeySym[Qt::Key_MultipleCandidate] = XK_Hangul_MultipleCandidate; // qtKeyToX11KeySym[Qt::Key_PreviousCandidate] = XK_Hangul_PreviousCandidate; qtKeyToVirtKeyHash[Qt::Key_Hangul_Special] = XK_Hangul_Special; // qtKeyToX11KeySym[Qt::Key_Mode_switch] = XK_Hangul_switch; } void QtX11KeyMapper::mapDeadKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Dead_Grave] = XK_dead_grave; qtKeyToVirtKeyHash[Qt::Key_Dead_Acute] = XK_dead_acute; qtKeyToVirtKeyHash[Qt::Key_Dead_Circumflex] = XK_dead_circumflex; qtKeyToVirtKeyHash[Qt::Key_Dead_Tilde] = XK_dead_tilde; qtKeyToVirtKeyHash[Qt::Key_Dead_Macron] = XK_dead_macron; qtKeyToVirtKeyHash[Qt::Key_Dead_Breve] = XK_dead_breve; qtKeyToVirtKeyHash[Qt::Key_Dead_Abovedot] = XK_dead_abovedot; qtKeyToVirtKeyHash[Qt::Key_Dead_Diaeresis] = XK_dead_diaeresis; qtKeyToVirtKeyHash[Qt::Key_Dead_Abovering] = XK_dead_abovering; qtKeyToVirtKeyHash[Qt::Key_Dead_Doubleacute] = XK_dead_doubleacute; qtKeyToVirtKeyHash[Qt::Key_Dead_Caron] = XK_dead_caron; qtKeyToVirtKeyHash[Qt::Key_Dead_Cedilla] = XK_dead_cedilla; qtKeyToVirtKeyHash[Qt::Key_Dead_Ogonek] = XK_dead_ogonek; qtKeyToVirtKeyHash[Qt::Key_Dead_Iota] = XK_dead_iota; qtKeyToVirtKeyHash[Qt::Key_Dead_Voiced_Sound] = XK_dead_voiced_sound; qtKeyToVirtKeyHash[Qt::Key_Dead_Semivoiced_Sound] = XK_dead_semivoiced_sound; qtKeyToVirtKeyHash[Qt::Key_Dead_Belowdot] = XK_dead_belowdot; qtKeyToVirtKeyHash[Qt::Key_Dead_Hook] = XK_dead_hook; qtKeyToVirtKeyHash[Qt::Key_Dead_Horn] = XK_dead_horn; } void QtX11KeyMapper::mapBrowseKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_Back] = XF86XK_Back; qtKeyToVirtKeyHash[Qt::Key_Forward] = XF86XK_Forward; qtKeyToVirtKeyHash[Qt::Key_Stop] = XF86XK_Stop; qtKeyToVirtKeyHash[Qt::Key_Refresh] = XF86XK_Refresh; qtKeyToVirtKeyHash[Qt::Key_Favorites] = XF86XK_Favorites; qtKeyToVirtKeyHash[Qt::Key_LaunchMedia] = XF86XK_AudioMedia; qtKeyToVirtKeyHash[Qt::Key_OpenUrl] = XF86XK_OpenURL; qtKeyToVirtKeyHash[Qt::Key_HomePage] = XF86XK_HomePage; qtKeyToVirtKeyHash[Qt::Key_Search] = XF86XK_Search; } void QtX11KeyMapper::mapMediaKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_VolumeDown] = XF86XK_AudioLowerVolume; qtKeyToVirtKeyHash[Qt::Key_VolumeMute] = XF86XK_AudioMute; qtKeyToVirtKeyHash[Qt::Key_VolumeUp] = XF86XK_AudioRaiseVolume; qtKeyToVirtKeyHash[Qt::Key_MediaPlay] = XF86XK_AudioPlay; qtKeyToVirtKeyHash[Qt::Key_MediaStop] = XF86XK_AudioStop; qtKeyToVirtKeyHash[Qt::Key_MediaPrevious] = XF86XK_AudioPrev; qtKeyToVirtKeyHash[Qt::Key_MediaNext] = XF86XK_AudioNext; qtKeyToVirtKeyHash[Qt::Key_MediaRecord] = XF86XK_AudioRecord; } void QtX11KeyMapper::mapLaunchKeysQtX11(QHash &qtKeyToVirtKeyHash) { qtKeyToVirtKeyHash[Qt::Key_LaunchMail] = XF86XK_Mail; qtKeyToVirtKeyHash[Qt::Key_Launch0] = XF86XK_MyComputer; qtKeyToVirtKeyHash[Qt::Key_Launch1] = XF86XK_Calculator; qtKeyToVirtKeyHash[Qt::Key_Standby] = XF86XK_Standby; qtKeyToVirtKeyHash[Qt::Key_Launch2] = XF86XK_Launch0; qtKeyToVirtKeyHash[Qt::Key_Launch3] = XF86XK_Launch1; qtKeyToVirtKeyHash[Qt::Key_Launch4] = XF86XK_Launch2; qtKeyToVirtKeyHash[Qt::Key_Launch5] = XF86XK_Launch3; qtKeyToVirtKeyHash[Qt::Key_Launch6] = XF86XK_Launch4; qtKeyToVirtKeyHash[Qt::Key_Launch7] = XF86XK_Launch5; qtKeyToVirtKeyHash[Qt::Key_Launch8] = XF86XK_Launch6; qtKeyToVirtKeyHash[Qt::Key_Launch9] = XF86XK_Launch7; qtKeyToVirtKeyHash[Qt::Key_LaunchA] = XF86XK_Launch8; qtKeyToVirtKeyHash[Qt::Key_LaunchB] = XF86XK_Launch9; qtKeyToVirtKeyHash[Qt::Key_LaunchC] = XF86XK_LaunchA; qtKeyToVirtKeyHash[Qt::Key_LaunchD] = XF86XK_LaunchB; qtKeyToVirtKeyHash[Qt::Key_LaunchE] = XF86XK_LaunchC; qtKeyToVirtKeyHash[Qt::Key_LaunchF] = XF86XK_LaunchD; } AntiMicroX-antimicrox-2888bf6/src/qtx11keymapper.h000066400000000000000000000036741377703515000221310ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QTX11KEYMAPPER_H #define QTX11KEYMAPPER_H #include "qtkeymapperbase.h" class QtX11KeyMapper : public QtKeyMapperBase { Q_OBJECT public: explicit QtX11KeyMapper(QObject *parent = nullptr); protected: void populateMappingHashes() override; void populateCharKeyInformation() override; private: void mapMiscKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapCursorMovesKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapModifiersKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapAdditionalKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapKeypadKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapInternationKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapJapanKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapKoreanKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapDeadKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapBrowseKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapMediaKeysQtX11(QHash &qtKeyToVirtKeyHash); void mapLaunchKeysQtX11(QHash &qtKeyToVirtKeyHash); }; #endif // QTX11KEYMAPPER_H AntiMicroX-antimicrox-2888bf6/src/quicksetdialog.cpp000066400000000000000000000420531377703515000225720ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "quicksetdialog.h" #include "ui_quicksetdialog.h" #include "buttoneditdialog.h" #include "inputdevice.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joybuttontypes/joydpadbutton.h" #include "joycontrolstick.h" #include "joydpad.h" #include "messagehandler.h" #include "setjoystick.h" #include "uihelpers/buttoneditdialoghelper.h" #include "vdpad.h" #include #include #include #include #include QuickSetDialog::QuickSetDialog(InputDevice *joystick, QWidget *parent) : QDialog(parent) , ui(new Ui::QuickSetDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->joystick = joystick; this->currentButtonDialog = nullptr; setWindowTitle(tr("Quick Set %1").arg(joystick->getName())); SetJoystick *currentset = joystick->getActiveSetJoystick(); currentset->release(); joystick->resetButtonDownCount(); QString temp = ui->joystickDialogLabel->text(); temp = temp.arg(joystick->getSDLName()).arg(joystick->getName()); ui->joystickDialogLabel->setText(temp); connectSticksForDialog(currentset); connectAxesForDialog(currentset); connectDpadForDialog(currentset); connectVDpadForDialog(currentset); connectBtnForDialog(currentset); connect(this, &QuickSetDialog::finished, this, &QuickSetDialog::restoreJoystickState); } QuickSetDialog::QuickSetDialog(InputDevice *joystick, ButtonEditDialogHelper *helper, const char *invokeString, int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode, bool withClear, bool withTrue, QWidget *parent) : QDialog(parent) , ui(new Ui::QuickSetDialog) { ui->setupUi(this); show(); this->joystick = joystick; this->invokeString = invokeString; this->code = code; this->alias = alias; this->index = index; this->mode = mode; this->withClear = withClear; this->withTrue = withTrue; this->helper = helper; lastButton = nullptr; setWindowTitle(tr("Quick Set %1").arg(joystick->getName())); setAttribute(Qt::WA_DeleteOnClose); setWindowModality(Qt::WindowModal); SetJoystick *currentset = joystick->getActiveSetJoystick(); QString temp = ui->joystickDialogLabel->text(); temp = temp.arg(joystick->getSDLName()).arg(joystick->getName()); ui->joystickDialogLabel->setText(temp); connectSticksForDialog(currentset); connectAxesForDialog(currentset); connectDpadForDialog(currentset); connectVDpadForDialog(currentset); connectBtnForDialog(currentset); connect(this, &QuickSetDialog::finished, this, &QuickSetDialog::restoreJoystickState); } void QuickSetDialog::connectSticksForDialog(SetJoystick *currentset) { QListIterator sticksList = currentset->getSticks().values(); while (sticksList.hasNext()) { JoyControlStick *stick = sticksList.next(); QHash *stickButtons = stick->getButtons(); QHashIterator iter(*stickButtons); while (iter.hasNext()) { JoyControlStickButton *stickbutton = iter.next().value(); if (stick->getJoyMode() != JoyControlStick::EightWayMode) { if ((stickbutton->getJoyNumber() != static_cast(JoyControlStick::StickLeftUp)) && (stickbutton->getJoyNumber() != static_cast(JoyControlStick::StickRightUp)) && (stickbutton->getJoyNumber() != static_cast(JoyControlStick::StickLeftDown)) && (stickbutton->getJoyNumber() != static_cast(JoyControlStick::StickRightDown))) { connect(stickbutton, &JoyControlStickButton::clicked, this, [this, stickbutton]() { showStickButtonDialog(stickbutton); }); } } else { connect(stickbutton, &JoyControlStickButton::clicked, this, [this, stickbutton]() { showStickButtonDialog(stickbutton); }); } if (!stickbutton->getIgnoreEventState()) stickbutton->setIgnoreEventState(true); } } } void QuickSetDialog::connectAxesForDialog(SetJoystick *currentset) { QListIterator axesList = currentset->getAxes()->values(); while (axesList.hasNext()) { JoyAxis *axis = axesList.next(); if (!axis->isPartControlStick() && axis->hasControlOfButtons()) { JoyAxisButton *naxisbutton = axis->getNAxisButton(); JoyAxisButton *paxisbutton = axis->getPAxisButton(); connect(naxisbutton, &JoyAxisButton::clicked, this, [this, naxisbutton]() { showAxisButtonDialog(naxisbutton); }); connect(paxisbutton, &JoyAxisButton::clicked, this, [this, paxisbutton]() { showAxisButtonDialog(paxisbutton); }); if (!naxisbutton->getIgnoreEventState()) naxisbutton->setIgnoreEventState(true); if (!paxisbutton->getIgnoreEventState()) paxisbutton->setIgnoreEventState(true); } } } void QuickSetDialog::connectDpadForDialog(SetJoystick *currentset) { QListIterator dpadsList = currentset->getHats().values(); while (dpadsList.hasNext()) { JoyDPad *dpad = dpadsList.next(); QHash *dpadbuttons = dpad->getButtons(); QHashIterator iter(*dpadbuttons); while (iter.hasNext()) { JoyDPadButton *dpadbutton = iter.next().value(); if (dpad->getJoyMode() != JoyDPad::EightWayMode) { if ((dpadbutton->getJoyNumber() != JoyDPadButton::DpadLeftUp) && (dpadbutton->getJoyNumber() != JoyDPadButton::DpadRightUp) && (dpadbutton->getJoyNumber() != JoyDPadButton::DpadLeftDown) && (dpadbutton->getJoyNumber() != JoyDPadButton::DpadRightDown)) { connect(dpadbutton, &JoyDPadButton::clicked, this, [this, dpadbutton] { showDPadButtonDialog(dpadbutton); }); } } else { connect(dpadbutton, &JoyDPadButton::clicked, this, [this, dpadbutton] { showDPadButtonDialog(dpadbutton); }); } if (!dpadbutton->getIgnoreEventState()) dpadbutton->setIgnoreEventState(true); } } } void QuickSetDialog::connectVDpadForDialog(SetJoystick *currentset) { QListIterator vdpadsList = currentset->getVdpads().values(); while (vdpadsList.hasNext()) { VDPad *dpad = vdpadsList.next(); if (dpad != nullptr) { QHash *dpadbuttons = dpad->getButtons(); QHashIterator iter(*dpadbuttons); while (iter.hasNext()) { JoyDPadButton *dpadbutton = iter.next().value(); if (dpad->getJoyMode() != JoyDPad::EightWayMode) { if ((dpadbutton->getJoyNumber() != JoyDPadButton::DpadLeftUp) && (dpadbutton->getJoyNumber() != JoyDPadButton::DpadRightUp) && (dpadbutton->getJoyNumber() != JoyDPadButton::DpadLeftDown) && (dpadbutton->getJoyNumber() != JoyDPadButton::DpadRightDown)) { connect(dpadbutton, &JoyDPadButton::clicked, this, [this, dpadbutton] { showDPadButtonDialog(dpadbutton); }); } } else { connect(dpadbutton, &JoyDPadButton::clicked, this, [this, dpadbutton] { showDPadButtonDialog(dpadbutton); }); } if (!dpadbutton->getIgnoreEventState()) dpadbutton->setIgnoreEventState(true); } } } } void QuickSetDialog::connectBtnForDialog(SetJoystick *currentset) { QListIterator btnsList = currentset->getButtons().values(); while (btnsList.hasNext()) { JoyButton *button = btnsList.next(); if ((button != nullptr) && !button->isPartVDPad()) { connect(button, &JoyButton::clicked, this, [this, button] { showButtonDialog(button); }); if (!button->getIgnoreEventState()) button->setIgnoreEventState(true); } } } QuickSetDialog::~QuickSetDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void QuickSetDialog::invokeMethodLastBtn(JoyButton *lastJoyBtn, Qt::ConnectionType connTypeForAlias, Qt::ConnectionType connTypeForNothing, Qt::ConnectionType connTypeForAll, bool possibleAxisAction) { lastButton = lastJoyBtn; // sometimes appears situation, when we want to map an axis of stick, // it's detected some state between pressing stick button and moving axis. // It chooses a function for pressing a stick, but later appears a problem, // because correct and prepared value is from the axis one, so static_cast // for stick button is failing // App can sometimes ask to three times for a button, but it's not going to crash this time // if lastButton is still a null pointer, check possible value correctness coming from axis if (possibleAxisAction && (lastButton == nullptr)) lastButton = qobject_cast(sender()); if (helper != nullptr) helper = new ButtonEditDialogHelper(); if (lastButton != nullptr) { helper->setThisButton(lastButton); helper->moveToThread(lastButton->thread()); qDebug() << "Thread in QuickSetDialog"; if (withClear) QMetaObject::invokeMethod(lastButton, "clearSlotsEventReset", Q_ARG(bool, withTrue)); // when alias exists but not index if ((alias != -1) && (index == -1)) { QMetaObject::invokeMethod(helper, invokeString, connTypeForAlias, Q_ARG(int, code), Q_ARG(int, alias), Q_ARG(JoyButtonSlot::JoySlotInputAction, mode)); // when alias doesn't exists and index too } else if ((alias == -1) && (index == -1)) { QMetaObject::invokeMethod(helper, invokeString, connTypeForNothing, Q_ARG(int, code), Q_ARG(JoyButtonSlot::JoySlotInputAction, mode)); // when all exist (code, alias, index) } else { QMetaObject::invokeMethod(helper, invokeString, connTypeForAll, Q_ARG(int, code), Q_ARG(int, alias), Q_ARG(int, index), Q_ARG(JoyButtonSlot::JoySlotInputAction, mode)); } } } void QuickSetDialog::showAxisButtonDialog(JoyAxisButton *joybtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); invokeMethodLastBtn(joybtn, Qt::QueuedConnection, Qt::QueuedConnection, Qt::QueuedConnection); this->close(); } void QuickSetDialog::showButtonDialog(JoyButton *joybtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); invokeMethodLastBtn(joybtn, Qt::QueuedConnection, Qt::QueuedConnection, Qt::QueuedConnection); this->close(); } void QuickSetDialog::showStickButtonDialog(JoyControlStickButton *joyctrlstickbtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); lastButton = joyctrlstickbtn; invokeMethodLastBtn(joyctrlstickbtn, Qt::QueuedConnection, Qt::QueuedConnection, Qt::QueuedConnection, true); this->close(); } void QuickSetDialog::showDPadButtonDialog(JoyDPadButton *joydpadbtn) { qInstallMessageHandler(MessageHandler::myMessageOutput); invokeMethodLastBtn(joydpadbtn, Qt::QueuedConnection, Qt::QueuedConnection, Qt::BlockingQueuedConnection); this->close(); } void QuickSetDialog::restoreJoystickState() { qInstallMessageHandler(MessageHandler::myMessageOutput); SetJoystick *currentset = joystick->getActiveSetJoystick(); restoreSticksStates(currentset); restoreAxesStates(currentset); restoreHatsStates(currentset); restoreVDPadsStates(currentset); restoreButtonsStates(currentset); currentset->release(); } void QuickSetDialog::restoreSticksStates(SetJoystick *currentset) { QListIterator sticksList = currentset->getSticks().values(); while (sticksList.hasNext()) { JoyControlStick *stick = sticksList.next(); QHash *stickButtons = stick->getButtons(); QHashIterator iter(*stickButtons); while (iter.hasNext()) { JoyControlStickButton *stickbutton = iter.next().value(); if (stickbutton->getIgnoreEventState()) stickbutton->setIgnoreEventState(false); disconnect(stickbutton, &JoyControlStickButton::clicked, this, nullptr); } } } void QuickSetDialog::restoreAxesStates(SetJoystick *currentset) { QListIterator axesList = currentset->getAxes()->values(); while (axesList.hasNext()) { JoyAxis *axis = axesList.next(); if (!axis->isPartControlStick() && axis->hasControlOfButtons()) { JoyAxisButton *naxisbutton = axis->getNAxisButton(); if (naxisbutton->getIgnoreEventState()) naxisbutton->setIgnoreEventState(false); JoyAxisButton *paxisbutton = axis->getPAxisButton(); if (paxisbutton->getIgnoreEventState()) paxisbutton->setIgnoreEventState(false); disconnect(naxisbutton, &JoyAxisButton::clicked, this, nullptr); disconnect(paxisbutton, &JoyAxisButton::clicked, this, nullptr); } } } void QuickSetDialog::restoreHatsStates(SetJoystick *currentset) { QListIterator hatsList = currentset->getHats().values(); while (hatsList.hasNext()) { JoyDPad *dpad = hatsList.next(); QHash *dpadbuttons = dpad->getButtons(); QHashIterator iter(*dpadbuttons); while (iter.hasNext()) { JoyDPadButton *dpadbutton = iter.next().value(); if (dpadbutton->getIgnoreEventState()) dpadbutton->setIgnoreEventState(false); disconnect(dpadbutton, &JoyDPadButton::clicked, this, nullptr); } } } void QuickSetDialog::restoreVDPadsStates(SetJoystick *currentset) { QListIterator vdpadsList = currentset->getVdpads().values(); while (vdpadsList.hasNext()) { VDPad *dpad = vdpadsList.next(); if (dpad != nullptr) { QHash *dpadbuttons = dpad->getButtons(); QHashIterator iter(*dpadbuttons); while (iter.hasNext()) { JoyDPadButton *dpadbutton = iter.next().value(); if (dpadbutton->getIgnoreEventState()) dpadbutton->setIgnoreEventState(false); disconnect(dpadbutton, &JoyDPadButton::clicked, this, nullptr); } } } } void QuickSetDialog::restoreButtonsStates(SetJoystick *currentset) { QListIterator btnsList = currentset->getButtons().values(); while (btnsList.hasNext()) { JoyButton *button = btnsList.next(); if ((button != nullptr) && !button->isPartVDPad()) { if (button->getIgnoreEventState()) button->setIgnoreEventState(false); disconnect(button, &JoyButton::clicked, this, nullptr); } } } JoyButton *QuickSetDialog::getLastPressedButton() const { return lastButton; } InputDevice *QuickSetDialog::getJoystick() const { return joystick; } QDialog *QuickSetDialog::getCurrentButtonDialog() const { return currentButtonDialog; } const char *QuickSetDialog::getInvokeString() const { return invokeString; } ButtonEditDialogHelper *QuickSetDialog::getHelper() const { return helper; } JoyButtonSlot::JoySlotInputAction QuickSetDialog::getMode() const { return mode; } AntiMicroX-antimicrox-2888bf6/src/quicksetdialog.h000066400000000000000000000072771377703515000222500ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QUICKSETDIALOG_H #define QUICKSETDIALOG_H #include "uihelpers/buttoneditdialoghelper.h" #include class InputDevice; class QWidget; class SetJoystick; class JoyControlStick; class JoyButton; class JoyControlStickButton; class JoyDPadButton; class JoyAxisButton; namespace Ui { class QuickSetDialog; } class QuickSetDialog : public QDialog { Q_OBJECT public: explicit QuickSetDialog(InputDevice *joystick, QWidget *parent = nullptr); QuickSetDialog(InputDevice *joystick, ButtonEditDialogHelper *helper, const char *invokeString, int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode, bool withClear, bool withTrue, QWidget *parent = nullptr); ~QuickSetDialog(); JoyButton *getLastPressedButton() const; InputDevice *getJoystick() const; QDialog *getCurrentButtonDialog() const; const char *getInvokeString() const; ButtonEditDialogHelper *getHelper() const; JoyButtonSlot::JoySlotInputAction getMode() const; private slots: void showAxisButtonDialog(JoyAxisButton *joybtn); // QuickSetDialogAxisBtn class void showButtonDialog(JoyButton *joybtn); // QuickSetDialogBtn class void showStickButtonDialog(JoyControlStickButton *joyctrlstickbtn); // QuickSetDialogStick class void showDPadButtonDialog(JoyDPadButton *joydpadbtn); // QuickSetDialogHat class void restoreJoystickState(); private: void invokeMethodLastBtn(JoyButton *lastJoyBtn, Qt::ConnectionType connTypeForAlias, Qt::ConnectionType connTypeForNothing, Qt::ConnectionType connTypeForAll, bool possibleAxisAction = false); void restoreSticksStates(SetJoystick *currentset); // QuickSetDialogStick class void restoreAxesStates(SetJoystick *currentset); // QuickSetDialogAxis class void restoreHatsStates(SetJoystick *currentset); // QuickSetDialogHat class void restoreVDPadsStates(SetJoystick *currentset); // QuickSetDialogVDPad class void restoreButtonsStates(SetJoystick *currentset); // QuickSetDialogBtn class void connectSticksForDialog(SetJoystick *currentset); // QuickSetDialogStick class void connectAxesForDialog(SetJoystick *currentset); // QuickSetDialogAxis class void connectDpadForDialog(SetJoystick *currentset); // QuickSetDialogHat class void connectVDpadForDialog(SetJoystick *currentset); // QuickSetDialogVDPad class void connectBtnForDialog(SetJoystick *currentset); // QuickSetDialogBtn class Ui::QuickSetDialog *ui; InputDevice *joystick; QDialog *currentButtonDialog; ButtonEditDialogHelper *helper; JoyButton *lastButton; const char *invokeString; int code; int alias; int index; JoyButtonSlot::JoySlotInputAction mode; bool withClear; bool withTrue; }; #endif // QUICKSETDIALOG_H AntiMicroX-antimicrox-2888bf6/src/quicksetdialog.ui000066400000000000000000000040761377703515000224300ustar00rootroot00000000000000 QuickSetDialog 0 0 400 300 Quick Set true <html><head/><body><p>Please press a button or move an axis on %1 (<span style=" font-weight:600;">%2</span>).<br/>A dialog window will then appear which will<br/>allow you to make an assignment.</p></body></html> Qt::AlignCenter false Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() QuickSetDialog accept() 248 254 157 274 buttonBox rejected() QuickSetDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/resources.qrc000066400000000000000000000060251377703515000215760ustar00rootroot00000000000000 images/antimicrox.png images/48-apps-antimicrox_trayicon.png images/axis.png images/button.png images/controllermap.png icons/actions/wiki.png icons/actions/about_qt.png icons/actions/about_antimicrox.png icons/actions/github_page.png icons/actions/issues.png icons/actions/settings.png icons/actions/stick_pad_assign.png icons/actions/calibration.png icons/actions/map_controller.png icons/actions/sliders.png icons/actions/key_checker.png icons/actions/application_exit.png icons/actions/archive_insert.png icons/actions/dialog_cancel.png icons/actions/dialog_close.png icons/actions/dialog_ok.png icons/actions/document_close.png icons/actions/document_open.png icons/actions/document_open_folder.png icons/actions/document_revert.png icons/actions/document_revert_small.png icons/actions/document_save.png icons/actions/document_save_as.png icons/actions/edit_clear.png icons/actions/edit_clear_list.png icons/actions/edit_delete.png icons/actions/edit_select.png icons/actions/edit_table_delete_row.png icons/actions/edit_table_insert_row_below.png icons/actions/games_config_custom.png icons/actions/games_config_options.png icons/actions/help_about.png icons/actions/text_field.png icons/actions/view_fullscreen.png icons/actions/view_refresh.png icons/actions/view_restore.png icons/application/16x16/apps/16-apps-io.github.antimicrox.antimicrox.png icons/application/24x24/apps/24-apps-io.github.antimicrox.antimicrox.png icons/application/32x32/apps/32-apps-io.github.antimicrox.antimicrox.png icons/application/48x48/apps/48-apps-io.github.antimicrox.antimicrox.png icons/application/64x64/apps/64-apps-io.github.antimicrox.antimicrox.png icons/application/128x128/apps/128-apps-io.github.antimicrox.antimicrox.png icons/application/scalable/apps/sc-apps-io.github.antimicrox.antimicrox.svg images/battery-low-level.png icons/actions/join_slots.png icons/actions/split_slot.png CHANGELOG.md AntiMicroX-antimicrox-2888bf6/src/sdleventreader.cpp000066400000000000000000000147721377703515000226000ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "sdleventreader.h" #include "antimicrosettings.h" #include "common.h" #include "globalvariables.h" #include "inputdevice.h" #include "messagehandler.h" //#include "logger.h" #include #include #include #include #include #include SDLEventReader::SDLEventReader(QMap *joysticks, AntiMicroSettings *settings, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->joysticks = joysticks; this->settings = settings; settings->getLock()->lock(); this->pollRate = settings->value("GamepadPollRate", GlobalVariables::AntimicroSettings::defaultSDLGamepadPollRate).toUInt(); settings->getLock()->unlock(); pollRateTimer.setParent(this); pollRateTimer.setTimerType(Qt::PreciseTimer); initSDL(); connect(&pollRateTimer, &QTimer::timeout, this, &SDLEventReader::performWork); } SDLEventReader::~SDLEventReader() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (sdlIsOpen) { closeSDL(); } } void SDLEventReader::initSDL() { qInstallMessageHandler(MessageHandler::myMessageOutput); // SDL_INIT_GAMECONTROLLER should automatically initialize SDL_INIT_JOYSTICK // but it doesn't seem to be the case with v2.0.4 SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK); SDL_JoystickEventState(SDL_ENABLE); sdlIsOpen = true; settings->getLock()->lock(); settings->beginGroup("Mappings"); QStringList mappings = settings->allKeys(); QStringListIterator iter(mappings); while (iter.hasNext()) { QString tempstring = iter.next(); QString mappingSetting = settings->value(tempstring, QString()).toString(); if (!mappingSetting.isEmpty()) { QByteArray temparray = mappingSetting.toUtf8(); char *mapping = temparray.data(); SDL_GameControllerAddMapping(mapping); // Let SDL take care of validation } } settings->endGroup(); settings->getLock()->unlock(); pollRateTimer.stop(); pollRateTimer.setInterval(pollRate); emit sdlStarted(); } void SDLEventReader::closeSDL() { qInstallMessageHandler(MessageHandler::myMessageOutput); pollRateTimer.stop(); SDL_Event event; closeDevices(); // Clear any pending events while (SDL_PollEvent(&event) > 0) { } SDL_Quit(); sdlIsOpen = false; emit sdlClosed(); } void SDLEventReader::performWork() { if (sdlIsOpen && (eventStatus() > 0)) { pollRateTimer.stop(); emit eventRaised(); } } void SDLEventReader::stop() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (sdlIsOpen) { SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); } pollRateTimer.stop(); } void SDLEventReader::refresh() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (sdlIsOpen) { stop(); QTimer::singleShot(0, this, SLOT(secondaryRefresh())); } } void SDLEventReader::secondaryRefresh() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (sdlIsOpen) closeSDL(); initSDL(); } void SDLEventReader::clearEvents() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (sdlIsOpen) { SDL_Event event; while (SDL_PollEvent(&event) > 0) { } } } bool SDLEventReader::isSDLOpen() { qInstallMessageHandler(MessageHandler::myMessageOutput); return sdlIsOpen; } int SDLEventReader::eventStatus() { int result = 0; SDL_PumpEvents(); switch (SDL_PeepEvents(nullptr, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { case -1: { Logger::LogError(QString("SDL Error: %1").arg(QString(SDL_GetError())), true, true); result = 0; break; } case 0: { if (!pollRateTimer.isActive()) pollRateTimer.start(); break; } default: { result = 1; break; } } return result; } void SDLEventReader::updatePollRate(int tempPollRate) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((tempPollRate >= 1) && (tempPollRate <= 16)) { bool pollTimerWasActive = pollRateTimer.isActive(); pollRateTimer.stop(); this->pollRate = tempPollRate; pollRateTimer.setInterval(pollRate); if (pollTimerWasActive) pollRateTimer.start(); } } void SDLEventReader::resetJoystickMap() { qInstallMessageHandler(MessageHandler::myMessageOutput); joysticks = nullptr; } void SDLEventReader::quit() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (sdlIsOpen) { closeSDL(); joysticks = nullptr; } } void SDLEventReader::closeDevices() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (sdlIsOpen && (joysticks != nullptr)) { QMapIterator iter(*joysticks); while (iter.hasNext()) { iter.next(); InputDevice *current = iter.value(); current->closeSDLDevice(); } } } /** * @brief Method to block activity on the SDLEventReader object and its thread * event loop. */ void SDLEventReader::haltServices() { qInstallMessageHandler(MessageHandler::myMessageOutput); PadderCommon::lockInputDevices(); PadderCommon::unlockInputDevices(); } QMap *SDLEventReader::getJoysticks() const { return joysticks; } AntiMicroSettings *SDLEventReader::getSettings() const { return settings; } QTimer const &SDLEventReader::getPollRateTimer() { return pollRateTimer; } AntiMicroX-antimicrox-2888bf6/src/sdleventreader.h000066400000000000000000000037561377703515000222450ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SDLEVENTREADER_H #define SDLEVENTREADER_H #include "joystick.h" class InputDevice; class AntiMicroSettings; class SDLEventReader : public QObject { Q_OBJECT public: explicit SDLEventReader(QMap *joysticks, AntiMicroSettings *settings, QObject *parent = nullptr); ~SDLEventReader(); bool isSDLOpen(); QMap *getJoysticks() const; AntiMicroSettings *getSettings() const; QTimer const &getPollRateTimer(); protected: void initSDL(); void closeSDL(); void clearEvents(); int eventStatus(); signals: void eventRaised(); void finished(); void sdlStarted(); void sdlClosed(); public slots: void performWork(); void stop(); void refresh(); void updatePollRate(int tempPollRate); // (unsigned) void resetJoystickMap(); void quit(); void closeDevices(); void haltServices(); private slots: void secondaryRefresh(); private: QMap *joysticks; bool sdlIsOpen; AntiMicroSettings *settings; int pollRate; QTimer pollRateTimer; }; #endif // SDLEVENTREADER_H AntiMicroX-antimicrox-2888bf6/src/setaxisthrottledialog.cpp000066400000000000000000000036751377703515000242170ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "setaxisthrottledialog.h" #include "ui_setaxisthrottledialog.h" #include "joyaxis.h" #include "messagehandler.h" #include #include SetAxisThrottleDialog::SetAxisThrottleDialog(JoyAxis *axis, QWidget *parent) : QDialog(parent) , ui(new Ui::SetAxisThrottleDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); this->axis = axis; QString currentText = ui->label->text(); currentText = currentText.arg(QString::number(axis->getRealJoyIndex())); ui->label->setText(currentText); connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SetAxisThrottleDialog::propogateThrottleChange); connect(this, &SetAxisThrottleDialog::initiateSetAxisThrottleChange, axis, &JoyAxis::propogateThrottleChange); } SetAxisThrottleDialog::~SetAxisThrottleDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void SetAxisThrottleDialog::propogateThrottleChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit initiateSetAxisThrottleChange(); } JoyAxis *SetAxisThrottleDialog::getAxis() const { return axis; } AntiMicroX-antimicrox-2888bf6/src/setaxisthrottledialog.h000066400000000000000000000025761377703515000236630ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SETAXISTHROTTLEDIALOG_H #define SETAXISTHROTTLEDIALOG_H #include class JoyAxis; class QWidget; namespace Ui { class SetAxisThrottleDialog; } class SetAxisThrottleDialog : public QDialog { Q_OBJECT public: explicit SetAxisThrottleDialog(JoyAxis *axis, QWidget *parent = nullptr); ~SetAxisThrottleDialog(); JoyAxis *getAxis() const; signals: void initiateSetAxisThrottleChange(); private slots: void propogateThrottleChange(); private: Ui::SetAxisThrottleDialog *ui; JoyAxis *axis; }; #endif // SETAXISTHROTTLEDIALOG_H AntiMicroX-antimicrox-2888bf6/src/setaxisthrottledialog.ui000066400000000000000000000035411377703515000240420ustar00rootroot00000000000000 SetAxisThrottleDialog 0 0 400 207 Throttle Change The throttle setting for Axis %1 has been changed. Would you like to distribute this throttle change to all sets? Qt::AlignCenter Qt::Horizontal QDialogButtonBox::No|QDialogButtonBox::Yes false buttonBox accepted() SetAxisThrottleDialog accept() 248 254 157 274 buttonBox rejected() SetAxisThrottleDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/setjoystick.cpp000066400000000000000000001026671377703515000221450ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "setjoystick.h" #include "globalvariables.h" #include "inputdevice.h" #include "joybutton.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joycontrolstick.h" #include "joydpad.h" #include "messagehandler.h" #include "vdpad.h" #include #include #include SetJoystick::SetJoystick(InputDevice *device, int index, QObject *parent) : SetJoystickXml(this, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_device = device; m_index = index; reset(); } SetJoystick::SetJoystick(InputDevice *device, int index, bool runreset, QObject *parent) : SetJoystickXml(this, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_device = device; m_index = index; if (runreset) reset(); } SetJoystick::~SetJoystick() { qInstallMessageHandler(MessageHandler::myMessageOutput); deleteSticks(); deleteVDpads(); deleteButtons(); deleteAxes(); deleteHats(); removeAllBtnFromQueue(); } JoyButton *SetJoystick::getJoyButton(int index) const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getButtons().value(index); } JoyAxis *SetJoystick::getJoyAxis(int index) const { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(!axes.isEmpty()); return axes.value(index); } JoyDPad *SetJoystick::getJoyDPad(int index) const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getHats().value(index); } VDPad *SetJoystick::getVDPad(int index) const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getVdpads().value(index); } JoyControlStick *SetJoystick::getJoyStick(int index) const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getSticks().value(index); } void SetJoystick::refreshButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); deleteButtons(); for (int i = 0; i < m_device->getNumberRawButtons(); i++) { JoyButton *button = new JoyButton(i, m_index, this, this); m_buttons.insert(i, button); enableButtonConnections(button); } } void SetJoystick::refreshAxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); deleteAxes(); InputDevice *device = getInputDevice(); for (int i = 0; i < device->getNumberRawAxes(); i++) { JoyAxis *axis = new JoyAxis(i, m_index, this, this); axes.insert(i, axis); if (device->hasCalibrationThrottle(i)) { JoyAxis::ThrottleTypes throttle = device->getCalibrationThrottle(i); axis->setInitialThrottle(throttle); } enableAxisConnections(axis); } } void SetJoystick::refreshHats() { qInstallMessageHandler(MessageHandler::myMessageOutput); deleteHats(); for (int i = 0; i < m_device->getNumberRawHats(); i++) { JoyDPad *dpad = new JoyDPad(i, m_index, this, this); hats.insert(i, dpad); enableHatConnections(dpad); } } void SetJoystick::deleteButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getButtons()); while (iter.hasNext()) { JoyButton *button = iter.next().value(); if (button != nullptr) { delete button; button = nullptr; } } m_buttons.clear(); } void SetJoystick::deleteAxes() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(axes); while (iter.hasNext()) { JoyAxis *axis = iter.next().value(); if (axis != nullptr) { axes.remove(iter.key()); delete axis; } } axes.clear(); } void SetJoystick::deleteSticks() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getSticks()); while (iter.hasNext()) { JoyControlStick *stick = iter.next().value(); if (stick != nullptr) { delete stick; stick = nullptr; } } sticks.clear(); } void SetJoystick::deleteVDpads() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getVdpads()); while (iter.hasNext()) { VDPad *dpad = iter.next().value(); if (dpad != nullptr) { delete dpad; dpad = nullptr; } } vdpads.clear(); } void SetJoystick::deleteHats() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getHats()); while (iter.hasNext()) { JoyDPad *dpad = iter.next().value(); if (dpad != nullptr) { hats.remove(iter.key()); delete dpad; } } hats.clear(); } int SetJoystick::getNumberButtons() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getButtons().count(); } int SetJoystick::getNumberAxes() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return axes.count(); } int SetJoystick::getNumberHats() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getHats().count(); } int SetJoystick::getNumberSticks() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getSticks().size(); } int SetJoystick::getNumberVDPads() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return getVdpads().size(); } void SetJoystick::reset() { qInstallMessageHandler(MessageHandler::myMessageOutput); deleteSticks(); deleteVDpads(); refreshAxes(); refreshButtons(); refreshHats(); m_name = QString(); } void SetJoystick::propogateSetChange(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); emit setChangeActivated(index); } void SetJoystick::propogateSetButtonAssociation(int button, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (newset != m_index) emit setAssignmentButtonChanged(button, m_index, newset, mode); } void SetJoystick::propogateSetAxisButtonAssociation(int button, int axis, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (newset != m_index) emit setAssignmentAxisChanged(button, axis, m_index, newset, mode); } void SetJoystick::propogateSetStickButtonAssociation(int button, int stick, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (newset != m_index) emit setAssignmentStickChanged(button, stick, m_index, newset, mode); } void SetJoystick::propogateSetDPadButtonAssociation(int button, int dpad, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (newset != m_index) emit setAssignmentDPadChanged(button, dpad, m_index, newset, mode); } void SetJoystick::propogateSetVDPadButtonAssociation(int button, int dpad, int newset, int mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (newset != m_index) emit setAssignmentVDPadChanged(button, dpad, m_index, newset, mode); } /** * @brief Perform a release of all elements of a set. Stick and vdpad * releases will be handled by the associated button or axis. */ void SetJoystick::release() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iterAxes(axes); while (iterAxes.hasNext()) { JoyAxis *axis = iterAxes.next().value(); axis->clearPendingEvent(); axis->joyEvent(axis->getCurrentThrottledDeadValue(), true); axis->eventReset(); } QHashIterator iterDPads(getHats()); while (iterDPads.hasNext()) { JoyDPad *dpad = iterDPads.next().value(); dpad->clearPendingEvent(); dpad->joyEvent(0, true); dpad->eventReset(); } QHashIterator iterButtons(getButtons()); while (iterButtons.hasNext()) { JoyButton *button = iterButtons.next().value(); button->clearPendingEvent(); button->joyEvent(false, true); button->eventReset(); } } bool SetJoystick::isSetEmpty() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = true; QHashIterator iter(getButtons()); while (iter.hasNext() && result) { JoyButton *button = iter.next().value(); if (!button->isDefault()) result = false; } QHashIterator iter2(axes); while (iter2.hasNext() && result) { JoyAxis *axis = iter2.next().value(); if (!axis->isDefault()) result = false; } QHashIterator iter3(getHats()); while (iter3.hasNext() && result) { JoyDPad *dpad = iter3.next().value(); if (!dpad->isDefault()) result = false; } QHashIterator iter4(getSticks()); while (iter4.hasNext() && result) { JoyControlStick *stick = iter4.next().value(); if (!stick->isDefault()) result = false; } QHashIterator iter5(getVdpads()); while (iter5.hasNext() && result) { VDPad *vdpad = iter5.next().value(); if (!vdpad->isDefault()) result = false; } return result; } void SetJoystick::propogateSetAxisThrottleSetting(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxis *axis = axes.value(index); if (axis != nullptr) emit setAssignmentAxisThrottleChanged(index, axis->getCurrentlyAssignedSet()); } void SetJoystick::addControlStick(int index, JoyControlStick *stick) { qInstallMessageHandler(MessageHandler::myMessageOutput); sticks.insert(index, stick); connect(stick, &JoyControlStick::stickNameChanged, this, &SetJoystick::propogateSetStickNameChange); QHashIterator iter(*stick->getButtons()); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button != nullptr) { connect(button, &JoyControlStickButton::setChangeActivated, this, &SetJoystick::propogateSetChange); connect(button, &JoyControlStickButton::setAssignmentChanged, this, &SetJoystick::propogateSetStickButtonAssociation); connect(button, &JoyControlStickButton::clicked, this, &SetJoystick::propogateSetStickButtonClick, Qt::QueuedConnection); connect(button, &JoyControlStickButton::released, this, &SetJoystick::propogateSetStickButtonRelease, Qt::QueuedConnection); connect(button, &JoyControlStickButton::buttonNameChanged, this, &SetJoystick::propogateSetStickButtonNameChange); } } } void SetJoystick::removeControlStick(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (getSticks().contains(index)) { JoyControlStick *stick = getSticks().value(index); sticks.remove(index); delete stick; stick = nullptr; } } void SetJoystick::addVDPad(int index, VDPad *vdpad) { qInstallMessageHandler(MessageHandler::myMessageOutput); vdpads.insert(index, vdpad); connect(vdpad, &VDPad::dpadNameChanged, this, &SetJoystick::propogateSetVDPadNameChange); QHashIterator iter(*vdpad->getButtons()); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); if (button != nullptr) { connect(button, &JoyDPadButton::setChangeActivated, this, &SetJoystick::propogateSetChange); connect(button, &JoyDPadButton::setAssignmentChanged, this, &SetJoystick::propogateSetVDPadButtonAssociation); connect(button, &JoyDPadButton::clicked, this, &SetJoystick::propogateSetDPadButtonClick, Qt::QueuedConnection); connect(button, &JoyDPadButton::released, this, &SetJoystick::propogateSetDPadButtonRelease, Qt::QueuedConnection); connect(button, &JoyDPadButton::buttonNameChanged, this, &SetJoystick::propogateSetVDPadButtonNameChange); } } } void SetJoystick::removeVDPad(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (getVdpads().contains(index)) { VDPad *vdpad = getVdpads().value(index); vdpads.remove(index); delete vdpad; vdpad = nullptr; } } int SetJoystick::getIndex() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index; } int SetJoystick::getRealIndex() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_index + 1; } void SetJoystick::propogateSetButtonClick(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *jButton = qobject_cast(sender()); if (jButton != nullptr && !jButton->getIgnoreEventState()) { emit setButtonClick(m_index, button); lastClickedButtons.append(jButton); qDebug() << "Added button " << jButton->getPartialName(false, true) << " to list"; qDebug() << "List has " << getLastClickedButtons().count() << " buttons"; } } QList const &SetJoystick::getLastClickedButtons() const { return lastClickedButtons; } void SetJoystick::removeAllBtnFromQueue() { if (!getLastClickedButtons().isEmpty()) lastClickedButtons.clear(); } int SetJoystick::getCountBtnInList(QString partialName) { int count = 0; foreach (const JoyButton *joyBtn, getLastClickedButtons()) { if (joyBtn->getPartialName(false, true) == partialName) count++; } return count; } void SetJoystick::propogateSetButtonRelease(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *jButton = qobject_cast(sender()); if (jButton != nullptr) { if (!jButton->getIgnoreEventState()) emit setButtonRelease(m_index, button); } } void SetJoystick::propogateSetAxisButtonClick(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *axisButton = qobject_cast(sender()); if (axisButton != nullptr) { JoyAxis *axis = axisButton->getAxis(); if (!axisButton->getIgnoreEventState()) emit setAxisButtonClick(m_index, axis->getIndex(), button); } } void SetJoystick::propogateSetAxisButtonRelease(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *axisButton = qobject_cast(sender()); if (axisButton != nullptr) { JoyAxis *axis = axisButton->getAxis(); if (!axisButton->getIgnoreEventState()) emit setAxisButtonRelease(m_index, axis->getIndex(), button); } } void SetJoystick::propogateSetStickButtonClick(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *stickButton = qobject_cast(sender()); if (stickButton != nullptr) { JoyControlStick *stick = stickButton->getStick(); if (stick && !stickButton->getIgnoreEventState()) emit setStickButtonClick(m_index, stick->getIndex(), button); } } void SetJoystick::propogateSetStickButtonRelease(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *stickButton = qobject_cast(sender()); if (stickButton != nullptr) { JoyControlStick *stick = stickButton->getStick(); if (!stickButton->getIgnoreEventState()) emit setStickButtonRelease(m_index, stick->getIndex(), button); } } void SetJoystick::propogateSetDPadButtonClick(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *dpadButton = qobject_cast(sender()); if (dpadButton) { JoyDPad *dpad = dpadButton->getDPad(); if (dpad && dpadButton->getButtonState() && !dpadButton->getIgnoreEventState()) { emit setDPadButtonClick(m_index, dpad->getIndex(), button); } } } void SetJoystick::propogateSetDPadButtonRelease(int button) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *dpadButton = qobject_cast(sender()); if (dpadButton != nullptr) { JoyDPad *dpad = dpadButton->getDPad(); if (dpad && !dpadButton->getButtonState() && !dpadButton->getIgnoreEventState()) { emit setDPadButtonRelease(m_index, dpad->getIndex(), button); } } } void SetJoystick::propogateSetButtonNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = qobject_cast(sender()); disconnect(button, &JoyButton::buttonNameChanged, this, &SetJoystick::propogateSetButtonNameChange); emit setButtonNameChange(button->getJoyNumber()); connect(button, &JoyButton::buttonNameChanged, this, &SetJoystick::propogateSetButtonNameChange); } void SetJoystick::propogateSetAxisButtonNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *button = qobject_cast(sender()); disconnect(button, &JoyAxisButton::buttonNameChanged, this, &SetJoystick::propogateSetAxisButtonNameChange); emit setAxisButtonNameChange(button->getAxis()->getIndex(), button->getJoyNumber()); connect(button, &JoyAxisButton::buttonNameChanged, this, &SetJoystick::propogateSetAxisButtonNameChange); } void SetJoystick::propogateSetStickButtonNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButton *button = qobject_cast(sender()); disconnect(button, &JoyControlStickButton::buttonNameChanged, this, &SetJoystick::propogateSetStickButtonNameChange); emit setStickButtonNameChange(button->getStick()->getIndex(), button->getJoyNumber()); connect(button, &JoyControlStickButton::buttonNameChanged, this, &SetJoystick::propogateSetStickButtonNameChange); } void SetJoystick::propogateSetDPadButtonNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *button = qobject_cast(sender()); disconnect(button, &JoyDPadButton::buttonNameChanged, this, &SetJoystick::propogateSetDPadButtonNameChange); emit setDPadButtonNameChange(button->getDPad()->getIndex(), button->getJoyNumber()); connect(button, &JoyDPadButton::buttonNameChanged, this, &SetJoystick::propogateSetDPadButtonNameChange); } void SetJoystick::propogateSetVDPadButtonNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPadButton *button = qobject_cast(sender()); disconnect(button, &JoyDPadButton::buttonNameChanged, this, &SetJoystick::propogateSetVDPadButtonNameChange); emit setVDPadButtonNameChange(button->getDPad()->getIndex(), button->getJoyNumber()); connect(button, &JoyDPadButton::buttonNameChanged, this, &SetJoystick::propogateSetVDPadButtonNameChange); } void SetJoystick::propogateSetAxisNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxis *axis = qobject_cast(sender()); disconnect(axis, &JoyAxis::axisNameChanged, this, &SetJoystick::propogateSetAxisNameChange); emit setAxisNameChange(axis->getIndex()); connect(axis, &JoyAxis::axisNameChanged, this, &SetJoystick::propogateSetAxisNameChange); } void SetJoystick::propogateSetStickNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStick *stick = qobject_cast(sender()); disconnect(stick, &JoyControlStick::stickNameChanged, this, &SetJoystick::propogateSetStickNameChange); emit setStickNameChange(stick->getIndex()); connect(stick, &JoyControlStick::stickNameChanged, this, &SetJoystick::propogateSetStickNameChange); } void SetJoystick::propogateSetDPadNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyDPad *dpad = qobject_cast(sender()); disconnect(dpad, &JoyDPad::dpadNameChanged, this, &SetJoystick::propogateSetDPadButtonNameChange); emit setDPadNameChange(dpad->getIndex()); connect(dpad, &JoyDPad::dpadNameChanged, this, &SetJoystick::propogateSetDPadButtonNameChange); } void SetJoystick::propogateSetVDPadNameChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); VDPad *vdpad = qobject_cast(sender()); disconnect(vdpad, &VDPad::dpadNameChanged, this, &SetJoystick::propogateSetVDPadNameChange); emit setVDPadNameChange(vdpad->getIndex()); connect(vdpad, &VDPad::dpadNameChanged, this, &SetJoystick::propogateSetVDPadNameChange); } void SetJoystick::setIgnoreEventState(bool ignore) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator iter(getButtons()); while (iter.hasNext()) { JoyButton *button = iter.next().value(); if (button != nullptr) button->setIgnoreEventState(ignore); } QHashIterator iter2(axes); while (iter2.hasNext()) { JoyAxis *axis = iter2.next().value(); if (axis != nullptr) { JoyAxisButton *naxisbutton = axis->getNAxisButton(); naxisbutton->setIgnoreEventState(ignore); JoyAxisButton *paxisbutton = axis->getPAxisButton(); paxisbutton->setIgnoreEventState(ignore); } } QHashIterator iter3(getHats()); while (iter3.hasNext()) { JoyDPad *dpad = iter3.next().value(); if (dpad != nullptr) { QHash *dpadbuttons = dpad->getButtons(); QHashIterator iterdpadbuttons(*dpadbuttons); while (iterdpadbuttons.hasNext()) { JoyDPadButton *dpadbutton = iterdpadbuttons.next().value(); if (dpadbutton) dpadbutton->setIgnoreEventState(ignore); } } } QHashIterator iter4(getSticks()); while (iter4.hasNext()) { JoyControlStick *stick = iter4.next().value(); if (stick != nullptr) { QHash *stickButtons = stick->getButtons(); QHashIterator iterstickbuttons(*stickButtons); while (iterstickbuttons.hasNext()) { JoyControlStickButton *stickbutton = iterstickbuttons.next().value(); stickbutton->setIgnoreEventState(ignore); } } } QHashIterator iter5(getVdpads()); while (iter5.hasNext()) { VDPad *vdpad = iter5.next().value(); if (vdpad != nullptr) { QHash *dpadbuttons = vdpad->getButtons(); QHashIterator itervdpadbuttons(*dpadbuttons); while (itervdpadbuttons.hasNext()) { JoyDPadButton *dpadbutton = itervdpadbuttons.next().value(); dpadbutton->setIgnoreEventState(ignore); } } } } void SetJoystick::propogateSetAxisActivated(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxis *axis = qobject_cast(sender()); // static_cast emit setAxisActivated(m_index, axis->getIndex(), value); } void SetJoystick::propogateSetAxisReleased(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxis *axis = qobject_cast(sender()); // static_cast emit setAxisReleased(m_index, axis->getIndex(), value); } void SetJoystick::enableButtonConnections(JoyButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(button, &JoyButton::setChangeActivated, this, &SetJoystick::propogateSetChange); connect(button, &JoyButton::setAssignmentChanged, this, &SetJoystick::propogateSetButtonAssociation); connect(button, &JoyButton::clicked, this, &SetJoystick::propogateSetButtonClick, Qt::QueuedConnection); connect(button, &JoyButton::clicked, m_device, &InputDevice::buttonClickEvent, Qt::QueuedConnection); connect(button, &JoyButton::released, this, &SetJoystick::propogateSetButtonRelease); connect(button, &JoyButton::released, m_device, &InputDevice::buttonReleaseEvent); connect(button, &JoyButton::buttonNameChanged, this, &SetJoystick::propogateSetButtonNameChange); } void SetJoystick::enableAxisConnections(JoyAxis *axis) { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(axis, &JoyAxis::throttleChangePropogated, this, &SetJoystick::propogateSetAxisThrottleSetting); connect(axis, &JoyAxis::axisNameChanged, this, &SetJoystick::propogateSetAxisNameChange); connect(axis, &JoyAxis::active, this, &SetJoystick::propogateSetAxisActivated); connect(axis, &JoyAxis::released, this, &SetJoystick::propogateSetAxisReleased); JoyAxisButton *button = axis->getNAxisButton(); connect(button, &JoyAxisButton::setChangeActivated, this, &SetJoystick::propogateSetChange); connect(button, &JoyAxisButton::setAssignmentChanged, this, &SetJoystick::propogateSetAxisButtonAssociation); connect(button, &JoyAxisButton::clicked, this, &SetJoystick::propogateSetAxisButtonClick, Qt::QueuedConnection); connect(button, &JoyAxisButton::released, this, &SetJoystick::propogateSetAxisButtonRelease, Qt::QueuedConnection); connect(button, &JoyAxisButton::buttonNameChanged, this, &SetJoystick::propogateSetAxisButtonNameChange); button = axis->getPAxisButton(); connect(button, &JoyAxisButton::setChangeActivated, this, &SetJoystick::propogateSetChange); connect(button, &JoyAxisButton::setAssignmentChanged, this, &SetJoystick::propogateSetAxisButtonAssociation); connect(button, &JoyAxisButton::clicked, this, &SetJoystick::propogateSetAxisButtonClick, Qt::QueuedConnection); connect(button, &JoyAxisButton::released, this, &SetJoystick::propogateSetAxisButtonRelease, Qt::QueuedConnection); connect(button, &JoyAxisButton::buttonNameChanged, this, &SetJoystick::propogateSetAxisButtonNameChange); } void SetJoystick::enableHatConnections(JoyDPad *dpad) { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(dpad, &JoyDPad::dpadNameChanged, this, &SetJoystick::propogateSetDPadNameChange); QHash *buttons = dpad->getJoyButtons(); QHashIterator iter(*buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); connect(button, &JoyDPadButton::setChangeActivated, this, &SetJoystick::propogateSetChange); connect(button, &JoyDPadButton::setAssignmentChanged, this, &SetJoystick::propogateSetDPadButtonAssociation); connect(button, &JoyDPadButton::clicked, this, &SetJoystick::propogateSetDPadButtonClick, Qt::QueuedConnection); connect(button, &JoyDPadButton::clicked, m_device, &InputDevice::dpadButtonClickEvent, Qt::QueuedConnection); connect(button, &JoyDPadButton::released, this, &SetJoystick::propogateSetDPadButtonRelease, Qt::QueuedConnection); connect(button, &JoyDPadButton::released, m_device, &InputDevice::dpadButtonReleaseEvent, Qt::QueuedConnection); connect(button, &JoyDPadButton::buttonNameChanged, this, &SetJoystick::propogateSetDPadButtonNameChange); } } InputDevice *SetJoystick::getInputDevice() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_device; } void SetJoystick::setName(QString name) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (name.length() <= GlobalVariables::SetJoystick::MAXNAMELENGTH) { m_name = name; emit propertyUpdated(); } else { name.truncate(GlobalVariables::SetJoystick::MAXNAMELENGTH - 3); // Truncate name to 27 characters. Add ellipsis at the end. m_name = QString(name).append("..."); emit propertyUpdated(); } } QString SetJoystick::getName() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return m_name; } void SetJoystick::copyAssignments(SetJoystick *destSet) { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < m_device->getNumberAxes(); i++) { JoyAxis *sourceAxis = axes.value(i); JoyAxis *destAxis = destSet->axes.value(i); if (sourceAxis && destAxis) sourceAxis->copyAssignments(destAxis); } QHashIterator stickIter(getSticks()); while (stickIter.hasNext()) { stickIter.next(); int index = stickIter.key(); JoyControlStick *sourceStick = stickIter.value(); JoyControlStick *destStick = destSet->getSticks().value(index); if (sourceStick && destStick) sourceStick->copyAssignments(destStick); } for (int i = 0; i < m_device->getNumberHats(); i++) { JoyDPad *sourceDPad = getHats().value(i); JoyDPad *destDPad = destSet->getHats().value(i); if (sourceDPad && destDPad) sourceDPad->copyAssignments(destDPad); } QHashIterator vdpadIter(getVdpads()); while (vdpadIter.hasNext()) { vdpadIter.next(); int index = vdpadIter.key(); VDPad *sourceVDpad = vdpadIter.value(); VDPad *destVDPad = destSet->getVdpads().value(index); if (sourceVDpad && destVDPad) sourceVDpad->copyAssignments(destVDPad); } for (int i = 0; i < m_device->getNumberButtons(); i++) { JoyButton *sourceButton = getButtons().value(i); JoyButton *destButton = destSet->getButtons().value(i); if (sourceButton && destButton) sourceButton->copyAssignments(destButton); } } QString SetJoystick::getSetLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (!m_name.isEmpty()) temp = tr("Set %1: %2").arg(m_index + 1).arg(m_name); else temp = tr("Set %1").arg(m_index + 1); return temp; } void SetJoystick::establishPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); connect(this, &SetJoystick::propertyUpdated, getInputDevice(), &InputDevice::profileEdited); } void SetJoystick::disconnectPropertyUpdatedConnection() { qInstallMessageHandler(MessageHandler::myMessageOutput); disconnect(this, &SetJoystick::propertyUpdated, getInputDevice(), &InputDevice::profileEdited); } /** * @brief Raise the dead zones for axes. Used when launching * the controller mapping window. */ void SetJoystick::raiseAxesDeadZones(int deadZone) { qInstallMessageHandler(MessageHandler::myMessageOutput); int tempDeadZone = deadZone; if ((deadZone <= 0) || (deadZone > 32767)) tempDeadZone = GlobalVariables::SetJoystick::RAISEDDEADZONE; QHashIterator axisIter(axes); while (axisIter.hasNext()) { JoyAxis *temp = axisIter.next().value(); temp->disconnectPropertyUpdatedConnection(); temp->setDeadZone(tempDeadZone); temp->establishPropertyUpdatedConnection(); } } void SetJoystick::currentAxesDeadZones(QList *axesDeadZones) { qInstallMessageHandler(MessageHandler::myMessageOutput); QHashIterator axisIter(axes); while (axisIter.hasNext()) { JoyAxis *temp = axisIter.next().value(); axesDeadZones->append(temp->getDeadZone()); } } void SetJoystick::setAxesDeadZones(QList *axesDeadZones) { qInstallMessageHandler(MessageHandler::myMessageOutput); QListIterator iter(*axesDeadZones); int axisNum = 0; while (iter.hasNext()) { int deadZoneValue = iter.next(); if (axes.contains(axisNum)) { JoyAxis *temp = getJoyAxis(axisNum); temp->disconnectPropertyUpdatedConnection(); temp->setDeadZone(deadZoneValue); temp->establishPropertyUpdatedConnection(); } axisNum++; } } void SetJoystick::setAxisThrottle(int axisNum, JoyAxis::ThrottleTypes throttle) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (axes.contains(axisNum)) { JoyAxis *temp = axes.value(axisNum); temp->setInitialThrottle(throttle); } } QHash *SetJoystick::getAxes() { return &axes; } QHash const &SetJoystick::getButtons() const { return m_buttons; } QHash const &SetJoystick::getHats() const { return hats; } QHash const &SetJoystick::getSticks() const { return sticks; } QHash const &SetJoystick::getVdpads() const { return vdpads; } AntiMicroX-antimicrox-2888bf6/src/setjoystick.h000066400000000000000000000206761377703515000216110ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SETJOYSTICK_H #define SETJOYSTICK_H #include "joyaxis.h" #include "xml/setjoystickxml.h" class InputDevice; class JoyButton; class JoyDPad; class JoyControlStick; class VDPad; class SetJoystick : public SetJoystickXml { Q_OBJECT public: explicit SetJoystick(InputDevice *device, int index, QObject *parent = 0); explicit SetJoystick(InputDevice *device, int index, bool runreset, QObject *parent = 0); ~SetJoystick(); JoyAxis *getJoyAxis(int index) const; JoyButton *getJoyButton(int index) const; JoyDPad *getJoyDPad(int index) const; JoyControlStick *getJoyStick(int index) const; VDPad *getVDPad(int index) const; int getNumberButtons() const; int getNumberAxes() const; int getNumberHats() const; int getNumberSticks() const; int getNumberVDPads() const; QHash const &getButtons() const; QHash const &getHats() const; QHash const &getSticks() const; QHash const &getVdpads() const; QHash *getAxes(); int getIndex() const; int getRealIndex() const; virtual void refreshButtons(); // SetButton class virtual void refreshAxes(); // SetAxis class virtual void refreshHats(); // SetHat class void release(); void addControlStick(int index, JoyControlStick *stick); // SetStick class void removeControlStick(int index); // SetStick class void addVDPad(int index, VDPad *vdpad); // SetVDPad class void removeVDPad(int index); // SetVDPad class void setIgnoreEventState(bool ignore); InputDevice *getInputDevice() const; void setName(QString name); QString getName() const; QString getSetLabel(); void raiseAxesDeadZones(int deadZone = 0); // SetAxis class void currentAxesDeadZones(QList *axesDeadZones); // SetAxis class void setAxesDeadZones(QList *axesDeadZones); // SetAxis class void setAxisThrottle(int axisNum, JoyAxis::ThrottleTypes throttle); // SetAxis class QList const &getLastClickedButtons() const; void removeAllBtnFromQueue(); int getCountBtnInList(QString partialName); bool isSetEmpty(); protected: void deleteButtons(); // SetButton class void deleteAxes(); // SetAxis class void deleteHats(); // SetHat class void deleteSticks(); // SetStick class void deleteVDpads(); // SetVDPad class void enableButtonConnections(JoyButton *button); // SetButton class void enableAxisConnections(JoyAxis *axis); // SetAxis class void enableHatConnections(JoyDPad *dpad); // SetHat class signals: void setChangeActivated(int index); void setAssignmentButtonChanged(int button, int originset, int newset, int mode); // SetButton class void setAssignmentAxisChanged(int button, int axis, int originset, int newset, int mode); // SetAxis class void setAssignmentStickChanged(int button, int stick, int originset, int newset, int mode); // SetStick class void setAssignmentDPadChanged(int button, int dpad, int originset, int newset, int mode); // SetHat class void setAssignmentVDPadChanged(int button, int dpad, int originset, int newset, int mode); // SetVDPad class void setAssignmentAxisThrottleChanged(int axis, int originset); // SetAxis class void setButtonClick(int index, int button); // SetButton class void setButtonRelease(int index, int button); // SetButton class void setAxisButtonClick(int setindex, int axis, int button); // SetAxis class void setAxisButtonRelease(int setindex, int axis, int button); // SetAxis class void setAxisActivated(int setindex, int axis, int value); // SetAxis class void setAxisReleased(int setindex, int axis, int value); // SetAxis class void setStickButtonClick(int setindex, int stick, int button); // SetStick class void setStickButtonRelease(int setindex, int stick, int button); // SetStick class void setDPadButtonClick(int setindex, int dpad, int button); // SetHat class void setDPadButtonRelease(int setindex, int dpad, int button); // SetHat class void setButtonNameChange(int index); // SetButton class void setAxisButtonNameChange(int axisIndex, int buttonIndex); // SetAxis class void setStickButtonNameChange(int stickIndex, int buttonIndex); // SetStick class void setDPadButtonNameChange(int dpadIndex, int buttonIndex); // SetHat class void setVDPadButtonNameChange(int vdpadIndex, int buttonIndex); // SetVDPad class void setAxisNameChange(int axisIndex); // SetAxis class void setStickNameChange(int stickIndex); // SetStick class void setDPadNameChange(int dpadIndex); // SetHat class void setVDPadNameChange(int vdpadIndex); // SetVDPad class void propertyUpdated(); public slots: virtual void reset(); void copyAssignments(SetJoystick *destSet); void propogateSetChange(int index); void propogateSetButtonAssociation(int button, int newset, int mode); // SetButton class void propogateSetAxisButtonAssociation(int button, int axis, int newset, int mode); // SetAxis class void propogateSetStickButtonAssociation(int button, int stick, int newset, int mode); // SetStick class void propogateSetDPadButtonAssociation(int button, int dpad, int newset, int mode); // SetHat class void propogateSetVDPadButtonAssociation(int button, int dpad, int newset, int mode); // SetVDPad class void establishPropertyUpdatedConnection(); void disconnectPropertyUpdatedConnection(); protected slots: void propogateSetAxisThrottleSetting(int index); // SetAxis class void propogateSetButtonClick(int button); // SetButton class void propogateSetButtonRelease(int button); // SetButton class void propogateSetAxisButtonClick(int button); // SetAxis class void propogateSetAxisButtonRelease(int button); // SetAxis class void propogateSetStickButtonClick(int button); // SetStick class void propogateSetStickButtonRelease(int button); // SetStick class void propogateSetDPadButtonClick(int button); // SetHat class void propogateSetDPadButtonRelease(int button); // SetHat class void propogateSetAxisActivated(int value); // SetAxis class void propogateSetAxisReleased(int value); // SetAxis class void propogateSetButtonNameChange(); // SetButton class void propogateSetAxisButtonNameChange(); // SetAxis class void propogateSetStickButtonNameChange(); // SetStick class void propogateSetDPadButtonNameChange(); // SetHat class void propogateSetVDPadButtonNameChange(); // SetVDPad class void propogateSetAxisNameChange(); // SetAxis class void propogateSetStickNameChange(); // SetStick class void propogateSetDPadNameChange(); // SetHat class void propogateSetVDPadNameChange(); // SetVDPad class private: QHash m_buttons; QHash axes; QHash hats; QHash sticks; QHash vdpads; QList lastClickedButtons; int m_index; InputDevice *m_device; QString m_name; }; Q_DECLARE_METATYPE(SetJoystick *) #endif // SETJOYSTICK_H AntiMicroX-antimicrox-2888bf6/src/setnamesdialog.cpp000066400000000000000000000045111377703515000225560ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "setnamesdialog.h" #include "ui_setnamesdialog.h" #include "globalvariables.h" #include "inputdevice.h" #include "messagehandler.h" #include #include #include SetNamesDialog::SetNamesDialog(InputDevice *device, QWidget *parent) : QDialog(parent) , ui(new Ui::SetNamesDialog) { ui->setupUi(this); qInstallMessageHandler(MessageHandler::myMessageOutput); setAttribute(Qt::WA_DeleteOnClose); this->device = device; auto joysList = device->getJoystick_sets(); for (int i = 0; i < joysList.size(); i++) { auto name = joysList[i]->getName(); ui->setNamesTableWidget->setItem(i, 0, new QTableWidgetItem(name)); } connect(this, &SetNamesDialog::accepted, this, &SetNamesDialog::saveSetNameChanges); } SetNamesDialog::~SetNamesDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); delete ui; } void SetNamesDialog::saveSetNameChanges() { qInstallMessageHandler(MessageHandler::myMessageOutput); for (int i = 0; i < ui->setNamesTableWidget->rowCount(); i++) { QTableWidgetItem *setNameItem = ui->setNamesTableWidget->item(i, 0); QString setNameText = setNameItem->text(); QString oldSetNameText = device->getSetJoystick(i)->getName(); if (setNameText != oldSetNameText) qDebug() << "Set number: " << i << " Renamed to: " << setNameText; device->getSetJoystick(i)->setName(setNameText); } } InputDevice *SetNamesDialog::getDevice() const { return device; } AntiMicroX-antimicrox-2888bf6/src/setnamesdialog.h000066400000000000000000000024411377703515000222230ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SETNAMESDIALOG_H #define SETNAMESDIALOG_H #include class InputDevice; class QWidget; namespace Ui { class SetNamesDialog; } class SetNamesDialog : public QDialog { Q_OBJECT public: explicit SetNamesDialog(InputDevice *device, QWidget *parent = nullptr); ~SetNamesDialog(); InputDevice *getDevice() const; private: Ui::SetNamesDialog *ui; InputDevice *device; private slots: void saveSetNameChanges(); }; #endif // SETNAMESDIALOG_H AntiMicroX-antimicrox-2888bf6/src/setnamesdialog.ui000066400000000000000000000076111377703515000224150ustar00rootroot00000000000000 SetNamesDialog 0 0 535 399 Set Name Settings true 1 QAbstractItemView::SingleSelection true Qt::SolidLine false true false true true true 30 18 Set 1 Set 2 Set 3 Set 4 Set 5 Set 6 Set 7 Set 8 Name Qt::Vertical QSizePolicy::Fixed 20 20 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() SetNamesDialog accept() 248 254 157 274 buttonBox rejected() SetNamesDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/simplekeygrabberbutton.cpp000066400000000000000000000244501377703515000243460ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "simplekeygrabberbutton.h" #include #include #include #include "antkeymapper.h" #include "event.h" #include "eventhandlerfactory.h" #include "messagehandler.h" #include #include #include #include SimpleKeyGrabberButton::SimpleKeyGrabberButton(QWidget *parent) : QPushButton(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); grabNextAction = false; grabbingWheel = false; edited = false; this->installEventFilter(this); } void SimpleKeyGrabberButton::keyPressEvent(QKeyEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); // Do not allow closing of dialog using Escape key if (event->key() == Qt::Key_Escape) return; QPushButton::keyPressEvent(event); } bool SimpleKeyGrabberButton::eventFilter(QObject *obj, QEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(obj); int controlcode = 0; if (grabNextAction && (event->type() == QEvent::MouseButtonRelease)) { QMouseEvent *mouseEve = static_cast(event); if (mouseEve->button() == Qt::RightButton) controlcode = 3; else if (mouseEve->button() == Qt::MiddleButton) controlcode = 2; else controlcode = mouseEve->button(); buttonslot.setSlotCode(controlcode); buttonslot.setSlotMode(JoyButtonSlot::JoyMouseButton); refreshButtonLabel(); edited = true; releaseMouse(); releaseKeyboard(); grabNextAction = grabbingWheel = false; emit buttonCodeChanged(controlcode); } else if (grabNextAction && (event->type() == static_cast(7))) { QKeyEvent *keyEve = static_cast(event); int tempcode = keyEve->nativeScanCode(); int virtualactual = keyEve->nativeVirtualKey(); BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); int finalvirtual = 0; int checkalias = 0; #if defined(WITH_X11) if (QApplication::platformName() == QStringLiteral("xcb")) { finalvirtual = X11KeyCodeToX11KeySym(tempcode); // Obtain group 1 X11 keysym. Removes effects from modifiers. #ifdef WITH_UINPUT if (handler->getIdentifier() == "uinput") { QtKeyMapperBase *x11KeyMapper = AntKeyMapper::getInstance()->getNativeKeyMapper(); // Find Qt Key corresponding to X11 KeySym. checkalias = x11KeyMapper->returnQtKey(finalvirtual); finalvirtual = AntKeyMapper::getInstance()->returnVirtualKey( checkalias); // Find corresponding Linux input key for the Qt key. } #endif #ifdef WITH_XTEST if (handler->getIdentifier() == "xtest") checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); // Check for alias against group 1 keysym. #endif } else { // Not running on xcb platform. finalvirtual = tempcode; checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); } #else if (QApplication::platformName() == QStringLiteral("xcb")) { finalvirtual = AntKeyMapper::getInstance()->returnVirtualKey(keyEve->key()); checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); } else { // Not running on xcb platform. finalvirtual = tempcode; checkalias = AntKeyMapper::getInstance()->returnQtKey(finalvirtual); } #endif controlcode = tempcode; bool valueUpdated = false; qDebug() << "slot string for simple key grab button is: " << buttonslot.getSlotString(); if ((keyEve->modifiers() & Qt::ControlModifier) && (keyEve->key() == Qt::Key_X)) { controlcode = 0; refreshButtonLabel(); } else if (controlcode <= 0) { controlcode = 0; setText(""); valueUpdated = true; edited = true; } else if ((checkalias > 0) && (finalvirtual > 0)) { buttonslot.setSlotCode(finalvirtual, checkalias); buttonslot.setSlotMode(JoyButtonSlot::JoyKeyboard); setText(keysymToKeyString(finalvirtual, checkalias).toUpper()); edited = true; valueUpdated = true; } else if (virtualactual > 0) { buttonslot.setSlotCode(virtualactual); buttonslot.setSlotMode(JoyButtonSlot::JoyKeyboard); setText(keysymToKeyString(virtualactual).toUpper()); edited = true; valueUpdated = true; } grabNextAction = false; grabbingWheel = false; releaseMouse(); releaseKeyboard(); if (valueUpdated) emit buttonCodeChanged(controlcode); } else if (grabNextAction && (event->type() == QEvent::Wheel) && !grabbingWheel) { grabbingWheel = true; } else if (grabNextAction && (event->type() == QEvent::Wheel)) { QWheelEvent *wheelEve = static_cast(event); QString text = QString(tr("Mouse")).append(" "); if ((wheelEve->orientation() == Qt::Vertical) && (wheelEve->delta() >= 120)) { controlcode = 4; } else if ((wheelEve->orientation() == Qt::Vertical) && (wheelEve->delta() <= -120)) { controlcode = 5; } else if ((wheelEve->orientation() == Qt::Horizontal) && (wheelEve->delta() >= 120)) { controlcode = 6; } else if ((wheelEve->orientation() == Qt::Horizontal) && (wheelEve->delta() <= -120)) { controlcode = 7; } if (controlcode > 0) { text = text.append(QString::number(controlcode)); setText(text); grabNextAction = false; grabbingWheel = false; edited = true; releaseMouse(); releaseKeyboard(); buttonslot.setSlotCode(controlcode); buttonslot.setSlotMode(JoyButtonSlot::JoyMouseButton); emit buttonCodeChanged(controlcode); } } else if (event->type() == QEvent::MouseButtonRelease) { QMouseEvent *mouseEve = static_cast(event); if (mouseEve->button() == Qt::LeftButton) { grabNextAction = true; setText("..."); setFocus(); grabKeyboard(); grabMouse(); } } return false; } void SimpleKeyGrabberButton::setValue(int value, int alias, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); buttonslot.setSlotCode(value, alias); buttonslot.setSlotMode(mode); edited = true; setText(buttonslot.getSlotString()); } void SimpleKeyGrabberButton::setValue(int value, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); buttonslot.setSlotCode(value); buttonslot.setSlotMode(mode); edited = true; setText(buttonslot.getSlotString()); } void SimpleKeyGrabberButton::setValue(QString value, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (mode) { case JoyButtonSlot::JoyLoadProfile: case JoyButtonSlot::JoyTextEntry: case JoyButtonSlot::JoyExecute: { buttonslot.setTextData(value); buttonslot.setSlotMode(mode); edited = true; break; } case JoyButtonSlot::JoyMix: { break; } default: { break; } } setText(buttonslot.getSlotString()); } void SimpleKeyGrabberButton::setValues(QString value, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (mode) { case JoyButtonSlot::JoyMix: { // buttonslot.setSlotCode(-1); buttonslot.setTextData(value); buttonslot.setSlotMode(JoyButtonSlot::JoyMix); edited = true; break; } default: { break; } } setText(buttonslot.getSlotString()); } void SimpleKeyGrabberButton::setValues(QString value, QList *jbtn, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (mode) { case JoyButtonSlot::JoyMix: { // buttonslot.setSlotCode(-1); buttonslot.setTextData(value); buttonslot.setSlotMode(JoyButtonSlot::JoyMix); buttonslot.setMixSlots(jbtn); edited = true; break; } default: { break; } } setText(buttonslot.getSlotString()); } JoyButtonSlot *SimpleKeyGrabberButton::getValue() { qInstallMessageHandler(MessageHandler::myMessageOutput); return &buttonslot; } JoyButtonSlot &SimpleKeyGrabberButton::getValueNonPointer() { qInstallMessageHandler(MessageHandler::myMessageOutput); return buttonslot; } void SimpleKeyGrabberButton::setValue(JoyButtonSlot *jbS) { buttonslot = jbS; } void SimpleKeyGrabberButton::refreshButtonLabel() { qInstallMessageHandler(MessageHandler::myMessageOutput); setText(buttonslot.getSlotString()); updateGeometry(); } bool SimpleKeyGrabberButton::isEdited() { qInstallMessageHandler(MessageHandler::myMessageOutput); return edited; } bool SimpleKeyGrabberButton::isGrabbing() { qInstallMessageHandler(MessageHandler::myMessageOutput); return grabNextAction; } AntiMicroX-antimicrox-2888bf6/src/simplekeygrabberbutton.h000066400000000000000000000043671377703515000240200ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SIMPLEKEYGRABBERBUTTON_H #define SIMPLEKEYGRABBERBUTTON_H #include "joybuttonslot.h" #include class QKeyEvent; class QEvent; class QWidget; class SimpleKeyGrabberButton : public QPushButton { Q_OBJECT public: explicit SimpleKeyGrabberButton(QWidget *parent = nullptr); void setValue(int value, int alias, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); // (.., unsigned) void setValue(int value, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void setValue(QString value, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyLoadProfile); void setValues(QString value, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyMix); void setValues(QString value, QList *jbtn, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyMix); JoyButtonSlot *getValue(); JoyButtonSlot &getValueNonPointer(); void setValue(JoyButtonSlot *jbS); bool isEdited(); bool isGrabbing(); protected: virtual void keyPressEvent(QKeyEvent *event); virtual bool eventFilter(QObject *obj, QEvent *event); signals: void buttonCodeChanged(int value); public slots: void refreshButtonLabel(); private: bool grabNextAction; bool grabbingWheel; bool edited; JoyButtonSlot buttonslot; }; Q_DECLARE_METATYPE(SimpleKeyGrabberButton *) #endif // SIMPLEKEYGRABBERBUTTON_H AntiMicroX-antimicrox-2888bf6/src/slotitemlistwidget.cpp000066400000000000000000000037731377703515000235300ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "slotitemlistwidget.h" #include "messagehandler.h" #include "simplekeygrabberbutton.h" #include #include #include #include SlotItemListWidget::SlotItemListWidget(QWidget *parent) : QListWidget(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } void SlotItemListWidget::insertItems(int row, QList items) { for (auto el : items) { insertItem(row, el); row++; } } void SlotItemListWidget::keyPressEvent(QKeyEvent *event) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool propogate = true; QListWidgetItem *currentItem = this->item(this->currentRow()); SimpleKeyGrabberButton *tempbutton = nullptr; if (currentItem != nullptr) tempbutton = currentItem->data(Qt::UserRole).value(); if (tempbutton != nullptr && tempbutton->isGrabbing()) { switch (event->key()) { case Qt::Key_Home: case Qt::Key_End: { propogate = false; break; } default: break; } } if (propogate) QListWidget::keyPressEvent(event); } AntiMicroX-antimicrox-2888bf6/src/slotitemlistwidget.h000066400000000000000000000023161377703515000231650ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SLOTITEMLISTWIDGET_H #define SLOTITEMLISTWIDGET_H #include class QWidget; class QKeyEvent; class SlotItemListWidget : public QListWidget { Q_OBJECT public: explicit SlotItemListWidget(QWidget *parent = nullptr); void insertItems(int row, QList items); protected: virtual void keyPressEvent(QKeyEvent *event); }; #endif // SLOTITEMLISTWIDGET_H AntiMicroX-antimicrox-2888bf6/src/springmousemoveinfo.h000066400000000000000000000025711377703515000233460ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SPRINGMOUSEMOVEINFO_H #define SPRINGMOUSEMOVEINFO_H namespace PadderCommon { typedef struct _springModeInfo { // Displacement of the X axis double displacementX; // Displacement of the Y axis double displacementY; // Width and height of the spring mode box int width; // unsigned int height; // unsigned // Should the cursor not move around the center // of the screen. bool relative; int screen; double springDeadX; double springDeadY; } springModeInfo; } // namespace PadderCommon #endif // SPRINGMOUSEMOVEINFO_H AntiMicroX-antimicrox-2888bf6/src/stickpushbuttongroup.cpp000066400000000000000000000162421377703515000241110ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "stickpushbuttongroup.h" #include "buttoneditdialog.h" #include "inputdevice.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joycontrolstick.h" #include "joycontrolstickbuttonpushbutton.h" #include "joycontrolstickeditdialog.h" #include "joycontrolstickpushbutton.h" #include "messagehandler.h" #include #include #include StickPushButtonGroup::StickPushButtonGroup(JoyControlStick *stick, bool keypadUnlocked, bool displayNames, QWidget *parent) : QGridLayout(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->keypadUnlocked = keypadUnlocked; this->stick = stick; this->displayNames = displayNames; generateButtons(); changeButtonLayout(); connect(stick, &JoyControlStick::joyModeChanged, this, &StickPushButtonGroup::changeButtonLayout); } void StickPushButtonGroup::generateButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickButtonPushButton *pushbutton = nullptr; upLeftButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickLeftUp, 0, 0); upButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickUp, 0, 1); upRightButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickRightUp, 0, 2); leftButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickLeft, 1, 0); stickWidget = new JoyControlStickPushButton(stick, displayNames, parentWidget()); stickWidget->setIcon( QIcon::fromTheme(QString::fromUtf8("games_config_options"), QIcon(":/icons/actions/games_config_options.png"))); connect(stickWidget, &JoyControlStickPushButton::clicked, this, &StickPushButtonGroup::showStickDialog); addWidget(stickWidget, 1, 1); rightButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickRight, 1, 2); downLeftButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickLeftDown, 2, 0); downButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickDown, 2, 1); downRightButton = generateBtnToGrid(pushbutton, stick, JoyControlStick::StickRightDown, 2, 2); } JoyControlStickButtonPushButton * StickPushButtonGroup::generateBtnToGrid(JoyControlStickButtonPushButton *pushbutton, JoyControlStick *stick, JoyStickDirectionsType::JoyStickDirections stickValue, int gridRow, int gridCol) { JoyControlStickButton *button = stick->getButtons()->value(stickValue); pushbutton = new JoyControlStickButtonPushButton(button, displayNames, parentWidget()); connect(pushbutton, &JoyControlStickButtonPushButton::clicked, this, [this, pushbutton] { openStickButtonDialog(pushbutton); }); button->establishPropertyUpdatedConnections(); connect(button, &JoyControlStickButton::slotsChanged, this, &StickPushButtonGroup::propogateSlotsChanged); addWidget(pushbutton, gridRow, gridCol); return pushbutton; } void StickPushButtonGroup::changeButtonLayout() { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((stick->getJoyMode() == JoyControlStick::StandardMode) || (stick->getJoyMode() == JoyControlStick::EightWayMode) || (stick->getJoyMode() == JoyControlStick::FourWayCardinal)) { upButton->setVisible(true); downButton->setVisible(true); leftButton->setVisible(true); rightButton->setVisible(true); } else { upButton->setVisible(false); downButton->setVisible(false); leftButton->setVisible(false); rightButton->setVisible(false); } if ((stick->getJoyMode() == JoyControlStick::EightWayMode) || (stick->getJoyMode() == JoyControlStick::FourWayDiagonal)) { upLeftButton->setVisible(true); upRightButton->setVisible(true); downLeftButton->setVisible(true); downRightButton->setVisible(true); } else { upLeftButton->setVisible(false); upRightButton->setVisible(false); downLeftButton->setVisible(false); downRightButton->setVisible(false); } } void StickPushButtonGroup::propogateSlotsChanged() { qInstallMessageHandler(MessageHandler::myMessageOutput); emit buttonSlotChanged(); } JoyControlStick *StickPushButtonGroup::getStick() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return stick; } void StickPushButtonGroup::openStickButtonDialog(JoyControlStickButtonPushButton *pushbutton) { qInstallMessageHandler(MessageHandler::myMessageOutput); ButtonEditDialog *dialog = new ButtonEditDialog(pushbutton->getButton(), stick->getParentSet()->getInputDevice(), keypadUnlocked, parentWidget()); dialog->show(); } void StickPushButtonGroup::showStickDialog() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyControlStickEditDialog *dialog = new JoyControlStickEditDialog(stick, keypadUnlocked, parentWidget()); dialog->show(); } void StickPushButtonGroup::toggleNameDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); displayNames = !displayNames; upButton->toggleNameDisplay(); downButton->toggleNameDisplay(); leftButton->toggleNameDisplay(); rightButton->toggleNameDisplay(); upLeftButton->toggleNameDisplay(); upRightButton->toggleNameDisplay(); downLeftButton->toggleNameDisplay(); downRightButton->toggleNameDisplay(); stickWidget->toggleNameDisplay(); } bool StickPushButtonGroup::ifDisplayNames() const { return displayNames; } JoyControlStickButtonPushButton *StickPushButtonGroup::getUpButton() const { return upButton; } JoyControlStickButtonPushButton *StickPushButtonGroup::getDownButton() const { return downButton; } JoyControlStickButtonPushButton *StickPushButtonGroup::getLeftButton() const { return leftButton; } JoyControlStickButtonPushButton *StickPushButtonGroup::getRightButton() const { return rightButton; } JoyControlStickButtonPushButton *StickPushButtonGroup::getUpLeftButton() const { return upLeftButton; } JoyControlStickButtonPushButton *StickPushButtonGroup::getUpRightButton() const { return upRightButton; } JoyControlStickButtonPushButton *StickPushButtonGroup::getDownLeftButton() const { return downLeftButton; } JoyControlStickButtonPushButton *StickPushButtonGroup::getDownRightButton() const { return downRightButton; } JoyControlStickPushButton *StickPushButtonGroup::getStickWidget() const { return stickWidget; } AntiMicroX-antimicrox-2888bf6/src/stickpushbuttongroup.h000066400000000000000000000061051377703515000235530ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef STICKPUSHBUTTONGROUP_H #define STICKPUSHBUTTONGROUP_H #include "joycontrolstickdirectionstype.h" #include class JoyControlStick; class QWidget; class JoyControlStickButtonPushButton; class JoyControlStickPushButton; class StickPushButtonGroup : public QGridLayout { Q_OBJECT public: explicit StickPushButtonGroup(JoyControlStick *stick, bool keypadUnlocked, bool displayNames = false, QWidget *parent = nullptr); JoyControlStick *getStick() const; bool ifDisplayNames() const; JoyControlStickButtonPushButton *getUpButton() const; JoyControlStickButtonPushButton *getDownButton() const; JoyControlStickButtonPushButton *getLeftButton() const; JoyControlStickButtonPushButton *getRightButton() const; JoyControlStickButtonPushButton *getUpLeftButton() const; JoyControlStickButtonPushButton *getUpRightButton() const; JoyControlStickButtonPushButton *getDownLeftButton() const; JoyControlStickButtonPushButton *getDownRightButton() const; JoyControlStickPushButton *getStickWidget() const; protected: void generateButtons(); signals: void buttonSlotChanged(); public slots: void changeButtonLayout(); void toggleNameDisplay(); private slots: void propogateSlotsChanged(); void openStickButtonDialog(JoyControlStickButtonPushButton *pushbutton); void showStickDialog(); private: JoyControlStick *stick; bool displayNames; bool keypadUnlocked; JoyControlStickButtonPushButton *upButton; JoyControlStickButtonPushButton *downButton; JoyControlStickButtonPushButton *leftButton; JoyControlStickButtonPushButton *rightButton; JoyControlStickButtonPushButton *upLeftButton; JoyControlStickButtonPushButton *upRightButton; JoyControlStickButtonPushButton *downLeftButton; JoyControlStickButtonPushButton *downRightButton; JoyControlStickPushButton *stickWidget; JoyControlStickButtonPushButton *generateBtnToGrid(JoyControlStickButtonPushButton *pushbutton, JoyControlStick *stick, JoyStickDirectionsType::JoyStickDirections stickValue, int gridRow, int gridCol); }; #endif // STICKPUSHBUTTONGROUP_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/000077500000000000000000000000001377703515000210525ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/uihelpers/advancebuttondialoghelper.cpp000066400000000000000000000064351377703515000270030ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "advancebuttondialoghelper.h" #include "joybutton.h" #include "messagehandler.h" #include AdvanceButtonDialogHelper::AdvanceButtonDialogHelper(JoyButton *button, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(button); this->button = button; } void AdvanceButtonDialogHelper::insertAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->eventReset(); button->insertAssignedSlot(code, alias, index, mode); } void AdvanceButtonDialogHelper::insertAssignedSlot(JoyButtonSlot *newSlot, int index, bool updateActiveString) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->eventReset(); button->insertAssignedSlot(newSlot, index, updateActiveString); } void AdvanceButtonDialogHelper::setAssignedSlot(JoyButtonSlot *otherSlot, int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->eventReset(); button->setAssignedSlot(otherSlot, index); } void AdvanceButtonDialogHelper::setAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->eventReset(); button->setAssignedSlot(code, alias, index, mode); } void AdvanceButtonDialogHelper::removeAssignedSlot(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); int j = 0; qDebug() << "Assigned list slots after joining"; for (auto el : *button->getAssignedSlots()) { qDebug() << j << ")"; qDebug() << "code: " << el->getSlotCode(); qDebug() << "mode: " << el->getSlotMode(); qDebug() << "string: " << el->getSlotString(); j++; } button->eventReset(); j = 0; qDebug() << "Assigned list slots after joining"; for (auto el : *button->getAssignedSlots()) { qDebug() << j << ")"; qDebug() << "code: " << el->getSlotCode(); qDebug() << "mode: " << el->getSlotMode(); qDebug() << "string: " << el->getSlotString(); j++; } button->removeAssignedSlot(index); } void AdvanceButtonDialogHelper::onlyReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); button->eventReset(); } void AdvanceButtonDialogHelper::onlyRemoveAssignedSlot(int index) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->removeAssignedSlot(index); } AntiMicroX-antimicrox-2888bf6/src/uihelpers/advancebuttondialoghelper.h000066400000000000000000000033441377703515000264440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ADVANCEBUTTONDIALOGHELPER_H #define ADVANCEBUTTONDIALOGHELPER_H #include "joybuttonslot.h" class JoyButton; class AdvanceButtonDialogHelper : public QObject { Q_OBJECT public: explicit AdvanceButtonDialogHelper(JoyButton *button, QObject *parent = nullptr); protected: JoyButton *button; public slots: void setAssignedSlot(JoyButtonSlot *otherSlot, int index); void setAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void insertAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void insertAssignedSlot(JoyButtonSlot *newSlot, int index, bool updateActiveString); void removeAssignedSlot(int index); void onlyReset(); void onlyRemoveAssignedSlot(int index); }; #endif // ADVANCEBUTTONDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/buttoneditdialoghelper.cpp000066400000000000000000000044601377703515000263230ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "buttoneditdialoghelper.h" #include "joybutton.h" #include "messagehandler.h" #include ButtonEditDialogHelper::ButtonEditDialogHelper(JoyButton *button, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(button); this->button = button; } ButtonEditDialogHelper::ButtonEditDialogHelper(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); } void ButtonEditDialogHelper::setAssignedSlot(int code, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->clearSlotsEventReset(false); button->setAssignedSlot(code, mode); } void ButtonEditDialogHelper::setAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->clearSlotsEventReset(false); button->setAssignedSlot(code, alias, mode); } void ButtonEditDialogHelper::setAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->clearSlotsEventReset(false); button->setAssignedSlot(code, alias, index, mode); } void ButtonEditDialogHelper::setUseTurbo(bool useTurbo) { qInstallMessageHandler(MessageHandler::myMessageOutput); button->setUseTurbo(useTurbo); } void ButtonEditDialogHelper::setThisButton(JoyButton *btn) { Q_ASSERT(btn); button = btn; } AntiMicroX-antimicrox-2888bf6/src/uihelpers/buttoneditdialoghelper.h000066400000000000000000000032371377703515000257710ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BUTTONEDITDIALOGHELPER_H #define BUTTONEDITDIALOGHELPER_H #include "joybuttonslot.h" class JoyButton; class ButtonEditDialogHelper : public QObject { Q_OBJECT public: explicit ButtonEditDialogHelper(JoyButton *button, QObject *parent = nullptr); explicit ButtonEditDialogHelper(QObject *parent = nullptr); void setThisButton(JoyButton *btn); protected: JoyButton *button; public slots: void setAssignedSlot(int code, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void setAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void setAssignedSlot(int code, int alias, int index, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void setUseTurbo(bool useTurbo); }; #endif // BUTTONEDITDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/dpadcontextmenuhelper.cpp000066400000000000000000000060741377703515000261670ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dpadcontextmenuhelper.h" #include "joybuttonslot.h" #include "messagehandler.h" #include #include #include DPadContextMenuHelper::DPadContextMenuHelper(JoyDPad *dpad, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(dpad); this->dpad = dpad; } void DPadContextMenuHelper::setPendingSlots(QHash *tempSlots) { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); QHashIterator iter(*tempSlots); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); JoyDPadButton::JoyDPadDirections tempDir = iter.key(); pendingSlots.insert(tempDir, slot); } } void DPadContextMenuHelper::clearPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); } void DPadContextMenuHelper::setFromPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getPendingSlots().isEmpty()) { QHashIterator iter(getPendingSlots()); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); if (slot) { JoyDPadButton::JoyDPadDirections tempDir = iter.key(); JoyDPadButton *button = dpad->getJoyButton(tempDir); button->clearSlotsEventReset(false); button->setAssignedSlot(slot->getSlotCode(), slot->getSlotCodeAlias(), slot->getSlotMode()); slot->deleteLater(); } } } } void DPadContextMenuHelper::clearButtonsSlotsEventReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash *buttons = dpad->getButtons(); QHashIterator iter(*buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->clearSlotsEventReset(); } } QHash const &DPadContextMenuHelper::getPendingSlots() { return pendingSlots; } AntiMicroX-antimicrox-2888bf6/src/uihelpers/dpadcontextmenuhelper.h000066400000000000000000000027631377703515000256350ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DPADCONTEXTMENUHELPER_H #define DPADCONTEXTMENUHELPER_H #include "joydpad.h" class JoyButtonSlot; class DPadContextMenuHelper : public QObject { Q_OBJECT public: explicit DPadContextMenuHelper(JoyDPad *dpad, QObject *parent = nullptr); void setPendingSlots(QHash *tempSlots); void clearPendingSlots(); QHash const &getPendingSlots(); public slots: void setFromPendingSlots(); void clearButtonsSlotsEventReset(); private: JoyDPad *dpad; QHash pendingSlots; }; #endif // DPADCONTEXTMENUHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/dpadeditdialoghelper.cpp000066400000000000000000000064061377703515000257220ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dpadeditdialoghelper.h" #include "joybuttonslot.h" #include "messagehandler.h" #include #include DPadEditDialogHelper::DPadEditDialogHelper(JoyDPad *dpad, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(dpad); this->dpad = dpad; } void DPadEditDialogHelper::setPendingSlots(QHash *tempSlots) { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); QHashIterator iter(*tempSlots); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); JoyDPadButton::JoyDPadDirections tempDir = iter.key(); pendingSlots.insert(tempDir, slot); } } void DPadEditDialogHelper::clearPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); } void DPadEditDialogHelper::setFromPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getPendingSlots().isEmpty()) { QHashIterator iter(getPendingSlots()); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); if (slot) { JoyDPadButton::JoyDPadDirections tempDir = iter.key(); JoyDPadButton *button = dpad->getJoyButton(tempDir); button->clearSlotsEventReset(false); button->setAssignedSlot(slot->getSlotCode(), slot->getSlotCodeAlias(), slot->getSlotMode()); slot->deleteLater(); } } } } void DPadEditDialogHelper::clearButtonsSlotsEventReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash *buttons = dpad->getButtons(); QHashIterator iter(*buttons); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); button->clearSlotsEventReset(); } } void DPadEditDialogHelper::updateJoyDPadDelay(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int temp = value * 10; if (dpad->getDPadDelay() != temp) { dpad->setDPadDelay(temp); } } QHash const &DPadEditDialogHelper::getPendingSlots() { return pendingSlots; } AntiMicroX-antimicrox-2888bf6/src/uihelpers/dpadeditdialoghelper.h000066400000000000000000000030261377703515000253620ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DPADEDITDIALOGHELPER_H #define DPADEDITDIALOGHELPER_H #include "joydpad.h" class JoyButtonSlot; class DPadEditDialogHelper : public QObject { Q_OBJECT public: explicit DPadEditDialogHelper(JoyDPad *dpad, QObject *parent = nullptr); void setPendingSlots(QHash *tempSlots); void clearPendingSlots(); QHash const &getPendingSlots(); public slots: void setFromPendingSlots(); void clearButtonsSlotsEventReset(); void updateJoyDPadDelay(int value); private: JoyDPad *dpad; QHash pendingSlots; }; #endif // DPADEDITDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/gamecontrollermappingdialoghelper.cpp000066400000000000000000000047661377703515000305440ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska . */ #include "gamecontrollermappingdialoghelper.h" #include "globalvariables.h" #include "inputdevice.h" #include "messagehandler.h" #include GameControllerMappingDialogHelper::GameControllerMappingDialogHelper(InputDevice *device, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->device = device; } void GameControllerMappingDialogHelper::raiseDeadZones() { qInstallMessageHandler(MessageHandler::myMessageOutput); device->setRawAxisDeadZone(GlobalVariables::InputDevice::RAISEDDEADZONE); device->getActiveSetJoystick()->raiseAxesDeadZones(); } void GameControllerMappingDialogHelper::raiseDeadZones(int deadZone) { qInstallMessageHandler(MessageHandler::myMessageOutput); device->getActiveSetJoystick()->raiseAxesDeadZones(deadZone); device->setRawAxisDeadZone(deadZone); } void GameControllerMappingDialogHelper::setupDeadZones() { qInstallMessageHandler(MessageHandler::myMessageOutput); device->getActiveSetJoystick()->setIgnoreEventState(true); device->getActiveSetJoystick()->release(); device->getActiveSetJoystick()->currentAxesDeadZones(&originalAxesDeadZones); device->getActiveSetJoystick()->raiseAxesDeadZones(); device->setRawAxisDeadZone(GlobalVariables::InputDevice::RAISEDDEADZONE); } void GameControllerMappingDialogHelper::restoreDeviceDeadZones() { qInstallMessageHandler(MessageHandler::myMessageOutput); device->getActiveSetJoystick()->setIgnoreEventState(false); device->getActiveSetJoystick()->release(); device->getActiveSetJoystick()->setAxesDeadZones(&originalAxesDeadZones); device->setRawAxisDeadZone(GlobalVariables::InputDevice::RAISEDDEADZONE); } AntiMicroX-antimicrox-2888bf6/src/uihelpers/gamecontrollermappingdialoghelper.h000066400000000000000000000026061377703515000302000ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GAMECONTROLLERMAPPINGDIALOGHELPER_H #define GAMECONTROLLERMAPPINGDIALOGHELPER_H #include #include class InputDevice; class GameControllerMappingDialogHelper : public QObject { Q_OBJECT public: explicit GameControllerMappingDialogHelper(InputDevice *device, QObject *parent = nullptr); public slots: void raiseDeadZones(); void raiseDeadZones(int deadZone); void setupDeadZones(); void restoreDeviceDeadZones(); private: InputDevice *device; QList originalAxesDeadZones; }; #endif // GAMECONTROLLERMAPPINGDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/joyaxiscontextmenuhelper.cpp000066400000000000000000000040321377703515000267350ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joyaxiscontextmenuhelper.h" #include "joyaxis.h" #include "messagehandler.h" #include JoyAxisContextMenuHelper::JoyAxisContextMenuHelper(JoyAxis *axis, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(axis); this->axis = axis; } void JoyAxisContextMenuHelper::setNAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = axis->getNAxisButton(); button->clearSlotsEventReset(false); button->setAssignedSlot(code, alias, mode); } void JoyAxisContextMenuHelper::setPAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = axis->getPAxisButton(); button->clearSlotsEventReset(false); button->setAssignedSlot(code, alias, mode); } void JoyAxisContextMenuHelper::clearAndResetAxisButtons() { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyAxisButton *nbutton = axis->getNAxisButton(); JoyAxisButton *pbutton = axis->getPAxisButton(); nbutton->clearSlotsEventReset(); pbutton->clearSlotsEventReset(); } AntiMicroX-antimicrox-2888bf6/src/uihelpers/joyaxiscontextmenuhelper.h000066400000000000000000000026531377703515000264110ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYAXISCONTEXTMENUHELPER_H #define JOYAXISCONTEXTMENUHELPER_H #include "joybuttonslot.h" class JoyAxis; class JoyAxisContextMenuHelper : public QObject { Q_OBJECT public: explicit JoyAxisContextMenuHelper(JoyAxis *axis, QObject *parent = nullptr); protected: JoyAxis *axis; public slots: void setNAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void setPAssignedSlot(int code, int alias, JoyButtonSlot::JoySlotInputAction mode = JoyButtonSlot::JoyKeyboard); void clearAndResetAxisButtons(); }; #endif // JOYAXISCONTEXTMENUHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/joycontrolstickcontextmenuhelper.cpp000066400000000000000000000066511377703515000305200ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickcontextmenuhelper.h" #include "joybuttonslot.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "messagehandler.h" #include #include JoyControlStickContextMenuHelper::JoyControlStickContextMenuHelper(JoyControlStick *stick, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(stick); this->stick = stick; } void JoyControlStickContextMenuHelper::setPendingSlots( QHash *tempSlots) { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); QHashIterator iter(*tempSlots); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); JoyControlStick::JoyStickDirections tempDir = iter.key(); pendingSlots.insert(tempDir, slot); } } void JoyControlStickContextMenuHelper::clearPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); } void JoyControlStickContextMenuHelper::setFromPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getPendingSlots().isEmpty()) { QHashIterator iter(getPendingSlots()); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); if (slot) { JoyControlStick::JoyStickDirections tempDir = iter.key(); JoyControlStickButton *button = stick->getDirectionButton(tempDir); if (button) { button->clearSlotsEventReset(false); button->setAssignedSlot(slot->getSlotCode(), slot->getSlotCodeAlias(), slot->getSlotMode()); } slot->deleteLater(); } } } } void JoyControlStickContextMenuHelper::clearButtonsSlotsEventReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash *buttons = stick->getButtons(); QHashIterator iter(*buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button) { button->clearSlotsEventReset(); } } } QHash const &JoyControlStickContextMenuHelper::getPendingSlots() { return pendingSlots; } AntiMicroX-antimicrox-2888bf6/src/uihelpers/joycontrolstickcontextmenuhelper.h000066400000000000000000000031151377703515000301550ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKCONTEXTMENUHELPER_H #define JOYCONTROLSTICKCONTEXTMENUHELPER_H #include "joycontrolstick.h" class JoyButtonSlot; class JoyControlStickContextMenuHelper : public QObject { Q_OBJECT public: explicit JoyControlStickContextMenuHelper(JoyControlStick *stick, QObject *parent = nullptr); void setPendingSlots(QHash *tempSlots); void clearPendingSlots(); QHash const &getPendingSlots(); public slots: void setFromPendingSlots(); void clearButtonsSlotsEventReset(); private: JoyControlStick *stick; QHash pendingSlots; }; #endif // JOYCONTROLSTICKCONTEXTMENUHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/joycontrolstickeditdialoghelper.cpp000066400000000000000000000072021377703515000302450ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickeditdialoghelper.h" #include "joybuttonslot.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "messagehandler.h" #include JoyControlStickEditDialogHelper::JoyControlStickEditDialogHelper(JoyControlStick *stick, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(stick); this->stick = stick; } void JoyControlStickEditDialogHelper::setPendingSlots(QHash *tempSlots) { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); QHashIterator iter(*tempSlots); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); JoyControlStick::JoyStickDirections tempDir = iter.key(); pendingSlots.insert(tempDir, slot); } } void JoyControlStickEditDialogHelper::clearPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingSlots.clear(); } void JoyControlStickEditDialogHelper::setFromPendingSlots() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!getPendingSlots().isEmpty()) { QHashIterator iter(getPendingSlots()); while (iter.hasNext()) { iter.next(); JoyButtonSlot *slot = iter.value(); if (slot) { JoyControlStick::JoyStickDirections tempDir = iter.key(); JoyControlStickButton *button = stick->getDirectionButton(tempDir); if (button) { button->clearSlotsEventReset(false); button->setAssignedSlot(slot->getSlotCode(), slot->getSlotCodeAlias(), slot->getSlotMode()); } slot->deleteLater(); } } } } void JoyControlStickEditDialogHelper::clearButtonsSlotsEventReset() { qInstallMessageHandler(MessageHandler::myMessageOutput); QHash *buttons = stick->getButtons(); QHashIterator iter(*buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button) { button->clearSlotsEventReset(); } } } void JoyControlStickEditDialogHelper::updateControlStickDelay(int value) { qInstallMessageHandler(MessageHandler::myMessageOutput); int temp = value * 10; if (stick->getStickDelay() != temp) { stick->setStickDelay(temp); } } QHash const &JoyControlStickEditDialogHelper::getPendingSlots() { return pendingSlots; } AntiMicroX-antimicrox-2888bf6/src/uihelpers/joycontrolstickeditdialoghelper.h000066400000000000000000000031641377703515000277150ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYCONTROLSTICKEDITDIALOGHELPER_H #define JOYCONTROLSTICKEDITDIALOGHELPER_H #include "joycontrolstick.h" class JoyButtonSlot; class JoyControlStickEditDialogHelper : public QObject { Q_OBJECT public: explicit JoyControlStickEditDialogHelper(JoyControlStick *stick, QObject *parent = nullptr); void setPendingSlots(QHash *tempSlots); void clearPendingSlots(); QHash const &getPendingSlots(); public slots: void setFromPendingSlots(); void clearButtonsSlotsEventReset(); void updateControlStickDelay(int value); private: JoyControlStick *stick; QHash pendingSlots; }; #endif // JOYCONTROLSTICKEDITDIALOGHELPER_H AntiMicroX-antimicrox-2888bf6/src/uihelpers/joytabwidgethelper.cpp000066400000000000000000000106421377703515000254550ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joytabwidgethelper.h" #include "inputdevice.h" #include "joybutton.h" #include "joybuttonslot.h" #include "messagehandler.h" #include "xml/inputdevicexml.h" #include "xmlconfigreader.h" #include "xmlconfigwriter.h" #include JoyTabWidgetHelper::JoyTabWidgetHelper(InputDevice *device, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_ASSERT(device); this->device = device; this->reader = nullptr; this->writer = nullptr; this->errorOccurred = false; } JoyTabWidgetHelper::~JoyTabWidgetHelper() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (this->reader != nullptr) { delete this->reader; this->reader = nullptr; } if (this->writer != nullptr) { delete this->writer; this->writer = nullptr; } } bool JoyTabWidgetHelper::hasReader() { qInstallMessageHandler(MessageHandler::myMessageOutput); return (this->reader != nullptr); } XMLConfigReader *JoyTabWidgetHelper::getReader() { qInstallMessageHandler(MessageHandler::myMessageOutput); return this->reader; } bool JoyTabWidgetHelper::hasWriter() { qInstallMessageHandler(MessageHandler::myMessageOutput); return (this->writer != nullptr); } XMLConfigWriter *JoyTabWidgetHelper::getWriter() { qInstallMessageHandler(MessageHandler::myMessageOutput); return this->writer; } bool JoyTabWidgetHelper::hasError() { qInstallMessageHandler(MessageHandler::myMessageOutput); return errorOccurred; } QString JoyTabWidgetHelper::getErrorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return lastErrorString; } bool JoyTabWidgetHelper::readConfigFile(QString filepath) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; device->disconnectPropertyUpdatedConnection(); if (device->getActiveSetNumber() != 0) { device->setActiveSetNumber(0); } device->resetButtonDownCount(); if (this->reader != nullptr) { this->reader->deleteLater(); this->reader = nullptr; } this->reader = new XMLConfigReader; this->reader->setFileName(filepath); this->reader->configJoystick(device); device->establishPropertyUpdatedConnection(); result = !this->reader->hasError(); return result; } bool JoyTabWidgetHelper::readConfigFileWithRevert(QString filepath) { qInstallMessageHandler(MessageHandler::myMessageOutput); device->revertProfileEdited(); return readConfigFile(filepath); } bool JoyTabWidgetHelper::writeConfigFile(QString filepath) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; if (this->writer != nullptr) { this->writer->deleteLater(); this->writer = nullptr; } this->writer = new XMLConfigWriter; this->writer->setFileName(filepath); InputDeviceXml *deviceXml = new InputDeviceXml(device); this->writer->write(deviceXml); delete deviceXml; result = !this->writer->hasError(); return result; } void JoyTabWidgetHelper::reInitDevice() { qInstallMessageHandler(MessageHandler::myMessageOutput); device->disconnectPropertyUpdatedConnection(); if (device->getActiveSetNumber() != 0) { device->setActiveSetNumber(0); } device->transferReset(); device->resetButtonDownCount(); device->reInitButtons(); device->establishPropertyUpdatedConnection(); } void JoyTabWidgetHelper::reInitDeviceWithRevert() { qInstallMessageHandler(MessageHandler::myMessageOutput); device->revertProfileEdited(); reInitDevice(); } AntiMicroX-antimicrox-2888bf6/src/uihelpers/joytabwidgethelper.h000066400000000000000000000032551377703515000251240ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYTABWIDGETHELPER_H #define JOYTABWIDGETHELPER_H #include class InputDevice; class XMLConfigReader; class XMLConfigWriter; class JoyTabWidgetHelper : public QObject { Q_OBJECT public: explicit JoyTabWidgetHelper(InputDevice *device, QObject *parent = nullptr); ~JoyTabWidgetHelper(); bool hasReader(); XMLConfigReader *getReader(); bool hasWriter(); XMLConfigWriter *getWriter(); bool hasError(); QString getErrorString(); protected: InputDevice *device; XMLConfigReader *reader; XMLConfigWriter *writer; bool errorOccurred; QString lastErrorString; public slots: bool readConfigFile(QString filepath); bool readConfigFileWithRevert(QString filepath); bool writeConfigFile(QString filepath); void reInitDevice(); void reInitDeviceWithRevert(); }; #endif // JOYTABWIDGETHELPER_H AntiMicroX-antimicrox-2888bf6/src/uinputhelper.cpp000066400000000000000000000356521377703515000223150ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "messagehandler.h" #include "uinputhelper.h" UInputHelper *UInputHelper::_instance = nullptr; UInputHelper::UInputHelper(QObject *parent) : QObject(parent) { populateKnownAliases(); connect(qApp, &QApplication::aboutToQuit, this, &UInputHelper::deleteLater); } UInputHelper::~UInputHelper() { _instance = nullptr; } void UInputHelper::populateKnownAliases() { if (getKnownAliasesX11SymVK().isEmpty()) populateX11SymVk(knownAliasesX11SymVK); if (getKnownAliasesVKStrings().isEmpty()) populateXVkStrings(knownAliasesVKStrings); } void UInputHelper::populateX11SymVk(QHash &knownAliasesX11SymVK) { knownAliasesX11SymVK.insert("a", KEY_A); knownAliasesX11SymVK.insert("b", KEY_B); knownAliasesX11SymVK.insert("c", KEY_C); knownAliasesX11SymVK.insert("d", KEY_D); knownAliasesX11SymVK.insert("e", KEY_E); knownAliasesX11SymVK.insert("f", KEY_F); knownAliasesX11SymVK.insert("g", KEY_G); knownAliasesX11SymVK.insert("h", KEY_H); knownAliasesX11SymVK.insert("i", KEY_I); knownAliasesX11SymVK.insert("j", KEY_J); knownAliasesX11SymVK.insert("k", KEY_K); knownAliasesX11SymVK.insert("l", KEY_L); knownAliasesX11SymVK.insert("m", KEY_M); knownAliasesX11SymVK.insert("n", KEY_N); knownAliasesX11SymVK.insert("o", KEY_O); knownAliasesX11SymVK.insert("p", KEY_P); knownAliasesX11SymVK.insert("q", KEY_Q); knownAliasesX11SymVK.insert("r", KEY_R); knownAliasesX11SymVK.insert("s", KEY_S); knownAliasesX11SymVK.insert("t", KEY_T); knownAliasesX11SymVK.insert("u", KEY_U); knownAliasesX11SymVK.insert("v", KEY_V); knownAliasesX11SymVK.insert("w", KEY_W); knownAliasesX11SymVK.insert("x", KEY_X); knownAliasesX11SymVK.insert("y", KEY_Y); knownAliasesX11SymVK.insert("z", KEY_Z); knownAliasesX11SymVK.insert("Escape", KEY_ESC); knownAliasesX11SymVK.insert("F1", KEY_F1); knownAliasesX11SymVK.insert("F2", KEY_F2); knownAliasesX11SymVK.insert("F3", KEY_F3); knownAliasesX11SymVK.insert("F4", KEY_F4); knownAliasesX11SymVK.insert("F5", KEY_F5); knownAliasesX11SymVK.insert("F6", KEY_F6); knownAliasesX11SymVK.insert("F7", KEY_F7); knownAliasesX11SymVK.insert("F8", KEY_F8); knownAliasesX11SymVK.insert("F9", KEY_F9); knownAliasesX11SymVK.insert("F10", KEY_F10); knownAliasesX11SymVK.insert("F11", KEY_F11); knownAliasesX11SymVK.insert("F12", KEY_F12); knownAliasesX11SymVK.insert("F13", KEY_F13); knownAliasesX11SymVK.insert("F14", KEY_F14); knownAliasesX11SymVK.insert("F15", KEY_F15); knownAliasesX11SymVK.insert("F16", KEY_F16); knownAliasesX11SymVK.insert("F17", KEY_F17); knownAliasesX11SymVK.insert("F18", KEY_F18); knownAliasesX11SymVK.insert("F19", KEY_F19); knownAliasesX11SymVK.insert("F20", KEY_F20); knownAliasesX11SymVK.insert("F21", KEY_F21); knownAliasesX11SymVK.insert("F22", KEY_F22); knownAliasesX11SymVK.insert("F23", KEY_F23); knownAliasesX11SymVK.insert("F24", KEY_F24); knownAliasesX11SymVK.insert("grave", KEY_GRAVE); knownAliasesX11SymVK.insert("1", KEY_1); knownAliasesX11SymVK.insert("2", KEY_2); knownAliasesX11SymVK.insert("3", KEY_3); knownAliasesX11SymVK.insert("4", KEY_4); knownAliasesX11SymVK.insert("5", KEY_5); knownAliasesX11SymVK.insert("6", KEY_6); knownAliasesX11SymVK.insert("7", KEY_7); knownAliasesX11SymVK.insert("8", KEY_8); knownAliasesX11SymVK.insert("9", KEY_9); knownAliasesX11SymVK.insert("0", KEY_0); knownAliasesX11SymVK.insert("minus", KEY_MINUS); knownAliasesX11SymVK.insert("equal", KEY_EQUAL); knownAliasesX11SymVK.insert("BackSpace", KEY_BACKSPACE); knownAliasesX11SymVK.insert("Tab", KEY_TAB); knownAliasesX11SymVK.insert("bracketleft", KEY_LEFTBRACE); knownAliasesX11SymVK.insert("bracketright", KEY_RIGHTBRACE); knownAliasesX11SymVK.insert("backslash", KEY_BACKSLASH); knownAliasesX11SymVK.insert("Caps_Lock", KEY_CAPSLOCK); knownAliasesX11SymVK.insert("semicolon", KEY_SEMICOLON); knownAliasesX11SymVK.insert("apostrophe", KEY_APOSTROPHE); knownAliasesX11SymVK.insert("Return", KEY_ENTER); knownAliasesX11SymVK.insert("Shift_L", KEY_LEFTSHIFT); knownAliasesX11SymVK.insert("comma", KEY_COMMA); knownAliasesX11SymVK.insert("period", KEY_DOT); knownAliasesX11SymVK.insert("slash", KEY_SLASH); knownAliasesX11SymVK.insert("Control_L", KEY_LEFTCTRL); knownAliasesX11SymVK.insert("Super_L", KEY_MENU); knownAliasesX11SymVK.insert("Alt_L", KEY_LEFTALT); knownAliasesX11SymVK.insert("space", KEY_SPACE); knownAliasesX11SymVK.insert("Alt_R", KEY_RIGHTALT); knownAliasesX11SymVK.insert("Menu", KEY_COMPOSE); knownAliasesX11SymVK.insert("Control_R", KEY_RIGHTCTRL); knownAliasesX11SymVK.insert("Shift_R", KEY_RIGHTSHIFT); knownAliasesX11SymVK.insert("Up", KEY_UP); knownAliasesX11SymVK.insert("Left", KEY_LEFT); knownAliasesX11SymVK.insert("Down", KEY_DOWN); knownAliasesX11SymVK.insert("Right", KEY_RIGHT); knownAliasesX11SymVK.insert("Print", KEY_PRINT); knownAliasesX11SymVK.insert("Insert", KEY_INSERT); knownAliasesX11SymVK.insert("Delete", KEY_DELETE); knownAliasesX11SymVK.insert("Home", KEY_HOME); knownAliasesX11SymVK.insert("End", KEY_END); knownAliasesX11SymVK.insert("Prior", KEY_PAGEUP); knownAliasesX11SymVK.insert("Next", KEY_PAGEDOWN); knownAliasesX11SymVK.insert("Num_Lock", KEY_NUMLOCK); knownAliasesX11SymVK.insert("KP_Divide", KEY_KPSLASH); knownAliasesX11SymVK.insert("KP_Multiply", KEY_KPASTERISK); knownAliasesX11SymVK.insert("KP_Subtract", KEY_KPMINUS); knownAliasesX11SymVK.insert("KP_Add", KEY_KPPLUS); knownAliasesX11SymVK.insert("KP_Enter", KEY_KPENTER); knownAliasesX11SymVK.insert("KP_1", KEY_KP1); knownAliasesX11SymVK.insert("KP_2", KEY_KP2); knownAliasesX11SymVK.insert("KP_3", KEY_KP3); knownAliasesX11SymVK.insert("KP_4", KEY_KP4); knownAliasesX11SymVK.insert("KP_5", KEY_KP5); knownAliasesX11SymVK.insert("KP_6", KEY_KP6); knownAliasesX11SymVK.insert("KP_7", KEY_KP7); knownAliasesX11SymVK.insert("KP_8", KEY_KP8); knownAliasesX11SymVK.insert("KP_9", KEY_KP9); knownAliasesX11SymVK.insert("KP_0", KEY_KP0); knownAliasesX11SymVK.insert("KP_Decimal", KEY_KPDOT); knownAliasesX11SymVK.insert("Scroll_Lock", KEY_SCROLLLOCK); knownAliasesX11SymVK.insert("Pause", KEY_PAUSE); knownAliasesX11SymVK.insert("Multi_key", KEY_RIGHTALT); } void UInputHelper::populateXVkStrings(QHash &knownAliasesVKStrings) { knownAliasesVKStrings.insert(KEY_A, tr("a")); knownAliasesVKStrings.insert(KEY_B, tr("b")); knownAliasesVKStrings.insert(KEY_C, tr("c")); knownAliasesVKStrings.insert(KEY_D, tr("d")); knownAliasesVKStrings.insert(KEY_E, tr("e")); knownAliasesVKStrings.insert(KEY_F, tr("f")); knownAliasesVKStrings.insert(KEY_G, tr("g")); knownAliasesVKStrings.insert(KEY_H, tr("h")); knownAliasesVKStrings.insert(KEY_I, tr("i")); knownAliasesVKStrings.insert(KEY_J, tr("j")); knownAliasesVKStrings.insert(KEY_K, tr("k")); knownAliasesVKStrings.insert(KEY_L, tr("l")); knownAliasesVKStrings.insert(KEY_M, tr("m")); knownAliasesVKStrings.insert(KEY_N, tr("n")); knownAliasesVKStrings.insert(KEY_O, tr("o")); knownAliasesVKStrings.insert(KEY_P, tr("p")); knownAliasesVKStrings.insert(KEY_Q, tr("q")); knownAliasesVKStrings.insert(KEY_R, tr("r")); knownAliasesVKStrings.insert(KEY_S, tr("s")); knownAliasesVKStrings.insert(KEY_T, tr("t")); knownAliasesVKStrings.insert(KEY_U, tr("u")); knownAliasesVKStrings.insert(KEY_V, tr("v")); knownAliasesVKStrings.insert(KEY_W, tr("w")); knownAliasesVKStrings.insert(KEY_X, tr("x")); knownAliasesVKStrings.insert(KEY_Y, tr("y")); knownAliasesVKStrings.insert(KEY_Z, tr("z")); knownAliasesVKStrings.insert(KEY_ESC, tr("Esc")); knownAliasesVKStrings.insert(KEY_F1, tr("F1")); knownAliasesVKStrings.insert(KEY_F2, tr("F2")); knownAliasesVKStrings.insert(KEY_F3, tr("F3")); knownAliasesVKStrings.insert(KEY_F4, tr("F4")); knownAliasesVKStrings.insert(KEY_F5, tr("F5")); knownAliasesVKStrings.insert(KEY_F6, tr("F6")); knownAliasesVKStrings.insert(KEY_F7, tr("F7")); knownAliasesVKStrings.insert(KEY_F8, tr("F8")); knownAliasesVKStrings.insert(KEY_F9, tr("F9")); knownAliasesVKStrings.insert(KEY_F10, tr("F10")); knownAliasesVKStrings.insert(KEY_F11, tr("F11")); knownAliasesVKStrings.insert(KEY_F12, tr("F12")); knownAliasesVKStrings.insert(KEY_F13, tr("F13")); knownAliasesVKStrings.insert(KEY_F14, tr("F14")); knownAliasesVKStrings.insert(KEY_F15, tr("F15")); knownAliasesVKStrings.insert(KEY_F16, tr("F16")); knownAliasesVKStrings.insert(KEY_F17, tr("F17")); knownAliasesVKStrings.insert(KEY_F18, tr("F18")); knownAliasesVKStrings.insert(KEY_F19, tr("F19")); knownAliasesVKStrings.insert(KEY_F20, tr("F20")); knownAliasesVKStrings.insert(KEY_F21, tr("F21")); knownAliasesVKStrings.insert(KEY_F22, tr("F22")); knownAliasesVKStrings.insert(KEY_F23, tr("F23")); knownAliasesVKStrings.insert(KEY_F24, tr("F24")); knownAliasesVKStrings.insert(KEY_GRAVE, tr("`")); knownAliasesVKStrings.insert(KEY_1, tr("1")); knownAliasesVKStrings.insert(KEY_2, tr("2")); knownAliasesVKStrings.insert(KEY_3, tr("3")); knownAliasesVKStrings.insert(KEY_4, tr("4")); knownAliasesVKStrings.insert(KEY_5, tr("5")); knownAliasesVKStrings.insert(KEY_6, tr("6")); knownAliasesVKStrings.insert(KEY_7, tr("7")); knownAliasesVKStrings.insert(KEY_8, tr("8")); knownAliasesVKStrings.insert(KEY_9, tr("9")); knownAliasesVKStrings.insert(KEY_0, tr("0")); knownAliasesVKStrings.insert(KEY_MINUS, tr("-")); knownAliasesVKStrings.insert(KEY_EQUAL, tr("=")); knownAliasesVKStrings.insert(KEY_BACKSPACE, tr("BackSpace")); knownAliasesVKStrings.insert(KEY_TAB, tr("Tab")); knownAliasesVKStrings.insert(KEY_LEFTBRACE, tr("[")); knownAliasesVKStrings.insert(KEY_RIGHTBRACE, tr("]")); knownAliasesVKStrings.insert(KEY_BACKSLASH, tr("\\")); knownAliasesVKStrings.insert(KEY_CAPSLOCK, tr("CapsLock")); knownAliasesVKStrings.insert(KEY_SEMICOLON, tr(";")); knownAliasesVKStrings.insert(KEY_APOSTROPHE, tr("'")); knownAliasesVKStrings.insert(KEY_ENTER, tr("Enter")); knownAliasesVKStrings.insert(KEY_LEFTSHIFT, tr("Shift_L")); knownAliasesVKStrings.insert(KEY_COMMA, tr(",")); knownAliasesVKStrings.insert(KEY_DOT, tr(".")); knownAliasesVKStrings.insert(KEY_SLASH, tr("/")); knownAliasesVKStrings.insert(KEY_LEFTCTRL, tr("Ctrl_L")); knownAliasesVKStrings.insert(KEY_MENU, tr("Super_L")); knownAliasesVKStrings.insert(KEY_LEFTALT, tr("Alt_L")); knownAliasesVKStrings.insert(KEY_SPACE, tr("Space")); knownAliasesVKStrings.insert(KEY_RIGHTALT, tr("Alt_R")); knownAliasesVKStrings.insert(KEY_COMPOSE, tr("Menu")); knownAliasesVKStrings.insert(KEY_RIGHTCTRL, tr("Ctrl_R")); knownAliasesVKStrings.insert(KEY_RIGHTSHIFT, tr("Shift_R")); knownAliasesVKStrings.insert(KEY_UP, tr("Up")); knownAliasesVKStrings.insert(KEY_LEFT, tr("Left")); knownAliasesVKStrings.insert(KEY_DOWN, tr("Down")); knownAliasesVKStrings.insert(KEY_RIGHT, tr("Right")); knownAliasesVKStrings.insert(KEY_PRINT, tr("PrtSc")); knownAliasesVKStrings.insert(KEY_INSERT, tr("Ins")); knownAliasesVKStrings.insert(KEY_DELETE, tr("Del")); knownAliasesVKStrings.insert(KEY_HOME, tr("Home")); knownAliasesVKStrings.insert(KEY_END, tr("End")); knownAliasesVKStrings.insert(KEY_PAGEUP, tr("PgUp")); knownAliasesVKStrings.insert(KEY_PAGEDOWN, tr("PgDn")); knownAliasesVKStrings.insert(KEY_NUMLOCK, tr("NumLock")); knownAliasesVKStrings.insert(KEY_KPSLASH, tr("/")); knownAliasesVKStrings.insert(KEY_KPASTERISK, tr("*")); knownAliasesVKStrings.insert(KEY_KPMINUS, tr("-")); knownAliasesVKStrings.insert(KEY_KPPLUS, tr("+")); knownAliasesVKStrings.insert(KEY_KPENTER, tr("KP_Enter")); knownAliasesVKStrings.insert(KEY_KP1, tr("KP_1")); knownAliasesVKStrings.insert(KEY_KP2, tr("KP_2")); knownAliasesVKStrings.insert(KEY_KP3, tr("KP_3")); knownAliasesVKStrings.insert(KEY_KP4, tr("KP_4")); knownAliasesVKStrings.insert(KEY_KP5, tr("KP_5")); knownAliasesVKStrings.insert(KEY_KP6, tr("KP_6")); knownAliasesVKStrings.insert(KEY_KP7, tr("KP_7")); knownAliasesVKStrings.insert(KEY_KP8, tr("KP_8")); knownAliasesVKStrings.insert(KEY_KP9, tr("KP_9")); knownAliasesVKStrings.insert(KEY_KP0, tr("KP_0")); knownAliasesVKStrings.insert(KEY_SCROLLLOCK, tr("SCLK")); knownAliasesVKStrings.insert(KEY_PAUSE, tr("Pause")); knownAliasesVKStrings.insert(KEY_KPDOT, tr(".")); knownAliasesVKStrings.insert(KEY_LEFTMETA, tr("Super_L")); knownAliasesVKStrings.insert(KEY_RIGHTMETA, tr("Super_R")); knownAliasesVKStrings.insert(KEY_MUTE, tr("Mute")); knownAliasesVKStrings.insert(KEY_VOLUMEDOWN, tr("VolDn")); knownAliasesVKStrings.insert(KEY_VOLUMEUP, tr("VolUp")); knownAliasesVKStrings.insert(KEY_PLAYPAUSE, tr("Play")); knownAliasesVKStrings.insert(KEY_STOPCD, tr("Stop")); knownAliasesVKStrings.insert(KEY_PREVIOUSSONG, tr("Prev")); knownAliasesVKStrings.insert(KEY_NEXTSONG, tr("Next")); } UInputHelper *UInputHelper::getInstance() { if (!_instance) _instance = new UInputHelper(); return _instance; } void UInputHelper::deleteInstance() { if (_instance != nullptr) { delete _instance; _instance = nullptr; } } QString UInputHelper::getDisplayString(int virtualkey) { QString temp = QString(); if (virtualkey <= 0) temp = tr("[NO KEY]"); else if (getKnownAliasesVKStrings().contains(virtualkey)) temp = getKnownAliasesVKStrings().value(virtualkey); return temp; } int UInputHelper::getVirtualKey(QString codestring) { int temp = 0; if (getKnownAliasesX11SymVK().contains(codestring)) temp = getKnownAliasesX11SymVK().value(codestring); return temp; } QHash const &UInputHelper::getKnownAliasesX11SymVK() { return knownAliasesX11SymVK; } QHash const &UInputHelper::getKnownAliasesVKStrings() { return knownAliasesVKStrings; } AntiMicroX-antimicrox-2888bf6/src/uinputhelper.h000066400000000000000000000032401377703515000217460ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UINPUTHELPER_H #define UINPUTHELPER_H #include #include #include class UInputHelper : public QObject { Q_OBJECT public: static UInputHelper *getInstance(); void deleteInstance(); QString getDisplayString(int virtualkey); int getVirtualKey(QString codestring); QHash const &getKnownAliasesX11SymVK(); QHash const &getKnownAliasesVKStrings(); protected: explicit UInputHelper(QObject *parent = nullptr); ~UInputHelper(); void populateKnownAliases(); static UInputHelper *_instance; QHash knownAliasesX11SymVK; QHash knownAliasesVKStrings; private: void populateXVkStrings(QHash &knownAliasesVKStrings); void populateX11SymVk(QHash &knownAliasesX11SymVK); }; #endif // UINPUTHELPER_H AntiMicroX-antimicrox-2888bf6/src/unixcapturewindowutility.cpp000066400000000000000000000100421377703515000247760ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "unixcapturewindowutility.h" #include "messagehandler.h" #include "qtx11keymapper.h" #include #include #include #include // for XGrabPointer #include "x11extras.h" UnixCaptureWindowUtility::UnixCaptureWindowUtility(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); targetPath = ""; failed = false; targetWindow = None; } /** * @brief Attempt to capture window selected with the mouse */ void UnixCaptureWindowUtility::attemptWindowCapture() { qInstallMessageHandler(MessageHandler::myMessageOutput); // Only create instance when needed. static QtX11KeyMapper x11KeyMapper; targetPath = ""; targetWindow = None; failed = false; bool escaped = false; Cursor cursor; Window target_window = None; int status = 0; Display *display = nullptr; QString potentialXDisplayString = X11Extras::getInstance()->getXDisplayString(); if (!potentialXDisplayString.isEmpty()) { QByteArray tempByteArray = potentialXDisplayString.toLocal8Bit(); display = XOpenDisplay(tempByteArray.constData()); } else { display = XOpenDisplay(nullptr); } Window rootWin = XDefaultRootWindow(display); cursor = XCreateFontCursor(display, XC_crosshair); status = XGrabPointer(display, rootWin, False, ButtonPressMask, GrabModeSync, GrabModeAsync, None, cursor, CurrentTime); if (status == Success) { XGrabKey(display, XKeysymToKeycode(display, static_cast(x11KeyMapper.returnVirtualKey(Qt::Key_Escape))), 0, rootWin, true, GrabModeAsync, GrabModeAsync); XEvent event; XAllowEvents(display, SyncPointer, CurrentTime); XWindowEvent(display, rootWin, ButtonPressMask | KeyPressMask, &event); switch (event.type) { case (ButtonPress): target_window = event.xbutton.subwindow; if (target_window == None) target_window = event.xbutton.window; qDebug() << QString::number(target_window, 16); break; case (KeyPress): { escaped = true; break; } default: break; } XUngrabKey(display, XKeysymToKeycode(display, static_cast(x11KeyMapper.returnVirtualKey(Qt::Key_Escape))), 0, rootWin); XUngrabPointer(display, CurrentTime); XFlush(display); } if (target_window != None) targetWindow = target_window; else if (!escaped) failed = true; XCloseDisplay(display); emit captureFinished(); } /** * @brief Get the saved path for a window * @return Program path */ QString UnixCaptureWindowUtility::getTargetPath() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return targetPath; } /** * @brief Check if attemptWindowCapture failed to obtain an application * @return Error status */ bool UnixCaptureWindowUtility::hasFailed() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return failed; } long UnixCaptureWindowUtility::getTargetWindow() const { qInstallMessageHandler(MessageHandler::myMessageOutput); return targetWindow; } AntiMicroX-antimicrox-2888bf6/src/unixcapturewindowutility.h000066400000000000000000000025131377703515000244470ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UNIXCAPTUREWINDOWUTILITY_H #define UNIXCAPTUREWINDOWUTILITY_H #include class UnixCaptureWindowUtility : public QObject { Q_OBJECT public: explicit UnixCaptureWindowUtility(QObject *parent = nullptr); QString getTargetPath() const; bool hasFailed() const; long getTargetWindow() const; signals: void captureFinished(); public slots: void attemptWindowCapture(); private: QString targetPath; bool failed; long targetWindow; }; #endif // UNIXCAPTUREWINDOWUTILITY_H AntiMicroX-antimicrox-2888bf6/src/unixwindowinfodialog.cpp000066400000000000000000000067761377703515000240450ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "ui_unixwindowinfodialog.h" #include "unixwindowinfodialog.h" #include "x11info.h" UnixWindowInfoDialog::UnixWindowInfoDialog(unsigned long window, QWidget *parent) : QDialog(parent) , ui(new Ui::UnixWindowInfoDialog) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); X11Info *info = X11Info::getInstance(); bool setRadioDefault = false; winClass = info->getWindowClass(window); ui->winClassLabel->setText(winClass); if (winClass.isEmpty()) { ui->winClassCheckBox->setEnabled(false); ui->winClassCheckBox->setChecked(false); } else { ui->winClassCheckBox->setChecked(true); setRadioDefault = true; } winName = info->getWindowTitle(window); ui->winTitleLabel->setText(winName); if (winName.isEmpty()) { ui->winTitleCheckBox->setEnabled(false); ui->winTitleCheckBox->setChecked(false); } else if (!setRadioDefault) { ui->winTitleCheckBox->setChecked(true); setRadioDefault = true; } ui->winPathLabel->clear(); int pid = info->getApplicationPid(window); if (pid > 0) { QString exepath = X11Info::getInstance()->getApplicationLocation(pid); if (!exepath.isEmpty()) { ui->winPathLabel->setText(exepath); winPath = exepath; if (!setRadioDefault) { ui->winTitleCheckBox->setChecked(true); setRadioDefault = true; } } else { ui->winPathCheckBox->setEnabled(false); ui->winPathCheckBox->setChecked(false); } } else { ui->winPathCheckBox->setEnabled(false); ui->winPathCheckBox->setChecked(false); } if (winClass.isEmpty() && winName.isEmpty() && winPath.isEmpty()) { QPushButton *button = ui->buttonBox->button(QDialogButtonBox::Ok); button->setEnabled(false); } connect(this, SIGNAL(accepted()), this, SLOT(populateOption())); } void UnixWindowInfoDialog::populateOption() { if (ui->winClassCheckBox->isChecked()) { selectedMatch = selectedMatch | WindowClass; } if (ui->winTitleCheckBox->isChecked()) { selectedMatch = selectedMatch | WindowName; } if (ui->winPathCheckBox->isChecked()) { selectedMatch = selectedMatch | WindowPath; } } UnixWindowInfoDialog::DialogWindowOption UnixWindowInfoDialog::getSelectedOptions() const { return selectedMatch; } QString UnixWindowInfoDialog::getWindowClass() const { return winClass; } QString UnixWindowInfoDialog::getWindowName() const { return winName; } QString UnixWindowInfoDialog::getWindowPath() const { return winPath; } UnixWindowInfoDialog::~UnixWindowInfoDialog() { delete ui; } AntiMicroX-antimicrox-2888bf6/src/unixwindowinfodialog.h000066400000000000000000000032231377703515000234720ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UNIXWINDOWINFODIALOG_H #define UNIXWINDOWINFODIALOG_H #include #include namespace Ui { class UnixWindowInfoDialog; } class UnixWindowInfoDialog : public QDialog { Q_OBJECT public: explicit UnixWindowInfoDialog(long window, QWidget *parent = nullptr); ~UnixWindowInfoDialog(); enum { WindowClass = (1 << 0), WindowName = (1 << 1), WindowPath = (1 << 2) }; typedef int DialogWindowOption; QString getWindowClass() const; QString getWindowName() const; QString getWindowPath() const; DialogWindowOption getSelectedOptions() const; private: Ui::UnixWindowInfoDialog *ui; DialogWindowOption selectedMatch; QString winClass; QString winName; QString winPath; private slots: void populateOption(); }; #endif // UNIXWINDOWINFODIALOG_H AntiMicroX-antimicrox-2888bf6/src/unixwindowinfodialog.ui000066400000000000000000000123141377703515000236610ustar00rootroot00000000000000 UnixWindowInfoDialog 0 0 533 333 Captured Window Properties 20 50 false Information About Window true 20 Class: true TextLabel Title: true TextLabel Path: true TextLabel Match By Properties true false false Class Title Path Qt::Vertical 20 40 Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() UnixWindowInfoDialog accept() 248 254 157 274 buttonBox rejected() UnixWindowInfoDialog reject() 316 260 286 274 AntiMicroX-antimicrox-2888bf6/src/vdpad.cpp000066400000000000000000000201331377703515000206530ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "vdpad.h" #include "globalvariables.h" #include "messagehandler.h" #include VDPad::VDPad(int index, int originset, SetJoystick *parentSet, QObject *parent) : JoyDPad(index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->upButton = nullptr; this->downButton = nullptr; this->leftButton = nullptr; this->rightButton = nullptr; pendingVDPadEvent = false; } VDPad::VDPad(JoyButton *upButton, JoyButton *downButton, JoyButton *leftButton, JoyButton *rightButton, int index, int originset, SetJoystick *parentSet, QObject *parent) : JoyDPad(index, originset, parentSet, parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->upButton = upButton; upButton->setVDPad(this); this->downButton = downButton; downButton->setVDPad(this); this->leftButton = leftButton; leftButton->setVDPad(this); this->rightButton = rightButton; rightButton->setVDPad(this); pendingVDPadEvent = false; } VDPad::~VDPad() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (upButton != nullptr) { upButton->removeVDPad(); upButton = nullptr; } if (downButton != nullptr) { downButton->removeVDPad(); downButton = nullptr; } if (leftButton != nullptr) { leftButton->removeVDPad(); leftButton = nullptr; } if (rightButton != nullptr) { rightButton->removeVDPad(); rightButton = nullptr; } } QString VDPad::getXmlName() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::VDPad::xmlName; } QString VDPad::getName(bool forceFullFormat, bool displayName) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString label = QString(); if (!getDpadName().isEmpty() && displayName) { if (forceFullFormat) label.append(tr("VDPad")).append(" "); label.append(getDpadName()); } else if (!getDefaultDpadName().isEmpty()) { if (forceFullFormat) label.append(tr("VDPad")).append(" "); label.append(getDefaultDpadName()); } else { label.append(tr("VDPad")).append(" "); label.append(QString::number(getRealJoyNumber())); } return label; } void VDPad::joyEvent(bool pressed, bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(pressed) int tempDirection = static_cast(JoyDPadButton::DpadCentered); // Check which buttons are currently active if ((upButton != nullptr) && upButton->getButtonState()) tempDirection |= JoyDPadButton::DpadUp; if (downButton && downButton->getButtonState()) tempDirection |= JoyDPadButton::DpadDown; if (leftButton && leftButton->getButtonState()) tempDirection |= JoyDPadButton::DpadLeft; if (rightButton && rightButton->getButtonState()) tempDirection |= JoyDPadButton::DpadRight; JoyDPad::joyEvent(tempDirection, ignoresets); pendingVDPadEvent = false; } void VDPad::addVButton(JoyDPadButton::JoyDPadDirections direction, JoyButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); switch (direction) { case JoyDPadButton::DpadUp: { if (upButton != nullptr) upButton->removeVDPad(); upButton = button; upButton->setVDPad(this); break; } case JoyDPadButton::DpadDown: { if (downButton != nullptr) downButton->removeVDPad(); downButton = button; downButton->setVDPad(this); break; } case JoyDPadButton::DpadLeft: { if (leftButton != nullptr) leftButton->removeVDPad(); leftButton = button; leftButton->setVDPad(this); break; } case JoyDPadButton::DpadRight: { if (rightButton != nullptr) rightButton->removeVDPad(); rightButton = button; rightButton->setVDPad(this); break; } default: break; } } void VDPad::removeVButton(JoyDPadButton::JoyDPadDirections direction) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((direction == JoyDPadButton::DpadUp) && (upButton != nullptr)) { upButton->removeVDPad(); upButton = nullptr; } else if ((direction == JoyDPadButton::DpadDown) && (downButton != nullptr)) { downButton->removeVDPad(); downButton = nullptr; } else if ((direction == JoyDPadButton::DpadLeft) && (leftButton != nullptr)) { leftButton->removeVDPad(); leftButton = nullptr; } else if ((direction == JoyDPadButton::DpadRight) && (rightButton != nullptr)) { rightButton->removeVDPad(); rightButton = nullptr; } } void VDPad::removeVButton(JoyButton *button) { qInstallMessageHandler(MessageHandler::myMessageOutput); if ((button != nullptr) && (button == upButton)) { upButton->removeVDPad(); upButton = nullptr; } else if ((button != nullptr) && (button == downButton)) { downButton->removeVDPad(); downButton = nullptr; } else if ((button != nullptr) && (button == leftButton)) { leftButton->removeVDPad(); leftButton = nullptr; } else if ((button != nullptr) && (button == rightButton)) { rightButton->removeVDPad(); rightButton = nullptr; } } bool VDPad::isEmpty() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool empty = true; if ((upButton != nullptr) || (downButton != nullptr) || (leftButton != nullptr) || (rightButton != nullptr)) { empty = false; } return empty; } JoyButton *VDPad::getVButton(JoyDPadButton::JoyDPadDirections direction) { qInstallMessageHandler(MessageHandler::myMessageOutput); JoyButton *button = nullptr; switch (direction) { case JoyDPadButton::DpadUp: { button = upButton; break; } case JoyDPadButton::DpadDown: { button = downButton; break; } case JoyDPadButton::DpadLeft: { button = leftButton; break; } case JoyDPadButton::DpadRight: { button = rightButton; break; } default: break; } return button; } bool VDPad::hasPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); return pendingVDPadEvent; } void VDPad::queueJoyEvent(bool ignoresets) { qInstallMessageHandler(MessageHandler::myMessageOutput); Q_UNUSED(ignoresets) pendingVDPadEvent = true; } void VDPad::activatePendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (pendingVDPadEvent) { // Always use true. The proper direction value will be determined // in the joyEvent method. joyEvent(true); pendingVDPadEvent = false; } } void VDPad::clearPendingEvent() { qInstallMessageHandler(MessageHandler::myMessageOutput); pendingVDPadEvent = false; } JoyButton *VDPad::getUpButton() const { return upButton; } JoyButton *VDPad::getDownButton() const { return downButton; } JoyButton *VDPad::getLeftButton() const { return leftButton; } JoyButton *VDPad::getRightButton() const { return rightButton; } bool VDPad::getPendingVDPadEvent() const { return pendingVDPadEvent; } AntiMicroX-antimicrox-2888bf6/src/vdpad.h000066400000000000000000000043101377703515000203170ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VDPAD_H #define VDPAD_H #include "joydpad.h" class VDPad : public JoyDPad { Q_OBJECT public: explicit VDPad(int index, int originset, SetJoystick *parentSet, QObject *parent = nullptr); explicit VDPad(JoyButton *upButton, JoyButton *downButton, JoyButton *leftButton, JoyButton *rightButton, int index, int originset, SetJoystick *parentSet, QObject *parent = nullptr); ~VDPad(); void joyEvent(bool pressed, bool ignoresets = false); void addVButton(JoyDPadButton::JoyDPadDirections direction, JoyButton *button); void removeVButton(JoyDPadButton::JoyDPadDirections direction); void removeVButton(JoyButton *button); JoyButton *getVButton(JoyDPadButton::JoyDPadDirections direction); bool isEmpty(); virtual QString getName(bool forceFullFormat = false, bool displayName = false) override; virtual QString getXmlName() override; void queueJoyEvent(bool ignoresets = false); bool hasPendingEvent(); void clearPendingEvent(); JoyButton *getUpButton() const; JoyButton *getDownButton() const; JoyButton *getLeftButton() const; JoyButton *getRightButton() const; bool getPendingVDPadEvent() const; public slots: void activatePendingEvent(); private: JoyButton *upButton; JoyButton *downButton; JoyButton *leftButton; JoyButton *rightButton; bool pendingVDPadEvent; }; #endif // VDPAD_H AntiMicroX-antimicrox-2888bf6/src/x11extras.cpp000066400000000000000000000615621377703515000214300ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "common.h" #include "globalvariables.h" #include "messagehandler.h" #include #include #include #include #include #include #include "x11extras.h" static QThreadStorage displays; X11Extras *X11Extras::_instance = nullptr; X11Extras::X11Extras(QObject *parent) : QObject(parent) , knownAliases() { qInstallMessageHandler(MessageHandler::myMessageOutput); _display = XOpenDisplay(nullptr); populateKnownAliases(); _instance = this; } /** * @brief Close display connection if one exists */ X11Extras::~X11Extras() { qInstallMessageHandler(MessageHandler::myMessageOutput); freeDisplay(); _instance = nullptr; } template void freeWindow(T *window) { if (window != nullptr) { XFree(window); window = nullptr; } } void X11Extras::freeDisplay() { if (_display != nullptr) { XCloseDisplay(_display); _display = nullptr; } } X11Extras *X11Extras::getInstance() { qInstallMessageHandler(MessageHandler::myMessageOutput); X11Extras *temp = nullptr; if (!displays.hasLocalData()) { qDebug() << "Displays don't have local data: create new instance of X11Extras"; temp = new X11Extras(); displays.setLocalData(temp); } else { qDebug() << "Display have local data"; temp = displays.localData(); } return temp; } void X11Extras::deleteInstance() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (displays.hasLocalData()) { X11Extras *temp = displays.localData(); delete temp; displays.setLocalData(nullptr); } } const char *X11Extras::getEnvVariable(const char *var) const { const char *val = ::getenv(var); if (val == 0) { return ""; } else { return val; } } /** * @brief Get display instance * @return Display struct */ Display *X11Extras::display() { qInstallMessageHandler(MessageHandler::myMessageOutput); return _display; } bool X11Extras::hasValidDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); return (_display != nullptr); } /** * @brief CURRENTLY NOT USED */ void X11Extras::closeDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); freeDisplay(); } /** * @brief Grab instance of active display. */ void X11Extras::syncDisplay() { qInstallMessageHandler(MessageHandler::myMessageOutput); _display = XOpenDisplay(nullptr); } /** * @brief Grab instance of specified display. Useful for having the GUI * on one display while generating events on another during ssh tunneling. * @param Valid display string that X can use */ void X11Extras::syncDisplay(QString displayString) { qInstallMessageHandler(MessageHandler::myMessageOutput); QByteArray tempByteArray = displayString.toLocal8Bit(); _display = XOpenDisplay(tempByteArray.constData()); } void X11Extras::setCustomDisplay(QString displayString) { qInstallMessageHandler(MessageHandler::myMessageOutput); GlobalVariables::X11Extras::_customDisplayString = displayString; } /** * @brief Return root window for a given X display * @param Screen number. If no value is passed, uses screen 1. * @return XID of the window */ unsigned long X11Extras::appRootWindow(int screen) { qInstallMessageHandler(MessageHandler::myMessageOutput); return (screen == -1) ? XDefaultRootWindow(display()) : XRootWindowOfScreen(XScreenOfDisplay(display(), screen)); } /** * @brief Get appropriate alias for a known KeySym string that might be blank * or contain invalid characters when returned from X. * @param QString representation of a KeySym string * @return Alias string or a blank QString if no alias was found */ QString X11Extras::getDisplayString(QString xcodestring) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (knownAliases.contains(xcodestring)) temp = knownAliases.value(xcodestring); return temp; } void X11Extras::populateKnownAliases() { qInstallMessageHandler(MessageHandler::myMessageOutput); // These aliases are needed for xstrings that would // return empty space characters from XLookupString if (knownAliases.isEmpty()) { knownAliases.insert("Escape", tr("ESC")); knownAliases.insert("Tab", tr("Tab")); knownAliases.insert("space", tr("Space")); knownAliases.insert("Delete", tr("DEL")); knownAliases.insert("Return", tr("Return")); knownAliases.insert("KP_Enter", tr("KP_Enter")); knownAliases.insert("BackSpace", tr("Backspace")); knownAliases.insert("ISO_Level3_Shift", tr("Alt Gr")); } } Window X11Extras::findParentClient(Window window) { qInstallMessageHandler(MessageHandler::myMessageOutput); Window parent = 0; Window root = 0; Window *children = 0; unsigned int num_children = 0; Window finalwindow = 0; Display *display = this->display(); if (windowIsViewable(display, window) && isWindowRelevant(display, window)) { finalwindow = window; } else { bool quitTraversal = false; while (!quitTraversal) { children = 0; if (XQueryTree(display, window, &root, &parent, &children, &num_children)) { if (children) { // must test for NULL XFree(children); } if (parent) { if (windowIsViewable(display, parent) && isWindowRelevant(display, parent)) { quitTraversal = true; finalwindow = parent; } else if (parent == 0) { quitTraversal = true; } else if (parent == root) { quitTraversal = true; } else { window = parent; } } else { quitTraversal = true; } } else { quitTraversal = true; } } } if (display != nullptr) qDebug() << "display in X11Extras::findParentClient(Window window) exists" << endl; else qDebug() << "display in X11Extras::findParentClient(Window window) doesn't exist" << endl; qDebug() << "parent: " << parent << endl; qDebug() << "root: " << root << endl; qDebug() << "num_children: " << num_children << endl; qDebug() << "finalwindow: " << finalwindow << endl; return finalwindow; } /** * @brief Check window and any parents for the window property "_NET_WM_PID" * @param Window XID for window of interest * @return PID of the application instance corresponding to the window */ int X11Extras::getApplicationPid(Window window) { qInstallMessageHandler(MessageHandler::myMessageOutput); Atom atom, actual_type; int actual_format = 0; unsigned long nitems = 0; unsigned long bytes_after = 0; unsigned char *prop = nullptr; int pid = 0; Window finalwindow = 0; Window parent = 0; Window root = 0; Window *children = nullptr; unsigned int num_children; Display *display = this->display(); atom = XInternAtom(display, "_NET_WM_PID", True); checkPropertyOnWin(windowHasProperty(display, window, atom), window, parent, finalwindow, root, children, display, num_children); if (finalwindow) { int status = 0; status = XGetWindowProperty(display, finalwindow, atom, 0, 1024, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); if ((status == 0) && (prop != nullptr)) { pid = prop[1] << 8; pid += prop[0]; XFree(prop); } } return pid; } void X11Extras::checkPropertyOnWin(bool windowCorrected, Window &window, Window &parent, Window &finalwindow, Window &root, Window *children, Display *display, unsigned int &num_children) { if (windowCorrected) { finalwindow = window; } else { bool quitTraversal = false; while (!quitTraversal) { children = nullptr; if (XQueryTree(display, window, &root, &parent, &children, &num_children)) { if (children != nullptr) { // must be a test for NULL XFree(children); } if (parent) { if (windowCorrected) { quitTraversal = true; finalwindow = parent; } else if (parent == 0) { quitTraversal = true; } else if (parent == root) { quitTraversal = true; } else { window = parent; } } else { quitTraversal = true; } } else { quitTraversal = true; } } } } /** * @brief Find the application file location for a given PID * @param PID of window * @return File location of application */ QString X11Extras::getApplicationLocation(int pid) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString exepath = QString(); if (pid > 0) { QString procString = QString("/proc/%1/exe").arg(pid); QFileInfo procFileInfo(procString); if (procFileInfo.exists()) { char buf[1024]; QByteArray tempByteArray = procString.toLocal8Bit(); ssize_t len = readlink(tempByteArray.constData(), buf, sizeof(buf) - 1); if (len != -1) buf[len] = '\0'; if (len > 0) { QString temp = QString::fromUtf8(buf); if (!temp.isEmpty()) exepath = temp; } } } return exepath; } /** * @brief Find the proper client window within a hierarchy. This check is needed * in some environments where the window that has been selected is actually * a child to a transparent parent window which was the one that was * actually grabbed * @param Top window to check * @return Client window XID or 0 if no appropriate window was found */ Window X11Extras::findClientWindow(Window window) { qInstallMessageHandler(MessageHandler::myMessageOutput); Window parent = 1; Window root = 0; Window *children = nullptr; unsigned int num_children = 0; Window finalwindow = 0; Display *display = this->display(); if (windowIsViewable(display, window) && isWindowRelevant(display, window)) { finalwindow = window; } else { XQueryTree(display, window, &root, &parent, &children, &num_children); if (children != nullptr) { for (unsigned int i = 0; (i < num_children) && !finalwindow; i++) { if (windowIsViewable(display, children[i]) && isWindowRelevant(display, window)) { finalwindow = children[i]; } } } if (!finalwindow && (children != nullptr)) { for (unsigned int i = 0; (i < num_children) && !finalwindow; i++) { finalwindow = findClientWindow(children[i]); } } freeWindow(children); } return finalwindow; } bool X11Extras::windowHasProperty(Display *display, Window window, Atom atom) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; Atom actual_type; int actual_format = 0; unsigned long nitems = 0; unsigned long bytes_after = 0; unsigned char *prop = nullptr; int status = 0; status = XGetWindowProperty(display, window, atom, 0, 1024, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); if ((status == Success) && (prop != nullptr)) { result = true; } freeWindow(prop); return result; } bool X11Extras::windowIsViewable(Display *display, Window window) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; XWindowAttributes xwa; XGetWindowAttributes(display, window, &xwa); if ((xwa.c_class == InputOutput) && (xwa.map_state == IsViewable)) { result = true; } return result; } /** * @brief Go through a window's properties and search for an Atom * from a defined list. If an Atom is found in a window's properties, * that window should be considered relevant and one that should be grabbed. * @param Display* * @param Window * @return If a window has a relevant Atom in its properties. */ bool X11Extras::isWindowRelevant(Display *display, Window window) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool result = false; QList temp; temp.append(XInternAtom(display, "WM_STATE", True)); temp.append(XInternAtom(display, "_NW_WM_STATE", True)); temp.append(XInternAtom(display, "_NW_WM_NAME", True)); QListIterator iter(temp); while (iter.hasNext()) { Atom current_atom = iter.next(); if (windowHasProperty(display, window, current_atom)) { iter.toBack(); result = true; } } return result; } QString X11Extras::getWindowTitle(Window window) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); Atom atom, actual_type; int actual_format = 0; unsigned long nitems = 0; unsigned long bytes_after = 0; unsigned char *prop = nullptr; int status = 0; qDebug() << "WIN: 0x" << QString::number(window, 16); Display *display = this->display(); Atom wm_name = XInternAtom(display, "WM_NAME", True); Atom net_wm_name = XInternAtom(display, "_NET_WM_NAME", True); atom = wm_name; QList tempList; tempList.append(wm_name); tempList.append(net_wm_name); QListIterator iter(tempList); while (iter.hasNext()) { Atom temp_atom = iter.next(); if (windowHasProperty(display, window, temp_atom)) { iter.toBack(); atom = temp_atom; } } status = XGetWindowProperty(display, window, atom, 0, 1024, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); if ((status == Success) && (prop != nullptr)) { char *tempprop = reinterpret_cast(prop); temp.append(QString::fromUtf8(tempprop)); qDebug() << temp; } freeWindow(prop); return temp; } QString X11Extras::getWindowClass(Window window) { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); Atom atom, actual_type; int actual_format = 0; unsigned long nitems = 0; unsigned long bytes_after = 0; unsigned char *prop = nullptr; int status = 0; Display *display = this->display(); atom = XInternAtom(display, "WM_CLASS", True); status = XGetWindowProperty(display, window, atom, 0, 1024, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); if ((status == Success) && (prop != nullptr)) { qDebug() << nitems; char *null_char = strchr(reinterpret_cast(prop), '\0'); if (((reinterpret_cast(prop)) + nitems - 1) > null_char) { *(null_char) = ' '; } char *tempprop = reinterpret_cast(prop); temp.append(QString::fromUtf8(tempprop)); qDebug() << temp; qDebug() << reinterpret_cast(prop); } freeWindow(prop); return temp; } unsigned long X11Extras::getWindowInFocus() { qInstallMessageHandler(MessageHandler::myMessageOutput); unsigned long result = 0; Window currentWindow = 0; int focusState = 0; Display *display = this->display(); if (display != nullptr) qDebug() << "display in X11Extras::getWindowInFocus() exists" << endl; else qDebug() << "display in X11Extras::getWindowInFocus() doesn't exist" << endl; XGetInputFocus(display, ¤tWindow, &focusState); if (currentWindow > 0) { result = static_cast(currentWindow); } qDebug() << "focusState of currentWindow: " << focusState << endl; qDebug() << "result of currentWindow: " << result << endl; return result; } /** * @brief Get QString representation of currently utilized X display. * @return */ QString X11Extras::getXDisplayString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return GlobalVariables::X11Extras::_customDisplayString; } int X11Extras::getGroup1KeySym(int virtualkey) { qInstallMessageHandler(MessageHandler::myMessageOutput); Display *display = this->display(); int temp = XKeysymToKeycode(display, virtualkey); return XkbKeycodeToKeysym(display, temp, 0, 0); } void X11Extras::x11ResetMouseAccelerationChange(QString pointerName) { qInstallMessageHandler(MessageHandler::myMessageOutput); int xi_opcode, event, error; xi_opcode = event = error = 0; Display *display = this->display(); bool result = XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error); if (!result) { Logger::LogInfo(tr("xinput extension was not found. No mouse acceleration changes will occur.")); } else { int ximajor = 2, ximinor = 0; if (XIQueryVersion(display, &ximajor, &ximinor) != Success) { Logger::LogInfo(tr("xinput version must be at least 2.0. No mouse acceleration changes will occur.")); result = false; } } if (result) { XIDeviceInfo *all_devices = nullptr; XIDeviceInfo *current_devices = nullptr; XIDeviceInfo *mouse_device = nullptr; int num_devices = 0; all_devices = XIQueryDevice(display, XIAllDevices, &num_devices); findVirtualPtr(num_devices, current_devices, mouse_device, all_devices, pointerName); if (mouse_device != nullptr) { XDevice *device = XOpenDevice(display, static_cast(mouse_device->deviceid)); int num_feedbacks = 0; int feedback_id = -1; XFeedbackState *feedbacks = XGetFeedbackControl(display, device, &num_feedbacks); XFeedbackState *temp = feedbacks; checkFeedback(temp, num_feedbacks, feedback_id); XFree(feedbacks); feedbacks = temp = nullptr; if (feedback_id <= -1) { Logger::LogInfo(tr("PtrFeedbackClass was not found for virtual pointer." "No change to mouse acceleration will occur for device with id=%1") .arg(device->device_id)); result = false; } else { Logger::LogInfo(tr("Changing mouse acceleration for device with id=%1").arg(device->device_id)); XPtrFeedbackControl feedback; feedback.c_class = PtrFeedbackClass; feedback.length = sizeof(XPtrFeedbackControl); feedback.id = static_cast(feedback_id); feedback.threshold = 0; feedback.accelNum = 1; feedback.accelDenom = 1; XChangeFeedbackControl(display, device, DvAccelNum | DvAccelDenom | DvThreshold, reinterpret_cast(&feedback)); XSync(display, false); } XCloseDevice(display, device); } if (all_devices != nullptr) XIFreeDeviceInfo(all_devices); } } void X11Extras::x11ResetMouseAccelerationChange() { qInstallMessageHandler(MessageHandler::myMessageOutput); x11ResetMouseAccelerationChange(GlobalVariables::X11Extras::mouseDeviceName); } struct X11Extras::ptrInformation X11Extras::getPointInformation(QString pointerName) { qInstallMessageHandler(MessageHandler::myMessageOutput); struct ptrInformation tempInfo; int xi_opcode, event, error; xi_opcode = event = error = 0; Display *display = this->display(); bool result = XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error); if (result) { int ximajor = 2, ximinor = 0; if (XIQueryVersion(display, &ximajor, &ximinor) != Success) { Logger::LogInfo(QObject::tr("xinput version must be at least 2.0. No mouse acceleration changes will occur.")); result = false; } } if (result) { XIDeviceInfo *all_devices = nullptr; XIDeviceInfo *current_devices = nullptr; XIDeviceInfo *mouse_device = nullptr; int num_devices = 0; all_devices = XIQueryDevice(display, XIAllDevices, &num_devices); findVirtualPtr(num_devices, current_devices, mouse_device, all_devices, pointerName); if (mouse_device != nullptr) { XDevice *device = XOpenDevice(display, static_cast(mouse_device->deviceid)); int num_feedbacks = 0; int feedback_id = -1; XFeedbackState *feedbacks = XGetFeedbackControl(display, device, &num_feedbacks); XFeedbackState *temp = feedbacks; checkFeedback(temp, num_feedbacks, feedback_id); if (feedback_id <= -1) { result = false; } else { XPtrFeedbackState *tempPtrFeedback = reinterpret_cast(temp); tempInfo.id = feedback_id; tempInfo.accelNum = tempPtrFeedback->accelNum; tempInfo.accelDenom = tempPtrFeedback->accelDenom; tempInfo.threshold = tempPtrFeedback->threshold; } XFree(feedbacks); feedbacks = temp = nullptr; XCloseDevice(display, device); } if (all_devices != nullptr) XIFreeDeviceInfo(all_devices); } return tempInfo; } void X11Extras::findVirtualPtr(int num_devices, XIDeviceInfo *current_devices, XIDeviceInfo *mouse_device, XIDeviceInfo *all_devices, QString pointerName) { for (int i = 0; i < num_devices; i++) { current_devices = &all_devices[i]; if ((current_devices->use == XISlavePointer) && (QString::fromUtf8(current_devices->name) == pointerName)) { mouse_device = current_devices; } } } void X11Extras::checkFeedback(XFeedbackState *temp, int &num_feedbacks, int &feedback_id) { for (int i = 0; (i < num_feedbacks) && (feedback_id == -1); i++) { if (temp->c_class == PtrFeedbackClass) { feedback_id = temp->id; } if ((i + 1) < num_feedbacks) { temp = (XFeedbackState *)((char *)temp + temp->length); } } } struct X11Extras::ptrInformation X11Extras::getPointInformation() { qInstallMessageHandler(MessageHandler::myMessageOutput); return getPointInformation(GlobalVariables::X11Extras::mouseDeviceName); } QPoint X11Extras::getPos() { qInstallMessageHandler(MessageHandler::myMessageOutput); XEvent mouseEvent; Window wid = DefaultRootWindow(display()); XWindowAttributes xwAttr; XQueryPointer(display(), wid, &mouseEvent.xbutton.root, &mouseEvent.xbutton.window, &mouseEvent.xbutton.x_root, &mouseEvent.xbutton.y_root, &mouseEvent.xbutton.x, &mouseEvent.xbutton.y, &mouseEvent.xbutton.state); XGetWindowAttributes(display(), wid, &xwAttr); QPoint currentPoint(mouseEvent.xbutton.x_root, mouseEvent.xbutton.y_root); return currentPoint; } QHash const &X11Extras::getKnownAliases() { return knownAliases; } AntiMicroX-antimicrox-2888bf6/src/x11extras.h000066400000000000000000000064771377703515000211010ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef X11EXTRAS_H #define X11EXTRAS_H #include #include #include #include #include class X11Extras : public QObject { Q_OBJECT public: struct ptrInformation { long id; int threshold; int accelNum; int accelDenom; ptrInformation() { id = -1; threshold = 0; accelNum = 0; accelDenom = 1; } }; ~X11Extras(); unsigned long appRootWindow(int screen = -1); Display *display(); bool hasValidDisplay(); QString getDisplayString(QString xcodestring); int getApplicationPid(Window window); QString getApplicationLocation(int pid); Window findClientWindow(Window window); Window findParentClient(Window window); void closeDisplay(); void syncDisplay(); void syncDisplay(QString displayString); static QString getXDisplayString(); QString getWindowTitle(Window window); QString getWindowClass(Window window); unsigned long getWindowInFocus(); int getGroup1KeySym(int virtualkey); void x11ResetMouseAccelerationChange(); void x11ResetMouseAccelerationChange(QString pointerName); struct ptrInformation getPointInformation(); struct ptrInformation getPointInformation(QString pointerName); static void setCustomDisplay(QString displayString); const char *getEnvVariable(const char *var) const; static X11Extras *getInstance(); static void deleteInstance(); QHash const &getKnownAliases(); protected: explicit X11Extras(QObject *parent = nullptr); void populateKnownAliases(); bool windowHasProperty(Display *display, Window window, Atom atom); bool windowIsViewable(Display *display, Window window); bool isWindowRelevant(Display *display, Window window); static X11Extras *_instance; public slots: QPoint getPos(); private: void checkPropertyOnWin(bool windowCorrected, Window &window, Window &parent, Window &finalwindow, Window &root, Window *children, Display *display, unsigned int &num_children); void freeDisplay(); void checkFeedback(XFeedbackState *temp, int &num_feedbacks, int &feedback_id); void findVirtualPtr(int num_devices, XIDeviceInfo *current_devices, XIDeviceInfo *mouse_device, XIDeviceInfo *all_devices, QString pointerName); QHash knownAliases; Display *_display; }; #endif // X11EXTRAS_H AntiMicroX-antimicrox-2888bf6/src/xml/000077500000000000000000000000001377703515000176525ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/src/xml/inputdevicexml.cpp000066400000000000000000000675231377703515000234330ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "inputdevicexml.h" #include "inputdevice.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joycontrolstick.h" #include "vdpad.h" #include "common.h" #include "globalvariables.h" #include "messagehandler.h" #include #include #include InputDeviceXml::InputDeviceXml(InputDevice *inputDevice, QObject *parent) : QObject(parent) , m_inputDevice(inputDevice) { } void InputDeviceXml::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == m_inputDevice->getXmlName())) { m_inputDevice->transferReset(); xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != m_inputDevice->getXmlName()))) { if ((xml->name() == "sets") && xml->isStartElement()) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "sets"))) { if ((xml->name() == "set") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); index = index - 1; if ((index >= 0) && (index < m_inputDevice->getJoystick_sets().size())) m_inputDevice->getJoystick_sets().value(index)->readConfig(xml); } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } else if ((xml->name() == "stickAxisAssociation") && xml->isStartElement()) { int stickIndex = xml->attributes().value("index").toString().toInt(); int xAxis = xml->attributes().value("xAxis").toString().toInt(); int yAxis = xml->attributes().value("yAxis").toString().toInt(); if ((stickIndex > 0) && (xAxis > 0) && (yAxis > 0)) { xAxis -= 1; yAxis -= 1; stickIndex -= 1; QList setsList = m_inputDevice->getJoystick_sets().values(); for (QList::iterator setJoy = setsList.begin(); setJoy != setsList.end(); setJoy++) { int i = setJoy - setsList.begin(); JoyAxis *axis1 = (*setJoy)->getJoyAxis(xAxis); JoyAxis *axis2 = (*setJoy)->getJoyAxis(yAxis); if ((axis1 != nullptr) && (axis2 != nullptr)) { JoyControlStick *stick = new JoyControlStick(axis1, axis2, stickIndex, i, m_inputDevice); (*setJoy)->addControlStick(stickIndex, stick); } } xml->readNext(); } else { xml->skipCurrentElement(); } } else if ((xml->name() == "vdpadButtonAssociations") && xml->isStartElement()) { int vdpadIndex = xml->attributes().value("index").toString().toInt(); if (vdpadIndex > 0) { QList setsList = m_inputDevice->getJoystick_sets().values(); for (QList::iterator setJoy = setsList.begin(); setJoy != setsList.end(); setJoy++) { int i = setJoy - setsList.begin(); VDPad *vdpad = (*setJoy)->getVDPad(vdpadIndex - 1); if (vdpad == nullptr) { vdpad = new VDPad(vdpadIndex - 1, i, *setJoy, *setJoy); (*setJoy)->addVDPad(vdpadIndex - 1, vdpad); } } xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "vdpadButtonAssociations"))) { if ((xml->name() == "vdpadButtonAssociation") && xml->isStartElement()) { int vdpadAxisIndex = xml->attributes().value("axis").toString().toInt(); int vdpadButtonIndex = xml->attributes().value("button").toString().toInt(); int vdpadDirection = xml->attributes().value("direction").toString().toInt(); if ((vdpadAxisIndex > 0) && (vdpadDirection > 0)) { vdpadAxisIndex -= 1; QList setsListJoy = m_inputDevice->getJoystick_sets().values(); for (QList::iterator setJoyCur = setsListJoy.begin(); setJoyCur != setsListJoy.end(); setJoyCur++) { VDPad *vdpad = (*setJoyCur)->getVDPad(vdpadIndex - 1); if (vdpad != nullptr) { JoyAxis *axis = (*setJoyCur)->getJoyAxis(vdpadAxisIndex); if (axis != nullptr) { JoyButton *button = nullptr; if (vdpadButtonIndex == 0) button = axis->getNAxisButton(); else if (vdpadButtonIndex == 1) button = axis->getPAxisButton(); if (button != nullptr) vdpad->addVButton( static_cast(vdpadDirection), button); } } } } else if ((vdpadButtonIndex > 0) && (vdpadDirection > 0)) { vdpadButtonIndex -= 1; QList setsListJoy = m_inputDevice->getJoystick_sets().values(); for (QList::iterator setJoyCur = setsListJoy.begin(); setJoyCur != setsListJoy.end(); setJoyCur++) { VDPad *vdpad = (*setJoyCur)->getVDPad(vdpadIndex - 1); if (vdpad != nullptr) { JoyButton *button = (*setJoyCur)->getJoyButton(vdpadButtonIndex); if (button != nullptr) vdpad->addVButton(static_cast(vdpadDirection), button); } } } xml->readNext(); } else { xml->skipCurrentElement(); } xml->readNextStartElement(); } } QList setJoys = m_inputDevice->getJoystick_sets().values(); for (QList::iterator currJoy = setJoys.begin(); currJoy != setJoys.end(); currJoy++) { QList VDPadLists = (*currJoy)->getVdpads().values(); for (QList::iterator currVDPad = VDPadLists.begin(); currVDPad != VDPadLists.end(); currVDPad++) { if (((*currVDPad) != nullptr) && (*currVDPad)->isEmpty()) (*currJoy)->removeVDPad(currVDPad - VDPadLists.begin()); } } } else if ((xml->name() == "names") && xml->isStartElement()) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "names"))) { if ((xml->name() == "buttonname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setButtonName(index, temp); } } else if ((xml->name() == "axisbuttonname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); int buttonIndex = xml->attributes().value("button").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; buttonIndex = buttonIndex - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setAxisButtonName(index, buttonIndex, temp); } } else if ((xml->name() == "controlstickbuttonname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); int buttonIndex = xml->attributes().value("button").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setStickButtonName(index, buttonIndex, temp); } } else if ((xml->name() == "dpadbuttonname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); int buttonIndex = xml->attributes().value("button").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setDPadButtonName(index, buttonIndex, temp); } } else if ((xml->name() == "vdpadbuttonname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); int buttonIndex = xml->attributes().value("button").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setVDPadButtonName(index, buttonIndex, temp); } } else if ((xml->name() == "axisname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setAxisName(index, temp); } } else if ((xml->name() == "controlstickname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setStickName(index, temp); } } else if ((xml->name() == "dpadname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setDPadName(index, temp); } } else if ((xml->name() == "vdpadname") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); QString temp = xml->readElementText(); index = index - 1; if ((index >= 0) && !temp.isEmpty()) { m_inputDevice->setVDPadName(index, temp); } } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } } else if ((xml->name() == "keyPressTime") && xml->isStartElement()) { int tempchoice = xml->readElementText().toInt(); if (tempchoice >= 10) { m_inputDevice->setDeviceKeyPressTime(tempchoice); } } else if ((xml->name() == "profilename") && xml->isStartElement()) { m_inputDevice->setProfileName(xml->readElementText()); } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } m_inputDevice->reInitButtons(); } } void InputDeviceXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); xml->writeStartElement(m_inputDevice->getXmlName()); xml->writeAttribute("configversion", QString::number(PadderCommon::LATESTCONFIGFILEVERSION)); xml->writeAttribute("appversion", PadderCommon::programVersion); xml->writeComment("The SDL name for a joystick is included for informational purposes only."); xml->writeTextElement("sdlname", m_inputDevice->getSDLName()); xml->writeComment("The Unique ID for a joystick is included for informational purposes only."); xml->writeTextElement("uniqueID", m_inputDevice->getUniqueIDString()); // xml->writeTextElement("guid", m_inputDevice->getGUIDString()); if (!m_inputDevice->getProfileName().isEmpty()) xml->writeTextElement("profilename", m_inputDevice->getProfileName()); QListIterator currJoyStick(m_inputDevice->getActiveSetJoystick()->getSticks().values()); while (currJoyStick.hasNext()) { JoyControlStick *stick = currJoyStick.next(); xml->writeStartElement("stickAxisAssociation"); xml->writeAttribute("index", QString::number(stick->getRealJoyIndex())); xml->writeAttribute("xAxis", QString::number(stick->getAxisX()->getRealJoyIndex())); xml->writeAttribute("yAxis", QString::number(stick->getAxisY()->getRealJoyIndex())); xml->writeEndElement(); } // write vdpadButtonAssociations QListIterator currVDPad(m_inputDevice->getActiveSetJoystick()->getVdpads().values()); while (currVDPad.hasNext()) { VDPad *vdpad = currVDPad.next(); xml->writeStartElement("vdpadButtonAssociations"); xml->writeAttribute("index", QString::number(vdpad->getRealJoyNumber())); JoyButton *button = vdpad->getVButton(JoyDPadButton::DpadUp); if (button != nullptr) { xml->writeStartElement("vdpadButtonAssociation"); if (typeid(*button) == typeid(JoyAxisButton)) { JoyAxisButton *axisbutton = qobject_cast(button); xml->writeAttribute("axis", QString::number(axisbutton->getAxis()->getRealJoyIndex())); xml->writeAttribute("button", QString::number(button->getJoyNumber())); } else { xml->writeAttribute("axis", QString::number(0)); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); } xml->writeAttribute("direction", QString::number(JoyDPadButton::DpadUp)); xml->writeEndElement(); } button = vdpad->getVButton(JoyDPadButton::DpadDown); if (button != nullptr) { xml->writeStartElement("vdpadButtonAssociation"); if (typeid(*button) == typeid(JoyAxisButton)) { JoyAxisButton *axisbutton = qobject_cast(button); xml->writeAttribute("axis", QString::number(axisbutton->getAxis()->getRealJoyIndex())); xml->writeAttribute("button", QString::number(button->getJoyNumber())); } else { xml->writeAttribute("axis", QString::number(0)); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); } xml->writeAttribute("direction", QString::number(JoyDPadButton::DpadDown)); xml->writeEndElement(); } button = vdpad->getVButton(JoyDPadButton::DpadLeft); if (button != nullptr) { xml->writeStartElement("vdpadButtonAssociation"); if (typeid(*button) == typeid(JoyAxisButton)) { JoyAxisButton *axisbutton = qobject_cast(button); xml->writeAttribute("axis", QString::number(axisbutton->getAxis()->getRealJoyIndex())); xml->writeAttribute("button", QString::number(button->getJoyNumber())); } else { xml->writeAttribute("axis", QString::number(0)); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); } xml->writeAttribute("direction", QString::number(JoyDPadButton::DpadLeft)); xml->writeEndElement(); } button = vdpad->getVButton(JoyDPadButton::DpadRight); if (button != nullptr) { xml->writeStartElement("vdpadButtonAssociation"); if (typeid(*button) == typeid(JoyAxisButton)) { JoyAxisButton *axisbutton = qobject_cast(button); xml->writeAttribute("axis", QString::number(axisbutton->getAxis()->getRealJoyIndex())); xml->writeAttribute("button", QString::number(button->getJoyNumber())); } else { xml->writeAttribute("axis", QString::number(0)); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); } xml->writeAttribute("direction", QString::number(JoyDPadButton::DpadRight)); xml->writeEndElement(); } xml->writeEndElement(); } bool tempHasNames = m_inputDevice->elementsHaveNames(); if (tempHasNames) { xml->writeStartElement("names"); // // write buttons of joystick QListIterator currJoyBtn(m_inputDevice->getActiveSetJoystick()->getButtons().values()); while (currJoyBtn.hasNext()) { JoyButton *button = currJoyBtn.next(); if ((button != nullptr) && !button->getButtonName().isEmpty()) { xml->writeStartElement("buttonname"); xml->writeAttribute("index", QString::number(button->getRealJoyNumber())); xml->writeCharacters(button->getButtonName()); xml->writeEndElement(); } } // write axes of joystick QListIterator currentAxis(m_inputDevice->getActiveSetJoystick()->getAxes()->values()); while (currentAxis.hasNext()) { JoyAxis *axis = currentAxis.next(); if (axis != nullptr) { if (!axis->getAxisName().isEmpty()) { xml->writeStartElement("axisname"); xml->writeAttribute("index", QString::number(axis->getRealJoyIndex())); xml->writeCharacters(axis->getAxisName()); xml->writeEndElement(); } // write button of axis (with negative values) JoyAxisButton *naxisbutton = axis->getNAxisButton(); if (!naxisbutton->getButtonName().isEmpty()) { xml->writeStartElement("axisbuttonname"); xml->writeAttribute("index", QString::number(axis->getRealJoyIndex())); xml->writeAttribute("button", QString::number(naxisbutton->getRealJoyNumber())); xml->writeCharacters(naxisbutton->getButtonName()); xml->writeEndElement(); } // write button of axis (with positive values) JoyAxisButton *paxisbutton = axis->getPAxisButton(); if (!paxisbutton->getButtonName().isEmpty()) { xml->writeStartElement("axisbuttonname"); xml->writeAttribute("index", QString::number(axis->getRealJoyIndex())); xml->writeAttribute("button", QString::number(paxisbutton->getRealJoyNumber())); xml->writeCharacters(paxisbutton->getButtonName()); xml->writeEndElement(); } } } // write sticks QListIterator currStick(m_inputDevice->getActiveSetJoystick()->getSticks().values()); while (currStick.hasNext()) { JoyControlStick *stick = currStick.next(); if (stick != nullptr) { if (!stick->getStickName().isEmpty()) { xml->writeStartElement("controlstickname"); xml->writeAttribute("index", QString::number(stick->getRealJoyIndex())); xml->writeCharacters(stick->getStickName()); xml->writeEndElement(); } // write button of each stick QHash *buttons = stick->getButtons(); QHashIterator iter(*buttons); while (iter.hasNext()) { JoyControlStickButton *button = iter.next().value(); if (button && !button->getButtonName().isEmpty()) { xml->writeStartElement("controlstickbuttonname"); xml->writeAttribute("index", QString::number(stick->getRealJoyIndex())); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); xml->writeCharacters(button->getButtonName()); xml->writeEndElement(); } } } } // write Hats QListIterator currJoyDPad(m_inputDevice->getActiveSetJoystick()->getHats().values()); while (currJoyDPad.hasNext()) { JoyDPad *dpad = currJoyDPad.next(); if (dpad != nullptr) { if (!dpad->getDpadName().isEmpty()) { xml->writeStartElement("dpadname"); xml->writeAttribute("index", QString::number(dpad->getRealJoyNumber())); xml->writeCharacters(dpad->getDpadName()); xml->writeEndElement(); } // write buttons of each Hat QHash *temp = dpad->getButtons(); QHashIterator iter(*temp); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); if (button && !button->getButtonName().isEmpty()) { xml->writeStartElement("dpadbuttonname"); xml->writeAttribute("index", QString::number(dpad->getRealJoyNumber())); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); xml->writeCharacters(button->getButtonName()); xml->writeEndElement(); } } } } // write VDPads QListIterator currVDPad(m_inputDevice->getActiveSetJoystick()->getVdpads().values()); while (currVDPad.hasNext()) { VDPad *vdpad = currVDPad.next(); if (vdpad != nullptr) { if (!vdpad->getDpadName().isEmpty()) { xml->writeStartElement("vdpadname"); xml->writeAttribute("index", QString::number(vdpad->getRealJoyNumber())); xml->writeCharacters(vdpad->getDpadName()); xml->writeEndElement(); } // write buttons of each VDPad QHash *temp = vdpad->getButtons(); QHashIterator iter(*temp); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); if ((button != nullptr) && !button->getButtonName().isEmpty()) { xml->writeStartElement("vdpadbutton"); xml->writeAttribute("index", QString::number(vdpad->getRealJoyNumber())); xml->writeAttribute("button", QString::number(button->getRealJoyNumber())); xml->writeCharacters(button->getButtonName()); xml->writeEndElement(); } } } } xml->writeEndElement(); // } if ((m_inputDevice->getDeviceKeyPressTime() > 0) && (m_inputDevice->getDeviceKeyPressTime() != GlobalVariables::InputDevice::DEFAULTKEYPRESSTIME)) xml->writeTextElement("keyPressTime", QString::number(m_inputDevice->getDeviceKeyPressTime())); xml->writeStartElement("sets"); QHash::const_iterator i = m_inputDevice->getJoystick_sets().constBegin(); while (i != m_inputDevice->getJoystick_sets().constEnd()) { if (!i.value()->isSetEmpty()) i.value()->writeConfig(xml); else qDebug() << "Set is empty"; ++i; } xml->writeEndElement(); xml->writeEndElement(); } AntiMicroX-antimicrox-2888bf6/src/xml/inputdevicexml.h000066400000000000000000000024401377703515000230630ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef INPUTDEVICEXML_H #define INPUTDEVICEXML_H #include class QXmlStreamReader; class QXmlStreamWriter; class InputDevice; class AntiMicroSettings; class InputDeviceXml : public QObject { Q_OBJECT public: explicit InputDeviceXml(InputDevice *inputDevice, QObject *parent = nullptr); public slots: virtual void readConfig(QXmlStreamReader *xml); // InputDeviceXml class virtual void writeConfig(QXmlStreamWriter *xml); // InputDeviceXml class private: InputDevice *m_inputDevice; }; #endif // INPUTDEVICEXML_H AntiMicroX-antimicrox-2888bf6/src/xml/joyaxisxml.cpp000066400000000000000000000162441377703515000225740ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joyaxisxml.h" #include "inputdevice.h" #include "joyaxis.h" #include "joybuttontypes/joyaxisbutton.h" #include "messagehandler.h" #include "xml/joybuttonxml.h" #include #include #include JoyAxisXml::JoyAxisXml(JoyAxis *axis, QObject *parent) : QObject(parent) { m_joyAxis = axis; joyButtonXmlNAxis = new JoyButtonXml(axis->getNAxisButton()); joyButtonXmlPAxis = new JoyButtonXml(axis->getPAxisButton()); } JoyAxisXml::~JoyAxisXml() { if (!joyButtonXmlNAxis.isNull()) delete joyButtonXmlNAxis; if (!joyButtonXmlPAxis.isNull()) delete joyButtonXmlPAxis; } void JoyAxisXml::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == m_joyAxis->getXmlName())) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != m_joyAxis->getXmlName()))) { bool found = readMainConfig(xml); if (!found && (xml->name() == m_joyAxis->getNAxisButton()->getXmlName()) && xml->isStartElement()) { found = true; readButtonConfig(xml); } if (!found) xml->skipCurrentElement(); xml->readNextStartElement(); } } } void JoyAxisXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool currentlyDefault = m_joyAxis->isDefault(); xml->writeStartElement(m_joyAxis->getXmlName()); xml->writeAttribute("index", QString::number(m_joyAxis->getRealJoyIndex())); if (!currentlyDefault) { if (m_joyAxis->getDeadZone() != GlobalVariables::JoyAxis::AXISDEADZONE) xml->writeTextElement("deadZone", QString::number(m_joyAxis->getDeadZone())); if (m_joyAxis->getMaxZoneValue() != GlobalVariables::JoyAxis::AXISMAXZONE) xml->writeTextElement("maxZone", QString::number(m_joyAxis->getMaxZoneValue())); } xml->writeTextElement("center_value", QString::number(m_joyAxis->getAxisCenterCal())); xml->writeTextElement("min_value", QString::number(m_joyAxis->getAxisMinCal())); xml->writeTextElement("max_value", QString::number(m_joyAxis->getAxisMaxCal())); xml->writeStartElement("throttle"); switch (m_joyAxis->getThrottle()) { case -2: xml->writeCharacters("negativehalf"); break; case -1: xml->writeCharacters("negative"); break; case 0: xml->writeCharacters("normal"); break; case 1: xml->writeCharacters("positive"); break; case 2: xml->writeCharacters("positivehalf"); break; } xml->writeEndElement(); if (!currentlyDefault) { joyButtonXmlNAxis->writeConfig(xml); joyButtonXmlPAxis->writeConfig(xml); } xml->writeEndElement(); } bool JoyAxisXml::readMainConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; if ((xml->name() == "deadZone") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); qDebug() << "From xml config dead zone is: " << tempchoice; m_joyAxis->setDeadZone(tempchoice); } else if ((xml->name() == "maxZone") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); qDebug() << "From xml config max zone is: " << tempchoice; m_joyAxis->setMaxZoneValue(tempchoice); } else if ((xml->name() == "center_value") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); qDebug() << "From xml config center value is: " << tempchoice; m_joyAxis->setAxisCenterCal(tempchoice); } else if ((xml->name() == "min_value") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); qDebug() << "From xml config min value is: " << tempchoice; m_joyAxis->setAxisMinCal(tempchoice); } else if ((xml->name() == "max_value") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); qDebug() << "From xml config max value is: " << tempchoice; m_joyAxis->setAxisMaxCal(tempchoice); } else if ((xml->name() == "throttle") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); qDebug() << "From xml config throttle name is: " << temptext; if (temptext == "negativehalf") { m_joyAxis->setThrottle(static_cast(JoyAxis::NegativeHalfThrottle)); } else if (temptext == "negative") { m_joyAxis->setThrottle(static_cast(JoyAxis::NegativeThrottle)); } else if (temptext == "normal") { m_joyAxis->setThrottle(static_cast(JoyAxis::NormalThrottle)); } else if (temptext == "positive") { m_joyAxis->setThrottle(static_cast(JoyAxis::PositiveThrottle)); } else if (temptext == "positivehalf") { m_joyAxis->setThrottle(static_cast(JoyAxis::PositiveHalfThrottle)); } InputDevice *device = m_joyAxis->getParentSet()->getInputDevice(); if (!device->hasCalibrationThrottle(m_joyAxis->getIndex())) { device->setCalibrationStatus(m_joyAxis->getIndex(), static_cast(m_joyAxis->getThrottle())); } m_joyAxis->setCurrentRawValue(m_joyAxis->getCurrentThrottledDeadValue()); m_joyAxis->updateCurrentThrottledValue(m_joyAxis->calculateThrottledValue(m_joyAxis->getCurrentRawValue())); } return found; } bool JoyAxisXml::readButtonConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; int index_local = xml->attributes().value("index").toString().toInt(); if (index_local == 1) { found = true; joyButtonXmlNAxis->readConfig(xml); } else if (index_local == 2) { found = true; joyButtonXmlPAxis->readConfig(xml); } return found; } AntiMicroX-antimicrox-2888bf6/src/xml/joyaxisxml.h000066400000000000000000000026451377703515000222410ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYAXISXML_H #define JOYAXISXML_H #include #include class JoyAxis; class JoyButtonXml; class QXmlStreamReader; class QXmlStreamWriter; class JoyAxisXml : public QObject { Q_OBJECT public: explicit JoyAxisXml(JoyAxis *axis, QObject *parent = nullptr); ~JoyAxisXml(); virtual void readConfig(QXmlStreamReader *xml); virtual void writeConfig(QXmlStreamWriter *xml); virtual bool readMainConfig(QXmlStreamReader *xml); virtual bool readButtonConfig(QXmlStreamReader *xml); private: JoyAxis *m_joyAxis; QPointer joyButtonXmlNAxis; QPointer joyButtonXmlPAxis; }; #endif // JOYAXISXML_H AntiMicroX-antimicrox-2888bf6/src/xml/joybuttonslotxml.cpp000066400000000000000000000375741377703515000240560ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybuttonslotxml.h" #include "antkeymapper.h" #include "globalvariables.h" #include "joybuttonslot.h" #include "messagehandler.h" #include #include #include #include int JoyButtonSlotXml::timeoutWrite = 5000; int JoyButtonSlotXml::timeoutRead = 5000; JoyButtonSlotXml::JoyButtonSlotXml(JoyButtonSlot *joyBtnSlot, QObject *parent) : QObject(parent) , m_joyBtnSlot(joyBtnSlot) { } void JoyButtonSlotXml::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); // QWriteLocker tempLocker(&xmlLock); std::chrono::time_point t1, t2; t1 = std::chrono::high_resolution_clock::now(); bool result = xmlLock.tryLockForWrite(); if (!result && timeoutWrite > 0) xmlLock.tryLockForWrite(timeoutWrite); qDebug() << "START OF READ CONFIG NAME: " << xml->name(); if (xml->isStartElement() && (xml->name() == "slot")) { QString profile = QString(); QString tempStringData = QString(); QString extraStringData = QString(); xml->readNextStartElement(); qDebug() << "NEXT TO THE START TAG NAME: " << xml->name(); // so it must be JoyMix if (!xml->atEnd() && (!xml->isEndElement() && (xml->name() == "slots"))) { qDebug() << "Detected mix slots"; QString slotMixString = QString(); bool firstTimePlus = true; xml->readNextStartElement(); int i = 0; while (xml->name() == "slot") { qDebug() << "Found mini slot in xml file"; xml->readNextStartElement(); // skip to minislot within slots list qDebug() << "Now xml name after read next is: " << xml->name(); // we don't want to add empty slot to minislots // skip again and check name of next tag if (xml->name() == "slot") xml->readNextStartElement(); // if reached the end of mini slots, read next elem, that should be mode JoyMix and break loop if (xml->name() == "slots") { xml->readNextStartElement(); break; } qDebug() << "And now xml name after read next is: " << xml->name(); JoyButtonSlot *minislot = new JoyButtonSlot(); readEachSlot(xml, minislot, profile, tempStringData, extraStringData); i++; m_joyBtnSlot->appendMiniSlot(minislot); if (!firstTimePlus) slotMixString.append('+'); firstTimePlus = false; slotMixString.append(minislot->getSlotString()); qDebug() << "Slot mix string now is named: " << slotMixString; qDebug() << "Added " << i << " minislots to current slot from xml file"; qDebug() << "Added mini slot string and mode and code: " << minislot->getSlotString() << " and " << minislot->getSlotMode() << " and " << minislot->getSlotCode(); qDebug() << "After readEachSlot for JoyMix now should be \"slot\" again or \"mode\": " << xml->name(); qDebug() << "It it start element? :" << (xml->isStartElement() ? "yes" : "no"); } i = 0; if (xml->name() == "mode" && xml->readElementText() == "mix") { qDebug() << "slot text data for joy mix is: " << slotMixString; m_joyBtnSlot->setSlotMode(JoyButtonSlot::JoyMix); m_joyBtnSlot->setTextData(slotMixString); m_joyBtnSlot->setSlotCode(-1); profile = QString(); tempStringData = QString(); extraStringData = QString(); slotMixString = QString(); firstTimePlus = true; xml->readNextStartElement(); } } else { readEachSlot(xml, m_joyBtnSlot, profile, tempStringData, extraStringData); qDebug() << "Detected simple slot: " << m_joyBtnSlot->getSlotString(); } } xmlLock.unlock(); t2 = std::chrono::high_resolution_clock::now(); if (timeoutRead == 3000) timeoutRead = std::chrono::duration_cast(t2 - t1).count(); } void JoyButtonSlotXml::readEachSlot(QXmlStreamReader *xml, JoyButtonSlot *joyBtnSlot, QString &profile, QString &tempStringData, QString &extraStringData) { while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "slot"))) { if ((xml->name() == "code") && xml->isStartElement()) { QString temptext = xml->readElementText(); bool ok = false; int tempchoice = temptext.toInt(&ok, 0); if (ok) joyBtnSlot->setSlotCode(tempchoice); } else if ((xml->name() == "profile") && xml->isStartElement()) { QString temptext = xml->readElementText(); profile = temptext; } else if ((xml->name() == "text") && xml->isStartElement()) { QString temptext = xml->readElementText(); tempStringData = temptext; } else if ((xml->name() == "path") && xml->isStartElement()) { QString temptext = xml->readElementText(); tempStringData = temptext; } else if ((xml->name() == "arguments") && xml->isStartElement()) { QString temptext = xml->readElementText(); extraStringData = temptext; } else if ((xml->name() == "mode") && xml->isStartElement()) { QString temptext = xml->readElementText(); if (temptext == "keyboard") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyKeyboard); } else if (temptext == "mousebutton") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyMouseButton); } else if (temptext == "mousemovement") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyMouseMovement); } else if (temptext == "pause") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyPause); } else if (temptext == "hold") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyHold); } else if (temptext == "cycle") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyCycle); } else if (temptext == "distance") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyDistance); } else if (temptext == "release") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyRelease); } else if (temptext == "mousespeedmod") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyMouseSpeedMod); } else if (temptext == "keypress") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyKeyPress); } else if (temptext == "delay") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyDelay); } else if (temptext == "loadprofile") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyLoadProfile); } else if (temptext == "setchange") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoySetChange); } else if (temptext == "textentry") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyTextEntry); } else if (temptext == "execute") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyExecute); } else if (temptext == "mix") { joyBtnSlot->setSlotMode(JoyButtonSlot::JoyMix); } } else { xml->skipCurrentElement(); } xml->readNextStartElement(); } setSlotData(joyBtnSlot, profile, tempStringData, extraStringData); } void JoyButtonSlotXml::setSlotData(JoyButtonSlot *joyBtnSlot, QString profile, QString tempStringData, QString extraStringData) { if (joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyKeyboard) { int virtualkey = AntKeyMapper::getInstance()->returnVirtualKey(joyBtnSlot->getSlotCode()); int tempkey = joyBtnSlot->getSlotCode(); if (virtualkey) { // Mapping found a valid native keysym. joyBtnSlot->setSlotCode(virtualkey, tempkey); } else if (joyBtnSlot->getSlotCode() > QtKeyMapperBase::nativeKeyPrefix) { // Value is in the native key range. Remove prefix and use // new value as a native keysym. int temp = joyBtnSlot->getSlotCode() - QtKeyMapperBase::nativeKeyPrefix; joyBtnSlot->setSlotCode(temp); } } else if ((joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyLoadProfile) && !profile.isEmpty()) { QFileInfo profileInfo(profile); if (!profileInfo.exists() || !((profileInfo.suffix() == "amgp") || (profileInfo.suffix() == "xml"))) { joyBtnSlot->setTextData(""); } else { joyBtnSlot->setTextData(profile); } } else if (joyBtnSlot->getSlotMode() == JoyButtonSlot::JoySetChange && !(joyBtnSlot->getSlotCode() >= 0) && !(joyBtnSlot->getSlotCode() < GlobalVariables::InputDevice::NUMBER_JOYSETS)) { joyBtnSlot->setSlotCode(-1); } else if ((joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyTextEntry) && !tempStringData.isEmpty()) { joyBtnSlot->setTextData(tempStringData); } else if ((joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyExecute) && !tempStringData.isEmpty()) { QFileInfo tempFile(tempStringData); if (tempFile.exists()) { joyBtnSlot->setTextData(tempStringData); if (!extraStringData.isEmpty()) joyBtnSlot->setExtraData(QVariant(extraStringData)); } } } void JoyButtonSlotXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); // QReadLocker tempLocker(&xmlLock); std::chrono::time_point t1, t2; t1 = std::chrono::high_resolution_clock::now(); bool result = xmlLock.tryLockForRead(); if (!result && timeoutRead > 0) xmlLock.tryLockForRead(timeoutRead); xml->writeStartElement(m_joyBtnSlot->getXmlName()); if (m_joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyMix) { qDebug() << "write JoyMix slot in xml file"; xml->writeStartElement("slots"); QListIterator iterMini(*m_joyBtnSlot->getMixSlots()); while (iterMini.hasNext()) { JoyButtonSlot *minislot = iterMini.next(); qDebug() << "write minislot: " << minislot->getSlotString(); xml->writeStartElement(m_joyBtnSlot->getXmlName()); writeEachSlot(xml, minislot); xml->writeEndElement(); } xml->writeEndElement(); xml->writeStartElement("mode"); xml->writeCharacters("mix"); xml->writeEndElement(); } else { writeEachSlot(xml, m_joyBtnSlot); } xml->writeEndElement(); xmlLock.unlock(); t2 = std::chrono::high_resolution_clock::now(); if (timeoutWrite == 3000) timeoutWrite = std::chrono::duration_cast(t2 - t1).count(); } void JoyButtonSlotXml::writeEachSlot(QXmlStreamWriter *xml, JoyButtonSlot *joyBtnSlot) { qDebug() << "slot mode for " << joyBtnSlot->getSlotString() << " is " << joyBtnSlot->getSlotMode(); if (joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyKeyboard) { int basekey = AntKeyMapper::getInstance()->returnQtKey(joyBtnSlot->getSlotCode()); int qtkey = joyBtnSlot->getSlotCodeAlias(); if ((qtkey > 0) || (basekey > 0)) { // Did not add an alias to slot. If a possible Qt key value // was found, use it. if ((qtkey == 0) && (basekey > 0)) qtkey = basekey; // Found a valid abstract keysym. qDebug() << "ANT KEY: " << QString::number(qtkey, 16); xml->writeTextElement("code", QString("0x%1").arg(qtkey, 0, 16)); } else if (joyBtnSlot->getSlotCode() > 0) { // No abstraction provided for key. Add prefix to native keysym. int tempkey = joyBtnSlot->getSlotCode() | QtKeyMapperBase::nativeKeyPrefix; qDebug() << "ANT KEY: " << QString::number(tempkey, 16); xml->writeTextElement("code", QString("0x%1").arg(tempkey, 0, 16)); } } else if ((joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyLoadProfile) && !joyBtnSlot->getTextData().isEmpty()) { xml->writeTextElement("profile", joyBtnSlot->getTextData()); } else if ((joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyTextEntry) && !joyBtnSlot->getTextData().isEmpty()) { xml->writeTextElement("text", joyBtnSlot->getTextData()); } else if ((joyBtnSlot->getSlotMode() == JoyButtonSlot::JoyExecute) && !joyBtnSlot->getTextData().isEmpty()) { xml->writeTextElement("path", joyBtnSlot->getTextData()); if (!joyBtnSlot->getExtraData().isNull() && joyBtnSlot->getExtraData().canConvert()) { xml->writeTextElement("arguments", joyBtnSlot->getExtraData().toString()); } } else { xml->writeTextElement("code", QString::number(joyBtnSlot->getSlotCode())); } qDebug() << "write mode for " << joyBtnSlot->getSlotString(); xml->writeStartElement("mode"); switch (joyBtnSlot->getSlotMode()) { case JoyButtonSlot::JoyKeyboard: xml->writeCharacters("keyboard"); break; case JoyButtonSlot::JoyMouseButton: xml->writeCharacters("mousebutton"); break; case JoyButtonSlot::JoyMouseMovement: xml->writeCharacters("mousemovement"); break; case JoyButtonSlot::JoyPause: xml->writeCharacters("pause"); break; case JoyButtonSlot::JoyHold: xml->writeCharacters("hold"); break; case JoyButtonSlot::JoyCycle: xml->writeCharacters("cycle"); break; case JoyButtonSlot::JoyDistance: xml->writeCharacters("distance"); break; case JoyButtonSlot::JoyRelease: xml->writeCharacters("release"); break; case JoyButtonSlot::JoyMouseSpeedMod: xml->writeCharacters("mousespeedmod"); break; case JoyButtonSlot::JoyKeyPress: xml->writeCharacters("keypress"); break; case JoyButtonSlot::JoyDelay: xml->writeCharacters("delay"); break; case JoyButtonSlot::JoyLoadProfile: xml->writeCharacters("loadprofile"); break; case JoyButtonSlot::JoySetChange: xml->writeCharacters("setchange"); break; case JoyButtonSlot::JoyTextEntry: xml->writeCharacters("textentry"); break; case JoyButtonSlot::JoyExecute: xml->writeCharacters("execute"); break; case JoyButtonSlot::JoyMix: xml->writeCharacters("mix"); break; } xml->writeEndElement(); } AntiMicroX-antimicrox-2888bf6/src/xml/joybuttonslotxml.h000066400000000000000000000032451377703515000235070ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTONSLOTXML_H #define JOYBUTTONSLOTXML_H #include #include class QXmlStreamReader; class QXmlStreamWriter; class JoyButtonSlot; class JoyButtonSlotXml : public QObject { Q_OBJECT public: explicit JoyButtonSlotXml(JoyButtonSlot *joyBtnSlot, QObject *parent = nullptr); virtual void readConfig(QXmlStreamReader *xml); virtual void writeConfig(QXmlStreamWriter *xml); static int timeoutWrite; static int timeoutRead; private: void writeEachSlot(QXmlStreamWriter *xml, JoyButtonSlot *joyBtnSlot); void readEachSlot(QXmlStreamReader *xml, JoyButtonSlot *joyBtnSlot, QString &profile, QString &tempStringData, QString &extraStringData); void setSlotData(JoyButtonSlot *joyBtnSlot, QString profile, QString tempStringData, QString extraStringData); JoyButtonSlot *m_joyBtnSlot; QReadWriteLock xmlLock; }; #endif // JOYBUTTONSLOTXML_H AntiMicroX-antimicrox-2888bf6/src/xml/joybuttonxml.cpp000066400000000000000000000531151377703515000231410ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joybuttonxml.h" #include "joybutton.h" #include "joybuttonslotxml.h" #include "messagehandler.h" #include #include #include JoyButtonXml::JoyButtonXml(JoyButton *joyButton, QObject *parent) : QObject(parent) { m_joyButton = joyButton; } bool JoyButtonXml::readButtonConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; if ((xml->name() == "toggle") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "true") m_joyButton->setToggle(true); } else if ((xml->name() == "turbointerval") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joyButton->setTurboInterval(tempchoice); } else if ((xml->name() == "turbomode") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "normal") m_joyButton->setTurboMode(JoyButton::NormalTurbo); else if (temptext == "gradient") m_joyButton->setTurboMode(JoyButton::GradientTurbo); else if (temptext == "pulse") m_joyButton->setTurboMode(JoyButton::PulseTurbo); } else if ((xml->name() == "useturbo") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "true") m_joyButton->setUseTurbo(true); } else if ((xml->name() == "mousespeedx") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joyButton->setMouseSpeedX(tempchoice); } else if ((xml->name() == "mousespeedy") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joyButton->setMouseSpeedY(tempchoice); } else if ((xml->name() == "cycleresetactive") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "true") m_joyButton->setCycleResetStatus(true); } else if ((xml->name() == "cycleresetinterval") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); if (tempchoice >= GlobalVariables::JoyButton::MINCYCLERESETTIME) m_joyButton->setCycleResetTime(tempchoice); } else if ((xml->name() == "slots") && xml->isStartElement()) { found = true; xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "slots"))) { if ((xml->name() == "slot") && xml->isStartElement()) { JoyButtonSlot *buttonslot = new JoyButtonSlot(m_joyButton); JoyButtonSlotXml *buttonSlotXml = new JoyButtonSlotXml(buttonslot); buttonSlotXml->readConfig(xml); delete buttonSlotXml; buttonSlotXml = nullptr; if (buttonslot->isValidSlot()) { bool inserted = m_joyButton->insertAssignedSlot(buttonslot, false); if (!inserted) { if (buttonslot->getSlotMode() == JoyButtonSlot::JoyMix && buttonslot->getMixSlots() != nullptr) { qDeleteAll(*buttonslot->getMixSlots()); buttonslot->getMixSlots()->clear(); delete buttonslot->getMixSlots(); buttonslot->assignMixSlotsToNull(); } delete buttonslot; buttonslot = nullptr; } } else { if (buttonslot->getSlotMode() == JoyButtonSlot::JoyMix && buttonslot->getMixSlots() != nullptr) { qDeleteAll(*buttonslot->getMixSlots()); buttonslot->getMixSlots()->clear(); delete buttonslot->getMixSlots(); buttonslot->assignMixSlotsToNull(); } delete buttonslot; buttonslot = nullptr; } } else { xml->skipCurrentElement(); } xml->readNextStartElement(); } } else if ((xml->name() == "setselect") && xml->isStartElement()) { if (!m_joyButton->isModifierButton()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); if ((tempchoice >= 0) && (tempchoice <= GlobalVariables::InputDevice::NUMBER_JOYSETS)) m_joyButton->setChangeSetSelection(tempchoice - 1, false); } } else if ((xml->name() == "setselectcondition") && xml->isStartElement()) { if (!m_joyButton->isModifierButton()) { found = true; QString temptext = xml->readElementText(); JoyButton::SetChangeCondition tempcondition = JoyButton::SetChangeDisabled; if (temptext == "one-way") tempcondition = JoyButton::SetChangeOneWay; else if (temptext == "two-way") tempcondition = JoyButton::SetChangeTwoWay; else if (temptext == "while-held") tempcondition = JoyButton::SetChangeWhileHeld; if (tempcondition != JoyButton::SetChangeDisabled) m_joyButton->setChangeSetCondition(tempcondition, false, false); } } else if ((xml->name() == "mousemode") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "cursor") m_joyButton->setMouseMode(JoyButton::MouseCursor); else if (temptext == "spring") m_joyButton->setMouseMode(JoyButton::MouseSpring); } else if ((xml->name() == "mouseacceleration") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "linear") m_joyButton->setMouseCurve(JoyButton::LinearCurve); else if (temptext == "quadratic") m_joyButton->setMouseCurve(JoyButton::QuadraticCurve); else if (temptext == "cubic") m_joyButton->setMouseCurve(JoyButton::CubicCurve); else if (temptext == "quadratic-extreme") m_joyButton->setMouseCurve(JoyButton::QuadraticExtremeCurve); else if (temptext == "power") m_joyButton->setMouseCurve(JoyButton::PowerCurve); else if (temptext == "precision") m_joyButton->setMouseCurve(JoyButton::EnhancedPrecisionCurve); else if (temptext == "easing-quadratic") m_joyButton->setMouseCurve(JoyButton::EasingQuadraticCurve); else if (temptext == "easing-cubic") m_joyButton->setMouseCurve(JoyButton::EasingCubicCurve); } else if ((xml->name() == "mousespringwidth") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joyButton->setSpringWidth(tempchoice); } else if ((xml->name() == "mousespringheight") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joyButton->setSpringHeight(tempchoice); } else if ((xml->name() == "mousesensitivity") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); double tempchoice = temptext.toDouble(); m_joyButton->setSensitivity(tempchoice); } else if ((xml->name() == "actionname") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (!temptext.isEmpty()) m_joyButton->setActionName(temptext); } else if ((xml->name() == "wheelspeedx") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joyButton->setWheelSpeed(tempchoice, 'X'); } else if ((xml->name() == "wheelspeedy") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joyButton->setWheelSpeed(tempchoice, 'Y'); } else if ((xml->name() == "relativespring") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "true") m_joyButton->setSpringRelativeStatus(true); } else if ((xml->name() == "easingduration") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); double tempchoice = temptext.toDouble(); m_joyButton->setEasingDuration(tempchoice); } else if ((xml->name() == "extraacceleration") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "true") m_joyButton->setExtraAccelerationStatus(true); } else if ((xml->name() == "accelerationmultiplier") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); double tempchoice = temptext.toDouble(); m_joyButton->setExtraAccelerationMultiplier(tempchoice); } else if ((xml->name() == "startaccelmultiplier") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); double tempchoice = temptext.toDouble(); m_joyButton->setStartAccelMultiplier(tempchoice); } else if ((xml->name() == "minaccelthreshold") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); double tempchoice = temptext.toDouble(); m_joyButton->setMinAccelThreshold(tempchoice); } else if ((xml->name() == "maxaccelthreshold") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); double tempchoice = temptext.toDouble(); m_joyButton->setMaxAccelThreshold(tempchoice); } else if ((xml->name() == "accelextraduration") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); double tempchoice = temptext.toDouble(); m_joyButton->setAccelExtraDuration(tempchoice); } else if ((xml->name() == "extraaccelerationcurve") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); JoyButton::JoyExtraAccelerationCurve tempcurve = JoyButton::DEFAULTEXTRAACCELCURVE; if (temptext == "linear") tempcurve = JoyButton::LinearAccelCurve; else if (temptext == "easeoutsine") tempcurve = JoyButton::EaseOutSineCurve; else if (temptext == "easeoutquad") tempcurve = JoyButton::EaseOutQuadAccelCurve; else if (temptext == "easeoutcubic") tempcurve = JoyButton::EaseOutCubicAccelCurve; m_joyButton->setExtraAccelerationCurve(tempcurve); } else if ((xml->name() == "springreleaseradius") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); if (!m_joyButton->isRelativeSpring()) m_joyButton->setSpringDeadCircleMultiplier(tempchoice); } return found; } void JoyButtonXml::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == m_joyButton->getXmlName())) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != m_joyButton->getXmlName()))) { bool found = readButtonConfig(xml); if (!found) xml->skipCurrentElement(); else m_joyButton->buildActiveZoneSummaryString(); xml->readNextStartElement(); } } } void JoyButtonXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!m_joyButton->isDefault()) { xml->writeStartElement(m_joyButton->getXmlName()); xml->writeAttribute("index", QString::number(m_joyButton->getRealJoyNumber())); if (m_joyButton->getToggleState() != GlobalVariables::JoyButton::DEFAULTTOGGLE) xml->writeTextElement("toggle", m_joyButton->getToggleState() ? "true" : "false"); if (m_joyButton->getTurboInterval() != GlobalVariables::JoyButton::DEFAULTTURBOINTERVAL) xml->writeTextElement("turbointerval", QString::number(m_joyButton->getTurboInterval())); if ((m_joyButton->getTurboMode() != JoyButton::DEFAULTTURBOMODE) && (m_joyButton->getTurboMode() == JoyButton::GradientTurbo)) xml->writeTextElement("turbomode", "gradient"); else if ((m_joyButton->getTurboMode() != JoyButton::DEFAULTTURBOMODE) && (m_joyButton->getTurboMode() == JoyButton::PulseTurbo)) xml->writeTextElement("turbomode", "pulse"); if (m_joyButton->isUsingTurbo() != GlobalVariables::JoyButton::DEFAULTUSETURBO) xml->writeTextElement("useturbo", m_joyButton->isUsingTurbo() ? "true" : "false"); if (m_joyButton->getMouseSpeedX() != GlobalVariables::JoyButton::DEFAULTMOUSESPEEDX) xml->writeTextElement("mousespeedx", QString::number(m_joyButton->getMouseSpeedX())); if (m_joyButton->getMouseSpeedY() != GlobalVariables::JoyButton::DEFAULTMOUSESPEEDY) xml->writeTextElement("mousespeedy", QString::number(m_joyButton->getMouseSpeedY())); if ((m_joyButton->getMouseMode() != JoyButton::DEFAULTMOUSEMODE) && (m_joyButton->getMouseMode() == JoyButton::MouseCursor)) { xml->writeTextElement("mousemode", "cursor"); } else if ((m_joyButton->getMouseMode() != JoyButton::DEFAULTMOUSEMODE) && (m_joyButton->getMouseMode() == JoyButton::MouseSpring)) { xml->writeTextElement("mousemode", "spring"); xml->writeTextElement("mousespringwidth", QString::number(m_joyButton->getSpringWidth())); xml->writeTextElement("mousespringheight", QString::number(m_joyButton->getSpringHeight())); } if (m_joyButton->getMouseCurve() != JoyButton::DEFAULTMOUSECURVE) { switch (m_joyButton->getMouseCurve()) { case JoyButton::LinearCurve: xml->writeTextElement("mouseacceleration", "linear"); break; case JoyButton::QuadraticCurve: xml->writeTextElement("mouseacceleration", "quadratic"); break; case JoyButton::CubicCurve: xml->writeTextElement("mouseacceleration", "cubic"); break; case JoyButton::QuadraticExtremeCurve: xml->writeTextElement("mouseacceleration", "quadratic-extreme"); break; case JoyButton::PowerCurve: xml->writeTextElement("mouseacceleration", "power"); xml->writeTextElement("mousesensitivity", QString::number(m_joyButton->getSensitivity())); break; case JoyButton::EnhancedPrecisionCurve: xml->writeTextElement("mouseacceleration", "precision"); break; case JoyButton::EasingQuadraticCurve: xml->writeTextElement("mouseacceleration", "easing-quadratic"); break; case JoyButton::EasingCubicCurve: xml->writeTextElement("mouseacceleration", "easing-cubic"); break; } } if (m_joyButton->getWheelSpeedX() != GlobalVariables::JoyButton::DEFAULTWHEELX) xml->writeTextElement("wheelspeedx", QString::number(m_joyButton->getWheelSpeedX())); if (m_joyButton->getWheelSpeedY() != GlobalVariables::JoyButton::DEFAULTWHEELY) xml->writeTextElement("wheelspeedy", QString::number(m_joyButton->getWheelSpeedY())); if (!m_joyButton->isModifierButton()) { if (m_joyButton->getChangeSetCondition() != JoyButton::SetChangeDisabled) { xml->writeTextElement("setselect", QString::number(m_joyButton->getSetSelection() + 1)); QString temptext = QString(); switch (m_joyButton->getChangeSetCondition()) { case JoyButton::SetChangeOneWay: temptext = "one-way"; break; case JoyButton::SetChangeTwoWay: temptext = "two-way"; break; case JoyButton::SetChangeWhileHeld: temptext = "while-held"; break; default: break; } xml->writeTextElement("setselectcondition", temptext); } } if (!m_joyButton->getActionName().isEmpty()) xml->writeTextElement("actionname", m_joyButton->getActionName()); if (m_joyButton->isCycleResetActive()) xml->writeTextElement("cycleresetactive", "true"); if (m_joyButton->getCycleResetTime() >= GlobalVariables::JoyButton::MINCYCLERESETTIME) xml->writeTextElement("cycleresetinterval", QString::number(m_joyButton->getCycleResetTime())); if (m_joyButton->isRelativeSpring()) xml->writeTextElement("relativespring", "true"); if (!qFuzzyCompare(m_joyButton->getEasingDuration(), GlobalVariables::JoyButton::DEFAULTEASINGDURATION)) xml->writeTextElement("easingduration", QString::number(m_joyButton->getEasingDuration())); if (m_joyButton->isExtraAccelerationEnabled()) xml->writeTextElement("extraacceleration", "true"); if (!qFuzzyCompare(m_joyButton->getExtraAccelerationMultiplier(), GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE)) xml->writeTextElement("accelerationmultiplier", QString::number(m_joyButton->getExtraAccelerationMultiplier())); if (!qFuzzyCompare(m_joyButton->getStartAccelMultiplier(), GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER)) xml->writeTextElement("startaccelmultiplier", QString::number(m_joyButton->getStartAccelMultiplier())); if (!qFuzzyCompare(m_joyButton->getMinAccelThreshold(), GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD)) xml->writeTextElement("minaccelthreshold", QString::number(m_joyButton->getMinAccelThreshold())); if (!qFuzzyCompare(m_joyButton->getMaxAccelThreshold(), GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD)) xml->writeTextElement("maxaccelthreshold", QString::number(m_joyButton->getMaxAccelThreshold())); if (!qFuzzyCompare(m_joyButton->getAccelExtraDuration(), GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION)) xml->writeTextElement("accelextraduration", QString::number(m_joyButton->getAccelExtraDuration())); if (m_joyButton->getSpringDeadCircleMultiplier() != GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS) xml->writeTextElement("springreleaseradius", QString::number(m_joyButton->getSpringDeadCircleMultiplier())); if (m_joyButton->getExtraAccelerationCurve() != JoyButton::DEFAULTEXTRAACCELCURVE) { QString temp = QString(); switch (m_joyButton->getExtraAccelerationCurve()) { case JoyButton::LinearAccelCurve: temp = "linear"; break; case JoyButton::EaseOutSineCurve: temp = "easeoutsine"; break; case JoyButton::EaseOutQuadAccelCurve: temp = "easeoutquad"; break; case JoyButton::EaseOutCubicAccelCurve: temp = "easeoutcubic"; break; } if (!temp.isEmpty()) xml->writeTextElement("extraaccelerationcurve", temp); } // Write information about assigned slots. if (!m_joyButton->getAssignedSlots()->isEmpty()) { xml->writeStartElement("slots"); QListIterator iter(*m_joyButton->getAssignedSlots()); while (iter.hasNext()) { JoyButtonSlot *buttonslot = iter.next(); JoyButtonSlotXml *buttonslotxml = new JoyButtonSlotXml(buttonslot); buttonslotxml->writeConfig(xml); delete buttonslotxml; buttonslotxml = nullptr; } xml->writeEndElement(); } xml->writeEndElement(); } } AntiMicroX-antimicrox-2888bf6/src/xml/joybuttonxml.h000066400000000000000000000023541377703515000226050ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYBUTTONXML_H #define JOYBUTTONXML_H #include class JoyButton; class QXmlStreamReader; class QXmlStreamWriter; class JoyButtonXml : public QObject { Q_OBJECT public: explicit JoyButtonXml(JoyButton *joyButton, QObject *parent = nullptr); virtual bool readButtonConfig(QXmlStreamReader *xml); virtual void readConfig(QXmlStreamReader *xml); virtual void writeConfig(QXmlStreamWriter *xml); private: JoyButton *m_joyButton; }; #endif // JOYBUTTONXML_H AntiMicroX-antimicrox-2888bf6/src/xml/joydpadxml.cpp000066400000000000000000000073011377703515000225320ustar00rootroot00000000000000 #include "joydpadxml.h" #include "globalvariables.h" #include "gamecontroller/gamecontrollerdpad.h" #include "joydpad.h" #include "vdpad.h" #include "xml/joybuttonxml.h" #include "messagehandler.h" #include #include #include #include #include template JoyDPadXml::JoyDPadXml(T *joydpad, QObject *parent) : QObject(parent) { m_joydpad = joydpad; } template void JoyDPadXml::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == m_joydpad->getXmlName())) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != m_joydpad->getXmlName()))) { bool found = readMainConfig(xml); if (!found) { xml->skipCurrentElement(); } xml->readNextStartElement(); } } } template void JoyDPadXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!m_joydpad->isDefault()) { xml->writeStartElement(m_joydpad->getXmlName()); xml->writeAttribute("index", QString::number(m_joydpad->getRealJoyNumber())); if (m_joydpad->getJoyMode() == JoyDPad::EightWayMode) { xml->writeTextElement("mode", "eight-way"); } else if (m_joydpad->getJoyMode() == JoyDPad::FourWayCardinal) { xml->writeTextElement("mode", "four-way"); } else if (m_joydpad->getJoyMode() == JoyDPad::FourWayDiagonal) { xml->writeTextElement("mode", "diagonal"); } if (m_joydpad->getDPadDelay() > GlobalVariables::JoyDPad::DEFAULTDPADDELAY) { xml->writeTextElement("dpadDelay", QString::number(m_joydpad->getDPadDelay())); } QHashIterator iter(*m_joydpad->getJoyButtons()); while (iter.hasNext()) { JoyDPadButton *button = iter.next().value(); JoyButtonXml *joyBtnXml = new JoyButtonXml(button); joyBtnXml->writeConfig(xml); } xml->writeEndElement(); } } template bool JoyDPadXml::readMainConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); bool found = false; if ((xml->name() == "dpadbutton") && xml->isStartElement()) { found = true; int index_local = xml->attributes().value("index").toString().toInt(); JoyDPadButton *button = m_joydpad->getJoyButton(index_local); if (button != nullptr) { JoyButtonXml *joyBtnXml = new JoyButtonXml(button); joyBtnXml->readConfig(xml); } else { xml->skipCurrentElement(); } } else if ((xml->name() == "mode") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); if (temptext == "eight-way") { m_joydpad->setJoyMode(JoyDPad::EightWayMode); } else if (temptext == "four-way") { m_joydpad->setJoyMode(JoyDPad::FourWayCardinal); } else if (temptext == "diagonal") { m_joydpad->setJoyMode(JoyDPad::FourWayDiagonal); } } else if ((xml->name() == "dpadDelay") && xml->isStartElement()) { found = true; QString temptext = xml->readElementText(); int tempchoice = temptext.toInt(); m_joydpad->setDPadDelay(tempchoice); } return found; } template class JoyDPadXml; template class JoyDPadXml; template class JoyDPadXml; AntiMicroX-antimicrox-2888bf6/src/xml/joydpadxml.h000066400000000000000000000023221377703515000221750ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef JOYDPADXML_H #define JOYDPADXML_H #include class QXmlStreamReader; class QXmlStreamWriter; template class JoyDPadXml : public QObject { public: explicit JoyDPadXml(T *joydpad, QObject *parent = nullptr); void readConfig(QXmlStreamReader *xml); // JoyDPadXml class void writeConfig(QXmlStreamWriter *xml); // JoyDPadXml class bool readMainConfig(QXmlStreamReader *xml); private: T *m_joydpad; }; #endif // JOYDPADXML_H AntiMicroX-antimicrox-2888bf6/src/xml/setjoystickxml.cpp000066400000000000000000000155101377703515000234540ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "setjoystickxml.h" #include "xml/joyaxisxml.h" #include "xml/joybuttonxml.h" #include "xml/joydpadxml.h" #include #include #include "joyaxis.h" #include "joybutton.h" #include "joycontrolstick.h" #include "joydpad.h" #include "vdpad.h" #include "setjoystick.h" #include "messagehandler.h" #include #include #include #include #include SetJoystickXml::SetJoystickXml(SetJoystick *setJoystick, QObject *parent) : QObject(parent) , m_setJoystick(setJoystick) { } void SetJoystickXml::readConfig(QXmlStreamReader *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (xml->isStartElement() && (xml->name() == "set")) { xml->readNextStartElement(); while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "set"))) { if ((xml->name() == "button") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); JoyButton *button = m_setJoystick->getJoyButton(index - 1); joyButtonXml = new JoyButtonXml(button); if (button != nullptr) joyButtonXml->readConfig(xml); else xml->skipCurrentElement(); } else if ((xml->name() == "axis") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); JoyAxis *axis = m_setJoystick->getJoyAxis(index - 1); joyAxisXml = new JoyAxisXml(axis); if (axis != nullptr) joyAxisXml->readConfig(xml); else xml->skipCurrentElement(); } else if ((xml->name() == "dpad") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); JoyDPad *dpad = m_setJoystick->getJoyDPad(index - 1); JoyDPadXml *joydpadXml = new JoyDPadXml(dpad); if (dpad != nullptr) joydpadXml->readConfig(xml); else xml->skipCurrentElement(); } else if ((xml->name() == "stick") && xml->isStartElement()) { int stickIndex = xml->attributes().value("index").toString().toInt(); if (stickIndex > 0) { stickIndex -= 1; JoyControlStick *stick = m_setJoystick->getJoyStick(stickIndex); if (stick != nullptr) stick->readConfig(xml); else xml->skipCurrentElement(); } else { xml->skipCurrentElement(); } } else if ((xml->name() == "vdpad") && xml->isStartElement()) { int index = xml->attributes().value("index").toString().toInt(); VDPad *vdpad = m_setJoystick->getVDPad(index - 1); JoyDPadXml *joydpadXml = new JoyDPadXml(vdpad); if (vdpad != nullptr) joydpadXml->readConfig(xml); else xml->skipCurrentElement(); } else if ((xml->name() == "name") && xml->isStartElement()) { QString temptext = xml->readElementText(); if (!temptext.isEmpty()) m_setJoystick->setName(temptext); } else { xml->skipCurrentElement(); // If none of the above, skip the element } xml->readNextStartElement(); } } } void SetJoystickXml::writeConfig(QXmlStreamWriter *xml) { qInstallMessageHandler(MessageHandler::myMessageOutput); if (!m_setJoystick->isSetEmpty()) { xml->writeStartElement("set"); xml->writeAttribute("index", QString::number(m_setJoystick->getIndex() + 1)); if (!m_setJoystick->getName().isEmpty()) xml->writeTextElement("name", m_setJoystick->getName()); QList sticksList = m_setJoystick->getSticks().values(); QListIterator i(sticksList); while (i.hasNext()) i.next()->writeConfig(xml); QList vdpadsList = m_setJoystick->getVdpads().values(); QListIterator vdpad(vdpadsList); while (vdpad.hasNext()) { JoyDPadXml *joydpadXml = new JoyDPadXml(vdpad.next()); joydpadXml->writeConfig(xml); delete joydpadXml; joydpadXml = nullptr; } QList axesList = m_setJoystick->getAxes()->values(); QListIterator axis(axesList); while (axis.hasNext()) { JoyAxis *axisCur = axis.next(); JoyAxisXml *joyAxisXml = new JoyAxisXml(axisCur); if (!axisCur->isPartControlStick() && axisCur->hasControlOfButtons()) { joyAxisXml->writeConfig(xml); } delete joyAxisXml; joyAxisXml = nullptr; } QList dpadsList = m_setJoystick->getHats().values(); QListIterator dpad(dpadsList); while (dpad.hasNext()) { JoyDPadXml *joydpadXml = new JoyDPadXml(dpad.next()); joydpadXml->writeConfig(xml); delete joydpadXml; joydpadXml = nullptr; } QList buttonsList = m_setJoystick->getButtons().values(); QListIterator button(buttonsList); while (button.hasNext()) { JoyButton *buttonCurr = button.next(); if ((buttonCurr != nullptr) && !buttonCurr->isPartVDPad()) { JoyButtonXml *joyButtonXml = new JoyButtonXml(buttonCurr); joyButtonXml->writeConfig(xml); delete joyButtonXml; joyButtonXml = nullptr; } } xml->writeEndElement(); } } AntiMicroX-antimicrox-2888bf6/src/xml/setjoystickxml.h000066400000000000000000000025101377703515000231150ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SETJOYSTICKXML_H #define SETJOYSTICKXML_H #include class SetJoystick; class JoyAxisXml; class JoyButtonXml; class QXmlStreamReader; class QXmlStreamWriter; class SetJoystickXml : public QObject { Q_OBJECT public: explicit SetJoystickXml(SetJoystick *setJoystick, QObject *parent = nullptr); virtual void readConfig(QXmlStreamReader *xml); virtual void writeConfig(QXmlStreamWriter *xml); private: SetJoystick *m_setJoystick; // JoyDPadXml* joydpadXml; JoyAxisXml *joyAxisXml; JoyButtonXml *joyButtonXml; }; #endif // SETJOYSTICKXML_H AntiMicroX-antimicrox-2888bf6/src/xmlconfigmigration.cpp000066400000000000000000000132261377703515000234620ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "xmlconfigmigration.h" #include "antkeymapper.h" #include "common.h" #include "event.h" #include "eventhandlerfactory.h" #include "messagehandler.h" #include #include #include XMLConfigMigration::XMLConfigMigration(QXmlStreamReader *reader, QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); this->reader = reader; if (reader->device() && reader->device()->isOpen()) { this->fileVersion = reader->attributes().value("configversion").toString().toInt(); } else { this->fileVersion = 0; } } bool XMLConfigMigration::requiresMigration() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool toMigrate = false; if ((fileVersion >= 2) && (fileVersion <= PadderCommon::LATESTCONFIGMIGRATIONVERSION)) { toMigrate = true; } return toMigrate; } QString XMLConfigMigration::migrate() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString tempXmlString = QString(); if (requiresMigration()) { QString initialData = readConfigToString(); reader->clear(); reader->addData(initialData); if ((fileVersion >= 2) && (fileVersion <= 5)) { tempXmlString = version0006Migration(); fileVersion = PadderCommon::LATESTCONFIGFILEVERSION; } } return tempXmlString; } QString XMLConfigMigration::readConfigToString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString tempXmlString = QString(); QXmlStreamWriter writer(&tempXmlString); writer.setAutoFormatting(true); while (!reader->atEnd()) { writer.writeCurrentToken(*reader); reader->readNext(); } return tempXmlString; } QString XMLConfigMigration::version0006Migration() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString tempXmlString = QString(); QXmlStreamWriter writer(&tempXmlString); writer.setAutoFormatting(true); reader->readNextStartElement(); reader->readNextStartElement(); writer.writeStartDocument(); writer.writeStartElement("joystick"); writer.writeAttribute("configversion", QString::number(6)); writer.writeAttribute("appversion", PadderCommon::programVersion); while (!reader->atEnd()) { if ((reader->name() == "slot") && reader->isStartElement()) { int slotcode = 0; QString slotmode = QString(); writer.writeCurrentToken(*reader); reader->readNext(); // Grab current slot code and slot mode while (!reader->atEnd() && (!reader->isEndElement() && (reader->name() != "slot"))) { if ((reader->name() == "code") && reader->isStartElement()) { QString tempcode = reader->readElementText(); slotcode = tempcode.toInt(); } else if ((reader->name() == "mode") && reader->isStartElement()) { slotmode = reader->readElementText(); } else { writer.writeCurrentToken(*reader); } reader->readNext(); } // Reformat slot code if associated with the keyboard if (slotcode && !slotmode.isEmpty()) { if (slotmode == "keyboard") { int tempcode = slotcode; BaseEventHandler *handler = EventHandlerFactory::getInstance()->handler(); if (handler->getIdentifier() == "xtest") { slotcode = AntKeyMapper::getInstance()->returnQtKey(X11KeyCodeToX11KeySym(slotcode)); } else { slotcode = 0; tempcode = 0; } if (slotcode > 0) { writer.writeTextElement("code", QString("0x%1").arg(slotcode, 0, 16)); } else if (tempcode > 0) { writer.writeTextElement("code", QString("0x%1").arg(tempcode | QtKeyMapperBase::nativeKeyPrefix, 0, 16)); } } else { writer.writeTextElement("code", QString::number(slotcode)); } writer.writeTextElement("mode", slotmode); } writer.writeCurrentToken(*reader); } else { writer.writeCurrentToken(*reader); } reader->readNext(); } return tempXmlString; } const QXmlStreamReader *XMLConfigMigration::getReader() { return reader; } int XMLConfigMigration::getFileVersion() const { return fileVersion; } AntiMicroX-antimicrox-2888bf6/src/xmlconfigmigration.h000066400000000000000000000025371377703515000231320ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XMLCONFIGMIGRATION_H #define XMLCONFIGMIGRATION_H #include class QXmlStreamReader; class XMLConfigMigration : public QObject { Q_OBJECT public: explicit XMLConfigMigration(QXmlStreamReader *reader, QObject *parent = nullptr); bool requiresMigration(); QString migrate(); const QXmlStreamReader *getReader(); int getFileVersion() const; private: QString readConfigToString(); QString version0006Migration(); QXmlStreamReader *reader; int fileVersion; }; #endif // XMLCONFIGMIGRATION_H AntiMicroX-antimicrox-2888bf6/src/xmlconfigreader.cpp000066400000000000000000000141141377703515000227300ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "xmlconfigreader.h" #include "common.h" #include "globalvariables.h" #include "inputdevice.h" #include "joystick.h" #include "messagehandler.h" #include "xmlconfigmigration.h" #include "xmlconfigwriter.h" #include "common.h" #include "gamecontroller/gamecontroller.h" #include "gamecontroller/xml/gamecontrollerxml.h" #include #include #include #include #include XMLConfigReader::XMLConfigReader(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); xml = new QXmlStreamReader(); configFile = nullptr; m_joystick = nullptr; initDeviceTypes(); } XMLConfigReader::~XMLConfigReader() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (configFile != nullptr) { if (configFile->isOpen()) configFile->close(); delete configFile; configFile = nullptr; } if (xml != nullptr) { delete xml; xml = nullptr; } if (!m_joystickXml.isNull()) delete m_joystickXml; } void XMLConfigReader::setJoystick(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_joystick = joystick; } void XMLConfigReader::setFileName(QString filename) { qInstallMessageHandler(MessageHandler::myMessageOutput); QFile *temp = new QFile(filename); if (temp->exists()) { configFile = temp; } else { delete temp; temp = nullptr; } } void XMLConfigReader::configJoystick(InputDevice *joystick) { qInstallMessageHandler(MessageHandler::myMessageOutput); m_joystick = joystick; read(); } bool XMLConfigReader::read() { qInstallMessageHandler(MessageHandler::myMessageOutput); bool error = false; if ((configFile != nullptr) && configFile->exists() && (m_joystick != nullptr)) { xml->clear(); if (!configFile->isOpen()) { configFile->open(QFile::ReadOnly | QFile::Text); xml->setDevice(configFile); } xml->readNextStartElement(); if (!deviceTypes.contains(xml->name().toString())) { xml->raiseError("Root node is not a joystick or controller"); } else if (xml->name() == GlobalVariables::Joystick::xmlName) { XMLConfigMigration migration(xml); if (migration.requiresMigration()) { QString migrationString = migration.migrate(); if (migrationString.length() > 0) { xml->clear(); // Remove QFile from reader and clear state xml->addData(migrationString); // Add converted XML string to reader xml->readNextStartElement(); // Skip joystick root node configFile->close(); // Close current config file configFile->open(QFile::WriteOnly | QFile::Text); // Write converted XML to file if (configFile->isOpen()) { configFile->write(migrationString.toLocal8Bit()); configFile->close(); } else { xml->raiseError(tr("Could not write updated profile XML to file %1.").arg(configFile->fileName())); } } } } while (!xml->atEnd()) { if (xml->isStartElement() && deviceTypes.contains(xml->name().toString())) { m_joystickXml = new InputDeviceXml(m_joystick); m_joystickXml->readConfig(xml); // if (!m_joystickXml.isNull()) delete m_joystickXml; } else { // If none of the above, skip the element xml->skipCurrentElement(); } xml->readNextStartElement(); } if (configFile->isOpen()) configFile->close(); if (xml->hasError() && (xml->error() != QXmlStreamReader::PrematureEndOfDocumentError)) { error = true; } else if (xml->hasError() && (xml->error() == QXmlStreamReader::PrematureEndOfDocumentError)) { xml->clear(); } } return error; } const QString XMLConfigReader::getErrorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); QString temp = QString(); if (xml->hasError()) temp = xml->errorString(); return temp; } bool XMLConfigReader::hasError() { qInstallMessageHandler(MessageHandler::myMessageOutput); return xml->hasError(); } void XMLConfigReader::initDeviceTypes() { qInstallMessageHandler(MessageHandler::myMessageOutput); deviceTypes.clear(); deviceTypes.append(GlobalVariables::Joystick::xmlName); deviceTypes.append(GlobalVariables::GameController::xmlName); } const QXmlStreamReader *XMLConfigReader::getXml() { return xml; } QString const &XMLConfigReader::getFileName() { return fileName; } const QFile *XMLConfigReader::getConfigFile() { return configFile; } const InputDevice *XMLConfigReader::getJoystick() { return m_joystick; } QStringList const &XMLConfigReader::getDeviceTypes() { return deviceTypes; } AntiMicroX-antimicrox-2888bf6/src/xmlconfigreader.h000066400000000000000000000034471377703515000224040ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XMLCONFIGREADER_H #define XMLCONFIGREADER_H #include #include #include class InputDevice; class QXmlStreamReader; class InputDeviceXml; class QFile; class XMLConfigReader : public QObject { Q_OBJECT public: explicit XMLConfigReader(QObject *parent = nullptr); ~XMLConfigReader(); void setJoystick(InputDevice *joystick); void setFileName(QString filename); const QString getErrorString(); bool hasError(); bool read(); const QXmlStreamReader *getXml(); QString const &getFileName(); const QFile *getConfigFile(); const InputDevice *getJoystick(); QPointer m_joystickXml; QStringList const &getDeviceTypes(); protected: void initDeviceTypes(); public slots: void configJoystick(InputDevice *joystick); private: QXmlStreamReader *xml; QString fileName; QFile *configFile; InputDevice *m_joystick; QStringList deviceTypes; }; #endif // XMLCONFIGREADER_H AntiMicroX-antimicrox-2888bf6/src/xmlconfigwriter.cpp000066400000000000000000000060141377703515000230020ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "xmlconfigwriter.h" #include "common.h" #include "inputdevice.h" #include "messagehandler.h" #include "xml/inputdevicexml.h" #include #include #include #include XMLConfigWriter::XMLConfigWriter(QObject *parent) : QObject(parent) { qInstallMessageHandler(MessageHandler::myMessageOutput); xml = new QXmlStreamWriter(); xml->setAutoFormatting(true); configFile = nullptr; m_joystick = nullptr; m_joystickXml = nullptr; writerError = false; } XMLConfigWriter::~XMLConfigWriter() { qInstallMessageHandler(MessageHandler::myMessageOutput); if (configFile != nullptr) { if (configFile->isOpen()) configFile->close(); delete configFile; configFile = nullptr; } if (xml != nullptr) { delete xml; xml = nullptr; } } void XMLConfigWriter::write(InputDeviceXml *joystickXml) { qInstallMessageHandler(MessageHandler::myMessageOutput); writerError = false; if (!configFile->isOpen()) { configFile->open(QFile::WriteOnly | QFile::Text); xml->setDevice(configFile); } else { writerError = true; writerErrorString = tr("Could not write to profile at %1.").arg(configFile->fileName()); } if (!writerError) { xml->writeStartDocument(); joystickXml->writeConfig(xml); xml->writeEndDocument(); } if (configFile->isOpen()) configFile->close(); } void XMLConfigWriter::setFileName(QString filename) { qInstallMessageHandler(MessageHandler::myMessageOutput); QFile *temp = new QFile(filename); fileName = filename; configFile = temp; } bool XMLConfigWriter::hasError() { qInstallMessageHandler(MessageHandler::myMessageOutput); return writerError; } const QString XMLConfigWriter::getErrorString() { qInstallMessageHandler(MessageHandler::myMessageOutput); return writerErrorString; } const QXmlStreamWriter *XMLConfigWriter::getXml() { return xml; } QString const &XMLConfigWriter::getFileName() { return fileName; } const QFile *XMLConfigWriter::getConfigFile() { return configFile; } const InputDevice *XMLConfigWriter::getJoystick() { return m_joystick; } AntiMicroX-antimicrox-2888bf6/src/xmlconfigwriter.h000066400000000000000000000031671377703515000224550ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XMLCONFIGWRITER_H #define XMLCONFIGWRITER_H #include class InputDevice; class QXmlStreamWriter; class InputDeviceXml; class QFile; class XMLConfigWriter : public QObject { Q_OBJECT public: explicit XMLConfigWriter(QObject *parent = nullptr); ~XMLConfigWriter(); void setFileName(QString filename); bool hasError(); const QString getErrorString(); const QXmlStreamWriter *getXml(); QString const &getFileName(); const QFile *getConfigFile(); const InputDevice *getJoystick(); public slots: void write(InputDeviceXml *joystickXml); private: QXmlStreamWriter *xml; QString fileName; QFile *configFile; InputDevice *m_joystick; InputDeviceXml *m_joystickXml; bool writerError; QString writerErrorString; }; #endif // XMLCONFIGWRITER_H AntiMicroX-antimicrox-2888bf6/tests/000077500000000000000000000000001377703515000174255ustar00rootroot00000000000000AntiMicroX-antimicrox-2888bf6/tests/CMakeLists.txt000066400000000000000000000013111377703515000221610ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8.11) project(aboutdialogClass) # Tell CMake to run moc when necessary: set(CMAKE_AUTOMOC ON) # As moc files are generated in the binary dir, tell CMake # to always look for includes there: set(CMAKE_INCLUDE_CURRENT_DIR ON) find_package(Qt5Test REQUIRED) set(GUIS_SRCS testaboutdialog.cpp testaddeditautoprofiledialog.cpp testadvancebuttondialog.cpp testcalibration.cpp testjoycontrolstickeditdialog.cpp testbuttoneditdialog.cpp testquicksetdialog.cpp testqkeydisplaydialog.cpp ) add_executable(GuiTests ${GUIS_SRCS}) #target_link_libraries( GuiTests antilib Qt5::Test ) ADD_TEST(NAME GuiTests COMMAND GuiTests) AntiMicroX-antimicrox-2888bf6/tests/testaboutdialog.cpp000066400000000000000000000055101377703515000233240ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "aboutdialog.h" #include #include #include #include class TestAboutDialog: public QObject { Q_OBJECT public: TestAboutDialog(QObject* parent = 0); private slots: void testVersion(); void infoTextBrowserEmpty(); void changelogPlainEmpty(); void textBrowserDevsEmpty(); void licenseInfoEmpty(); void creditsInfoEmpty(); private: AboutDialog aboutDialog; }; TestAboutDialog::TestAboutDialog(QObject* parent) : QObject(parent), aboutDialog() { QTestEventLoop::instance().enterLoop(1); } void TestAboutDialog::infoTextBrowserEmpty() { QTextBrowser* infoTextBrowser = aboutDialog.findChild("infoTextBrowser"); QVERIFY2(!infoTextBrowser->toPlainText().isEmpty(), "infoTextBrowser is empty"); } void TestAboutDialog::changelogPlainEmpty() { QPlainTextEdit* changelogTextEdit = aboutDialog.findChild("changelogTextEdit"); QVERIFY2(!changelogTextEdit->toPlainText().isEmpty(), "changelogTextEdit is empty"); } void TestAboutDialog::textBrowserDevsEmpty() { QPlainTextEdit* developersInfo = aboutDialog.findChild("plainTextEdit"); QVERIFY2(!developersInfo->toPlainText().isEmpty(), "plainTextEdit for info about developers is empty"); } void TestAboutDialog::licenseInfoEmpty() { QTextBrowser* licenseInfo = aboutDialog.findChild("textBrowser_2"); QVERIFY2(!licenseInfo->toPlainText().isEmpty(), "textBrowser_2 about license information is empty"); } void TestAboutDialog::creditsInfoEmpty() { QTextBrowser* creditsInfo = aboutDialog.findChild("textBrowser"); QVERIFY2(!creditsInfo->toPlainText().isEmpty(), "textBrowser about credits is empty"); } void TestAboutDialog::testVersion() { QLabel* versionLabel = aboutDialog.findChild("versionLabel"); QCOMPARE(versionLabel->text(), QString("2.25")); } QTEST_MAIN(TestAboutDialog) #include "testaboutdialog.moc" AntiMicroX-antimicrox-2888bf6/tests/testaddeditautoprofiledialog.cpp000066400000000000000000000077161377703515000260740ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #inlude "addeditautoprofiledialog.h" #include /* AutoProfileInfo* getAutoProfile() const; // if not empty then 1) profileLineEdit must be equal to getAutoProfile()->getProfileLocation() 2) devicesComboBox must be equal to getAutoProfile()->getDeviceName() 3) winClassLineEdit must be equal to getAutoProfile()->getWindowClass() 4) if getAutoProfile()->isPartialState() then should be setPartialCheckBox->checked() 5) if getAutoProfile()->isCurrentDefault() then should be asDefaultCheckBox->checked() 6) if getAutoProfile()->getWindowName() is not empty then should be winNameLineEdit->text() == getAutoProfile()->getWindowName() 7) if getAutoProfile()->getExe() is not empty then should be applicationLineEdit->text() == getAutoProfile()->getExe() //QString getOriginalGUID() const; QString getOriginalUniqueID() const; QString getOriginalExe() const; QString getOriginalWindowClass() const; QString getOriginalWindowName() const; QList *getDevices() const; // cannot be empty AntiMicroSettings *getSettings() const; // cannot be empty bool getEditForm() const; bool getDefaultInfo() const; // QList const& getReservedGUIDs(); QList const& getReservedUniques(); // cannot be empty profileBrowsePushButton not disabled detectWinPropsSelectWindowPushButton not disabled devicesComboBox not disabled and not empty asDefaultCheckBox not disabled if devicesComboBox first element is not -1 asDefaultCheckBox disabled if devicesComboBox first element is -1 buttonBox Cancel not disabled applicationPushButton not disabled selectWindowPushButton not disabled profileLineEdit not disabled winClassLineEdit not disabled winNameLineEdit not disabled applicationLineEdit not disabled buttonBox Ok disabled if profileLineEdit is empty and doesn't exist and devicesComboBox first element is empty and winClassLineEdit is empty buttonBox Ok enabled if profileLineEdit isn't empty and exist and devicesComboBox first element is not empty and winClassLineEdit is not empty test keyClick on profileBrowsePushButton test keyClick on detectWinPropsSelectWindowPushButton test keyClick on buttonBox->cancel test keyClick on applicationPushButton test keyClick on selectWindowPushButton test mouseClick on profileBrowsePushButton test mouseClick on detectWinPropsSelectWindowPushButton test mouseClick on buttonBox->cancel test mouseClick on applicationPushButton test mouseClick on selectWindowPushButton */ class TestAddEditAutoProfileDialog: public QObject { Q_OBJECT public: TestAddEditAutoProfileDialog(QObject* parent = 0); void checkAutoProfile(); void checkOriginalUniqueIDs(); private slots: private: AddEditAutoProfileDialog addEditAutoProfileDialog; }; TestAddEditAutoProfileDialog::TestAddEditAutoProfileDialog(QObject* parent) : QObject(parent), addEditAutoProfileDialog() { QTestEventLoop::instance().enterLoop(1); } // QTEST_MAIN(TestAddEditAutoProfileDialog) #include "testaddeditautoprofiledialog.moc" AntiMicroX-antimicrox-2888bf6/tests/testadvancebuttondialog.cpp000066400000000000000000000152301377703515000250470ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "advancebuttondialog.h" #include /* window title should be Advanced: gamepadBtn first slot cannot be empty first slot value should be equal to last pressed button if getAssignedSlots() is not empty then slots should be equal and in order to getAssignedSlots() elements if from comboBox is chosen "Blank or KB/M" then text should be tr("Insert a new blank slot.") if from comboBox is chosen "Cycle" then text should be tr("Slots past a Cycle action will be executed " "on the next button press. Multiple cycles can be added " "in order to create partitions in a sequence.") if from comboBox is chosen "Delay" then text should be tr("Delays the time that the next slot is activated " "by the time specified. Slots activated before the " "delay will remain active after the delay time " "has passed.") if from comboBox is chosen "Distance" then text should be tr("Distance action specifies that the slots afterwards " "will only be executed when an axis is moved " "a certain range past the designated dead zone.") if from comboBox is chosen "Execute" then text should be tr("Execute program when slot is activated.") if from comboBox is chosen "Hold" then text should be tr("Insert a hold action. Slots after the action will only be " "executed if the button is held past the interval specified.") if from comboBox is chosen "Load" then text should be tr("Chose a profile to load when this slot is activated.") if from comboBox is chosen "Mouse Mod" then text should be tr("Mouse mod action will modify all mouse speed settings " "by a specified percentage while the action is being processed. " "This can be useful for slowing down the mouse while " "sniping.") if from comboBox is chosen "Pause" then text should be tr("Insert a pause that occurs in between key presses.") if from comboBox is chosen "Press Time" then text should be tr("Specify the time that keys past this slot should be " "held down.") if from comboBox is chosen "Release" then text should be tr("Insert a release action. Slots after the action will only be " "executed after a button release if the button was held " "past the interval specified.") if from comboBox is chosen "Set Change" then text should be tr("Change to selected set once slot is activated.") if from comboBox is chosen "Text Entry" then text should be tr("Full string will be typed when a " "slot is activated.") if last empty slot clicked and press some keyboard value it should hold new value from keyboard if clicked "Clear all" button then there should be only one slot that is empty if clicked "Delete" button and if current slot is not first, then should be destroyed if clicked "Delete" burron on first slot, but there are other slots, then first slot is the second one, previous first slot is destroyed if clicked "Delete" button on first slot and there aren't any other slots, then the first slot is not destroyed but is empty Toggle->checkbox is not disabled if Turbo->checkbox is not checked then turboSlider is disabled if Turbo->checkbox is checked then turboSlider is enabled if Turbo->delay label is equal to sliderValue / 100.0 + sec. if Turbo->rate is equal to 100.0 / sliderValue + /sec. if Set Selector->comboBox->count == 22 enum SlotTypeComboIndex { KBMouseSlot = 0, CycleSlot, DelaySlot, DistanceSlot, ExecuteSlot, HoldSlot, LoadSlot, MouseModSlot, PauseSlot, PressTimeSlot, ReleaseSlot, SetChangeSlot, TextEntry }; if SlotTypeComboIndex::KBMouseSlot == 0, SlotTypeComboIndex::CycleSlot == 1 itd if last empty slot clicked and press some keyboard value it should hold new value from keyboard if clicked "Clear all" button then there should be only one slot that is empty if clicked "Delete" button and if current slot is not first, then should be destroyed if clicked "Delete" burron on first slot, but there are other slots, then first slot is the second one, previous first slot is destroyed if clicked "Delete" button on first slot and there aren't any other slots, then the first slot is not destroyed but is empty Toggle->checkbox is not disabled if Turbo->checkbox is not checked then turboSlider is disabled if Turbo->checkbox is checked then turboSlider is enabled if Turbo->delay label is equal to sliderValue / 100.0 + sec. if Turbo->rate is equal to 100.0 / sliderValue + /sec. if Set Selector->comboBox->count == 22 enum SlotTypeComboIndex { KBMouseSlot = 0, CycleSlot, DelaySlot, DistanceSlot, ExecuteSlot, HoldSlot, LoadSlot, MouseModSlot, PauseSlot, PressTimeSlot, ReleaseSlot, SetChangeSlot, TextEntry }; if SlotTypeComboIndex::KBMouseSlot == 0, SlotTypeComboIndex::CycleSlot == 1 itd if slot->getSlotMode() == JoyButtonSlot::JoySetChange then ui->slotSetChangeComboBox->findData(QVariant(slot->getSlotCode())) >= 0 close/cancel button cannot be disabled */ class TestAdvanceButtonDialog: public QObject { Q_OBJECT public: TestAdvanceButtonDialog(QObject* parent = 0); private slots: private: AdvanceButtonDialog advanceButtonDialog; }; TestAdvanceButtonDialog::TestAdvanceButtonDialog(QObject* parent) : QObject(parent), advanceButtonDialog() { QTestEventLoop::instance().enterLoop(1); } // QTEST_MAIN(TestAdvanceButtonDialog) #include "testadvancebuttondialog.moc" AntiMicroX-antimicrox-2888bf6/tests/testbuttoneditdialog.cpp000066400000000000000000000051411377703515000243730ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "buttoneditdialog.h" #include /* if slotSummaryLabel->text() == tr("[NO KEY]") and lastJoyButton is nullptr lastJoyButton->getSlotsString().replace("&", "&&") == tr("[NO KEY]") then advancedPushButton should be disabled if slotSummaryLabel->text() != tr("[NO KEY]") and lastJoyButton is not nullptr and lastJoyButton->getSlotsString().replace("&", "&&") != tr("[NO KEY]") then advancedPushButton should be enabled toggleCheckBox should be checked if lastJoyButton->getToggleState() turboCheckBox should be checked if lastJoyButton->isUsingTurbo() buttonNameLineEdit cannot be disabled actionNameLineEdit cannot be disabled buttonBox->Cancel cannot be disabled virtualKeyMouseTabWidget->tab(0)->->findChildren () check if each QString getXcodestring() const; != "" QString getDisplayString() const; != tr("[NO KEY]") int getKeycode() const; != 0 int getQkeyalias() const; != 0 only if it's not a none button and otherKeysPushbutton QList newlist = mouseTab->findChildren(); QListIterator iter(newlist); while (iter.hasNext()) { VirtualMousePushButton *mousebutton = iter.next(); // test if getMouseCode() is not null or less } getOtherKeysMenu()-actions() if AntKeyMapper::getInstance()->returnQtKey(oneFromListAction) != 0 */ class TestButtonEditDialog: public QObject { Q_OBJECT public: TestButtonEditDialog(QObject* parent = 0); private slots: private: ButtonEditDialog buttonEditDialog; }; TestButtonEditDialog::TestButtonEditDialog(QObject* parent) : QObject(parent), buttonEditDialog() { QTestEventLoop::instance().enterLoop(1); } // QTEST_MAIN(TestButtonEditDialog) #include "testbuttoneditdialog.moc" AntiMicroX-antimicrox-2888bf6/tests/testcalibration.cpp000066400000000000000000000100061377703515000233150ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "calibration.h" #include /* resetBtn should be enabled when !stick->wasCalibrated() resetBtn should be disabled when stick->wasCalibrated() Calibration->findChildren() count is equal to 2 startButton cannot be disabled cancelBtn cannot be disabled saveBtn is enabled when ui->steps->text() == tr("\n---Calibration done!---\n") && stick->setCalibrationSummary != ui->Informations->text() || this->text != stick->setCalibrationSummary saveBtn is disabled when ui->steps->text() != tr("\n---Calibration done!---\n") && stick->setCalibrationSummary == ui->Informations->text() || this->text == stick->setCalibrationSummary controllersBox->count() == this->joysticks->count int currContrBoxIndex = ui->controllersBox->currentIndex(); QList sticksList = joysticks->value(currContrBoxIndex)->getSetJoystick(currContrBoxIndex)->getSticks().values(); QList currStick(sticksList); ui->axesBox->count == currStick->count // test for other controllers and sticks too at the same time if each controlstick.data()->thread()->priority() != InheritPriority // if each thread is running, otherwise show priority if window title == tr("Calibration") if ui->stickStatusBoxWidget->getStick == ui->axesBox at 0 // ACTIONS if there are ui->axesBox->count > 1 choose the next one and check if ui->stickStatusBoxWidget->getStick == ui->axesBox at 0 && joyAxisX = controlstick->getAxisX(); joyAxisY = controlstick->getAxisY(); if progressBarsLayout->->itemAt(0)->widget() == tr("Axis %1").arg(joyAxisX->getRealJoyIndex()) and progressBarsLayout->->itemAt(2)->widget() == tr("Axis %1").arg(joyAxisY->getRealJoyIndex()) check results of connect(joyAxisX, &JoyAxis::moved, this, &Calibration::checkX); connect(joyAxisY, &JoyAxis::moved, this, &Calibration::checkY); test methods 1) no values 2) various expected values 3) various unexpected values 4) really big values 5) values below 0 int Calibration::chooseMinMax(QString min_max_sign, QList ax_values) Calibration::checkX(int value) Calibration::checkY(int value) Calibration::setController(QString controllerName) Calibration::setProgressBars(int inputDevNr, int setJoyNr, int stickNr) Calibration::setProgressBars(JoyControlStick* controlstick) bool Calibration::enoughProb(int x_count, int y_count, QString character) int Calibration::calibratedDeadZone(int center, int deadzone) void Calibration::summarizeValues(int &numbFromList, const int &mappednumb) void Calibration::getMinVal(int &numbFromList, const int &mappednumb) void Calibration::getMaxVal(int &numbFromList, const int &mappednumb) void Calibration::setQuadraticZoneCalibrated(int &max_axis_val_x, int &min_axis_val_x, int &max_axis_val_y, int &min_axis_val_y) void Calibration::restoreCalValues() -> if all local variables are default again */ class TestCalibration: public QObject { Q_OBJECT public: TestCalibration(QObject* parent = 0); private slots: private: TestCalibration calibrationDialog; }; TestCalibration::TestCalibration(QObject* parent) : QObject(parent), Calibration() { QTestEventLoop::instance().enterLoop(1); } // QTEST_MAIN(TestAdvanceButtonDialog) #include "testcalibration.moc" AntiMicroX-antimicrox-2888bf6/tests/testjoycontrolstickeditdialog.cpp000066400000000000000000000100321377703515000263130ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "joycontrolstickeditdialog.h" #include /* presetsComboBox->count should be 12 joyModeComboBox->count should be 4 deadZoneSlider->value == stick->getDeadZone() deadZoneSpinBox->value == stick->getDeadZone() maxZoneSlider->value == stick->getMaxZone() maxZoneSpinBox->value == stick->getMaxZone() diagonalRangeSlider->value == stick->getDiagonalRange() diagonalRangeSpinBox->value == stick->getDiagonalRange() squareStickSlider->value == stick->getCircleAdjust() * 100 squareStickSpinBox->value == stick->getCircleAdjust() * 100 stickDelaySlider->value == stick->getStickDelay() * .1 stickDelayDoubleSpinBox->value == stick->getStickDelay() * .001 modifierPushButton->text == stick->getModifierButton()->getSlotsSummary() stickNameLineEdit->text == stick->getStickName() QString xCoorString = QString::number(stick->getXCoordinate()); if (stick->getCircleAdjust() > 0.0) { xCoorString.append(QString(" (%1)").arg(stick->getCircleXCoordinate())); } xCoordinateLabel->text == xCoorString QString yCoorString = QString::number(stick->getYCoordinate()); if (stick->getCircleAdjust() > 0.0) { yCoorString.append(QString(" (%1)").arg(stick->getCircleYCoordinate())); } yCoordinateLabel->text() == yCoorString distanceLabel->text() == QString::number(stick->getAbsoluteRawDistance()) diagonalLabel->text() == QString::number(stick->calculateBearing()) fromSafeZoneValueLabel->text() == QString::number(stick->getDistanceFromDeadZone() * 100.0) stickStatusBoxWidget->getStick() == stick stickStatusBoxWidget has to be visible mouseSettingsPushButton runs new window mouseSettingsPushButton is never disabled presetsComboBox is not disabled joyModeComboBox is not disabled deadZoneSlider is not disabled maxZoneSlider is not disabled diagonalRangeSlider is not disabled squareStickSlider is not disabled stickDelaySlider is not disabled stickNameLineEdit is not disabled deadZoneSlider->setValue(int) deadZoneSlider->value() == deadZoneSpinBox->value() stickStatusBoxWidget->getStick()->getDeadZone() maxZoneSlider->setValue(int) maxZoneSlider->value() == maxZoneSlider->value() stickStatusBoxWidget->getStick()->getMaxZone() diagonalRangeSlider->setValue(int) diagonalRangeSlider->value() == diagonalRangeSlider->value() stickStatusBoxWidget->getStick()->getDiagonalRange() squareStickSlider->setValue(int) squareStickSlider->value() == squareStickSpinBox->value() stickStatusBoxWidget->getStick()->getCircleAdjust() == squareStickSpinBox->value() / 100 stickDelaySlider->setValue(int) stickDelaySlider->value() == stickDelayDoubleSpinBox->value() stickStatusBoxWidget->getStick()->getStickDelay() == stickDelayDoubleSpinBox->value() / .001 window->title() == Set + stick->getStickName() */ class TestJoyControlStickEditDialog: public QObject { Q_OBJECT public: TestJoyControlStickEditDialog(QObject* parent = 0); private slots: private: JoyControlStickEditDialog axisEditDialog; }; TestJoyControlStickEditDialog::TestJoyControlStickEditDialog(QObject* parent) : QObject(parent), JoyControlStickEditDialog() { QTestEventLoop::instance().enterLoop(1); } // QTEST_MAIN(TestJoyControlStickEditDialog) #include "testjoycontrolstickeditdialog.moc" AntiMicroX-antimicrox-2888bf6/tests/testqkeydisplaydialog.cpp000066400000000000000000000054511377703515000245550ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "qkeydisplaydialog.h" #include /* label->text() cannot be empty buttonBox->Close cannot be disabled nativeTitleLabel->text() == tr("Native Key Value:") qtKeyTitleLabel->text() == tr("Qt Key Value:") antiTitleLabel->text() == tr("AntiMicroX Key Value:") label->text() is all visible label->text() contains
label->text() contains nativeKeyLabel->text() at the start is 0x00000000 or empty qtKeyLabel->text() at the start is 0x00000000 or empty antimicroKeyLabel->text() at the start is 0x00000000 or empty run keyReleaseEvent(QKeyEvent *event) for all keys, that are physically present: // qnamespace.h -> enum Key { contains all adresses of keys in Qt // keysymdef.h and XF86keysym.h contain adresses of keys in X11 // input-event-codes.h contains addresses of keys in uinput if int virtualkey = event->nativeVirtualKey() is != 0 if it's X11 if X11Extras::getInstance()->getGroup1KeySym(virtualkey) > 0 then check out if if it's uinput QtKeyMapperBase *nativeKeyMapper = AntKeyMapper::getInstance()->getNativeKeyMapper(); int tempalias = nativeKeyMapper->returnQtKey(virtualkey); if AntKeyMapper::getInstance()->returnVirtualKey(tempalias) > 0 then check out if ui->nativeKeyLabel->text() == QString("0x%1").arg(finalvirtual, 0, 16) ui->qtKeyLabel->text() == QString("0x%1").arg(event->key(), 0, 16) ui->antimicroKeyLabel->text() == QString("0x%1").arg(AntKeyMapper::getInstance()->returnQtKey(finalvirtual), 0, 16) */ class TestQKeyDisplayDialog: public QObject { Q_OBJECT public: TestQKeyDisplayDialog(QObject* parent = 0); private slots: private: QKeyDisplayDialog qkeydisplaydialog; }; TestQKeyDisplayDialog::TestQKeyDisplayDialog(QObject* parent) : QObject(parent), QKeyDisplayDialog() { QTestEventLoop::instance().enterLoop(1); } // QTEST_MAIN(TestQKeyDisplayDialog) #include "testqkeydisplaydialog.moc" AntiMicroX-antimicrox-2888bf6/tests/testquicksetdialog.cpp000066400000000000000000000100321377703515000240350ustar00rootroot00000000000000/* antimicrox Gamepad to KB+M event mapper * Copyright (C) 2015 Travis Nickles * Copyright (C) 2020 Jagoda Górska * Copyright (C) 2020 Paweł Kotiuk * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "quicksetdialog.h" #include /* buttonBox->Close cannot be disabled joystickDialogLabel->text() cannot be empty getJoystick() cannot be null pointer if joystickDialogLabel->text() == ui->joystickDialogLabel->text().arg(joystick->getSDLName()).arg(joystick->getName()) QListIterator sticksList = currentset->getSticks().values(); if sticksList.hasNext() then device has sticks (amount = currentset->getSticks().values().count()) QListIterator axesList = currentset->getAxes()->values();; if axesList.hasNext() then device has axes (amount = currentset->getAxes()->values().count()) QListIterator dpadsList = currentset->getHats().values(); if dpadsList.hasNext() then device has dpads (amount = currentset->getHats().values().count()) QListIterator vdpadsList = currentset->getVdpads().values(); if vdpadsList.hasNext() then device has vdpads (amount = currentset->getVdpads().values().count()) QListIterator btnsList = currentset->getButtons().values(); if btnsList.hasNext() then device has buttons (amount = currentset->getButtons().values().count()) emit pressed stick qobject_cast(getLastPressedButton()) != nullptr add thread to list emit pressed axis possibleAxisAction && qobject_cast(getLastPressedButton()) != nullptr add thread to list emit pressed dpad qobject_cast(getLastPressedButton()) != nullptr add thread to list emit pressed vdpad qobject_cast(getLastPressedButton()) != nullptr add thread to list emit pressed button qobject_cast(getLastPressedButton()) != nullptr add thread to list emit pressed any button getHelper() cannot be nullptr add thread to list all threads should be different run restoreJoystickState (below connections don't exist anymore): for each stickbutton connect(stickbutton, &JoyControlStickButton::clicked, this, [this, stickbutton]() { showStickButtonDialog(stickbutton); }); for each naxisbutton connect(naxisbutton, &JoyAxisButton::clicked, this, [this, naxisbutton]() { showAxisButtonDialog(naxisbutton); }); for each paxisbutton connect(paxisbutton, &JoyAxisButton::clicked, this, [this, paxisbutton]() { showAxisButtonDialog(paxisbutton); }); for each dpadbutton connect(dpadbutton, &JoyDPadButton::clicked, this, [this, dpadbutton] { showDPadButtonDialog(dpadbutton); }); for each vdpadbutton connect(dpadbutton, &JoyDPadButton::clicked, this, [this, dpadbutton] { showDPadButtonDialog(dpadbutton); }); for each button connect(button, &JoyButton::clicked, this, [this, button] { showButtonDialog(button); }); */ class TestQuickSetDialog: public QObject { Q_OBJECT public: TestQuickSetDialog(QObject* parent = 0); private slots: private: QuickSetDialog quicksetdialog; }; TestQuickSetDialog::TestQuickSetDialog(QObject* parent) : QObject(parent), QuickSetDialog() { QTestEventLoop::instance().enterLoop(1); } // QTEST_MAIN(TestQuickSetDialog) #include "testquicksetdialog.moc"