├── .github └── FUNDING.yml ├── .gitignore ├── FreeJoyQt.pro ├── InnoSetup-installerCreatorScript.iss ├── LICENSE ├── README.md └── src ├── .clang-format ├── FreeJoyQt_de_DE.qm ├── FreeJoyQt_de_DE.ts ├── FreeJoyQt_ru.qm ├── FreeJoyQt_ru.ts ├── FreeJoyQt_zh_CN.qm ├── FreeJoyQt_zh_CN.ts ├── Images ├── BluePill_render.jpg ├── ST_wiki.png ├── ST_wiki_dark.png ├── flags │ ├── Germany.png │ ├── Russia.png │ ├── United_Kingdom.png │ └── china.png ├── folder.png ├── icon-16.png ├── icon-32.png ├── icon-big.rar ├── icon-old.rar ├── icon-trans.rar ├── icon.ico ├── icon.png ├── info_icon.png ├── main-white.png ├── main.png ├── moon.png ├── pinout.png ├── reset.png ├── setings.png ├── sun.png └── warning.png ├── POWqvw.json ├── common_defines.h ├── common_types.h ├── configtofile.cpp ├── configtofile.h ├── converter.cpp ├── converter.h ├── deviceconfig.cpp ├── deviceconfig.h ├── firmwareupdater.cpp ├── firmwareupdater.h ├── global.h ├── hidapi.h ├── hiddevice.cpp ├── hiddevice.h ├── linux ├── 99-hid-FreeJoy.rules ├── hidapi.c ├── linux build.txt └── readme.txt ├── mac └── hidapi.c ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── mainwindow_style.cpp ├── mousewheelguard.cpp ├── mousewheelguard.h ├── reportconverter.cpp ├── reportconverter.h ├── resources.qrc ├── src.pro ├── stm_main.c ├── stm_main.h ├── styles └── default.qss ├── version.h ├── widgets ├── adv-settings │ ├── advancedsettings.cpp │ ├── advancedsettings.h │ ├── advancedsettings.ui │ ├── flasher.cpp │ ├── flasher.h │ └── flasher.ui ├── axes-curves │ ├── axescurves.cpp │ ├── axescurves.h │ ├── axescurves.ui │ ├── axescurvesbutton.cpp │ ├── axescurvesbutton.h │ ├── axescurvesconfig.cpp │ ├── axescurvesconfig.h │ ├── axescurvesconfig.ui │ ├── axescurvesplot.cpp │ ├── axescurvesplot.h │ ├── axescurvesprofiles.cpp │ ├── axescurvesprofiles.h │ └── axescurvesprofiles.ui ├── axes │ ├── axes.cpp │ ├── axes.h │ ├── axes.ui │ ├── axesconfig.cpp │ ├── axesconfig.h │ ├── axesconfig.ui │ ├── axesextended.cpp │ ├── axesextended.h │ ├── axesextended.ui │ ├── axestobuttonsconfig.cpp │ ├── axestobuttonsslider.cpp │ ├── axestobuttonsslider.h │ └── axestobuttonsslider.ui ├── buttons │ ├── buttonconfig.cpp │ ├── buttonconfig.h │ ├── buttonconfig.ui │ ├── buttonlogical.cpp │ ├── buttonlogical.h │ ├── buttonlogical.ui │ ├── buttonphysical.cpp │ ├── buttonphysical.h │ └── buttonphysical.ui ├── centered_cbox.cpp ├── centered_cbox.h ├── debugwindow.cpp ├── debugwindow.h ├── debugwindow.ui ├── encoders │ ├── encoders.cpp │ ├── encoders.h │ ├── encoders.ui │ ├── encodersconfig.cpp │ ├── encodersconfig.h │ └── encodersconfig.ui ├── infolabel.cpp ├── infolabel.h ├── led │ ├── led.cpp │ ├── led.h │ ├── led.ui │ ├── ledconfig.cpp │ ├── ledconfig.h │ └── ledconfig.ui ├── pins │ ├── currentconfig.cpp │ ├── currentconfig.h │ ├── currentconfig.ui │ ├── pincombobox.cpp │ ├── pincombobox.h │ ├── pincombobox.ui │ ├── pinconfig.cpp │ ├── pinconfig.h │ ├── pinconfig.ui │ ├── pinsbluepill.cpp │ ├── pinsbluepill.h │ ├── pinsbluepill.ui │ ├── pinscontrlite.cpp │ ├── pinscontrlite.h │ └── pinscontrlite.ui ├── selectfolder.cpp ├── selectfolder.h ├── selectfolder.ui ├── shift-reg │ ├── shiftregisters.cpp │ ├── shiftregisters.h │ ├── shiftregisters.ui │ ├── shiftregistersconfig.cpp │ ├── shiftregistersconfig.h │ └── shiftregistersconfig.ui ├── switchbutton.cpp └── switchbutton.h ├── winapp.rc └── windows └── hidapi.c /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: freejoy 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.user 3 | *.pro.user 4 | *.pro.user.* 5 | FreeJoyQt.pro.user 6 | .vscode 7 | -------------------------------------------------------------------------------- /FreeJoyQt.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | CONFIG+=ordered 4 | 5 | SUBDIRS = \ 6 | src 7 | -------------------------------------------------------------------------------- /InnoSetup-installerCreatorScript.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | #define INNO_SETUP 5 | #include "F:\sources\Qt\FreeJoyConfiguratorQt\src\version.h" 6 | #define MyAppName "FreeJoy Configurator" 7 | #define MyAppVersion APP_VERSION 8 | #define MyAppPublisher "FreeJoy" 9 | #define MyAppURL "" 10 | #define MyAppExeName "FreeJoyQt.exe" 11 | 12 | 13 | [Setup] 14 | ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. 15 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 16 | AppId={{DE67475C-2799-4D59-8A23-27F028E18C42} 17 | AppName={#MyAppName} 18 | AppVersion={#MyAppVersion} 19 | ;AppVerName={#MyAppName} {#MyAppVersion} 20 | AppPublisher={#MyAppPublisher} 21 | AppPublisherURL={#MyAppURL} 22 | AppSupportURL={#MyAppURL} 23 | AppUpdatesURL={#MyAppURL} 24 | DefaultDirName={autopf}\{#MyAppName} 25 | DisableProgramGroupPage=yes 26 | ; Uncomment the following line to run in non administrative install mode (install for current user only.) 27 | PrivilegesRequired=lowest 28 | ;PrivilegesRequiredOverridesAllowed=dialog 29 | OutputBaseFilename=FreeJoy Installer 30 | SetupIconFile=F:\sources\Qt\FreeJoyConfiguratorQt\src\Images\icon.ico 31 | Compression=lzma 32 | SolidCompression=yes 33 | WizardStyle=modern 34 | 35 | [Languages] 36 | Name: "english"; MessagesFile: "compiler:Default.isl" 37 | 38 | [Tasks] 39 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; 40 | 41 | [Dirs] 42 | Name: "{app}\configs" 43 | 44 | [Files] 45 | Source: "C:\Users\123\Desktop\FreeJoyQt-v1.7.1b0-Windows\1111\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 46 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 47 | 48 | 49 | [Icons] 50 | Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 51 | Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon 52 | 53 | [Run] 54 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent 55 | 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FreeJoy Configurator 2 | 3 | FreeJoy Configurator is a visual utility allowing you to setup your [FreeJoy](https://github.com/vostrenkov/FreeJoy) device for your own requirements. 4 | 5 | ![](https://github.com/FreeJoy-Team/FreeJoyConfiguratorQt/blob/master/src/Images/main.png) 6 | 7 | ## Features 8 | 9 | * Pin mapping configuration 10 | * Digital inputs configuration (buttons, toggle switches, encoders, etc.) 11 | * Analog input configuration (calibration, smoothing, curve shapes, etc.) 12 | * Axes to buttons configuration 13 | * Shift registers configuration 14 | * Saving and loading configuration to file 15 | * Flashing device firmware 16 | 17 | Check [our wiki](https://github.com/FreeJoy-Team/FreeJoyWiki) for detailed instructions. 18 | 19 | ## Downloads 20 | - [Windows](https://github.com/FreeJoy-Team/FreeJoyConfiguratorQt/releases) 21 | - [AppImage](https://github.com/FreeJoy-Team/FreeJoyConfiguratorQt/releases) 22 | 23 | ## Installation 24 | 25 | ### Windows 26 | 1. Download, unpack, run 27 | 28 | ### Linux 29 | 1. Downloand and unpack .tar.xz 30 | 2. Edit 99-hid-FreeJoy.rules or leave it as it is 31 | 3. Copy "99-hid-FreeJoy.rules" to /etc/udev/rules.d 32 | * `sudo cp 99-hid-FreeJoy.rules /etc/udev/rules.d` 33 | 4. Run AppImage or build from source 34 | 35 | ## Building 36 | 37 | ### Windows Build Requirements 38 | * Qt 5.15 SDK or later 39 | * Windows 7 or later 40 | * [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) (Community edition is fine) or MinGW 41 | * Select **MSVC 2019** or **MinGW** option during Qt installation. 42 | 43 | ### Linux/Unix Build Requirements 44 | * Qt 5.11 SDK or later 45 | * GCC or Clang 46 | * Install the required packages: 47 | * `qt5-default libxcb-xinerama0 libudev-dev libusb-1.0-0-dev libfox-1.6-dev` 48 | 49 | ### Build Setup Steps 50 | 1. Install the latest Qt SDK (and optionally, the Qt Creator IDE) from https://www.qt.io/download 51 | * You may also use your Linux distro's package manager for the Qt SDK as long as the packages are Qt 5.11 or later. 52 | 2. Open the project in Qt Creator or build from qmake on the command line. 53 | * Run `qmake FreeJoyQt.pro` then `make` 54 | -------------------------------------------------------------------------------- /src/.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | AccessModifierOffset: -4 3 | AlignAfterOpenBracket: Align 4 | AlignConsecutiveAssignments: false 5 | AlignConsecutiveDeclarations: false 6 | AlignEscapedNewlines: DontAlign 7 | AlignOperands: true 8 | AlignTrailingComments: true 9 | AllowAllParametersOfDeclarationOnNextLine: true 10 | AllowShortBlocksOnASingleLine: false 11 | AllowShortCaseLabelsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: Inline 13 | AllowShortIfStatementsOnASingleLine: false 14 | AllowShortLoopsOnASingleLine: false 15 | AlwaysBreakAfterReturnType: None 16 | AlwaysBreakBeforeMultilineStrings: false 17 | AlwaysBreakTemplateDeclarations: true 18 | BinPackArguments: false 19 | BinPackParameters: false 20 | BraceWrapping: 21 | AfterClass: true 22 | AfterControlStatement: false 23 | AfterEnum: false 24 | AfterFunction: true 25 | AfterNamespace: false 26 | AfterObjCDeclaration: false 27 | AfterStruct: true 28 | AfterUnion: false 29 | BeforeCatch: false 30 | BeforeElse: false 31 | IndentBraces: false 32 | SplitEmptyFunction: false 33 | SplitEmptyRecord: false 34 | SplitEmptyNamespace: false 35 | BreakBeforeBinaryOperators: All 36 | BreakBeforeBraces: Custom 37 | BreakBeforeInheritanceComma: false 38 | BreakBeforeTernaryOperators: true 39 | BreakConstructorInitializersBeforeComma: false 40 | BreakConstructorInitializers: BeforeComma 41 | BreakAfterJavaFieldAnnotations: false 42 | BreakStringLiterals: true 43 | ColumnLimit: 120 44 | CommentPragmas: '^ IWYU pragma:' 45 | CompactNamespaces: false 46 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 47 | ConstructorInitializerIndentWidth: 4 48 | ContinuationIndentWidth: 4 49 | Cpp11BracedListStyle: true 50 | DerivePointerAlignment: false 51 | DisableFormat: false 52 | ExperimentalAutoDetectBinPacking: false 53 | FixNamespaceComments: true 54 | ForEachMacros: 55 | - forever # avoids { wrapped to next line 56 | - foreach 57 | - Q_FOREACH 58 | - BOOST_FOREACH 59 | IncludeCategories: 60 | - Regex: '^ 5 | 6 | class QSettings; 7 | #include "common_types.h" 8 | 9 | class ConfigToFile : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | // explicit ConfigToFile(QObject *parent = nullptr); 14 | 15 | static void loadDeviceConfigFromFile(QWidget *parent, const QString &fileName, dev_config_t &devC); 16 | static void saveDeviceConfigToFile(const QString &fileName, dev_config_t &devC); 17 | //signals: 18 | 19 | private: 20 | static void oldConfigHandler(QWidget *parent, dev_config_t &devC); 21 | 22 | }; 23 | 24 | #endif // CONFIGTOFILE_H 25 | -------------------------------------------------------------------------------- /src/converter.cpp: -------------------------------------------------------------------------------- 1 | #include "converter.h" 2 | #include 3 | 4 | Converter::Converter() {} 5 | 6 | //! Returns the index of the item containing the deviceEnum ; otherwise returns -1 7 | int Converter::EnumToIndex(const int deviceEnum, const QVector &list) 8 | { 9 | for (int i = 0; i < list.size(); ++i) { 10 | if (deviceEnum == list[i].deviceEnumIndex) { 11 | return i; 12 | } 13 | } 14 | qCritical() << "Converter::EnumToIndex returns -1"; 15 | return -1; 16 | } 17 | 18 | //! Returns the index of the item containing the deviceEnum ; otherwise returns -1 19 | int Converter::EnumToIndex(const int deviceEnum, const QVector &list) 20 | { 21 | for (int i = 0; i < list.size(); ++i) { 22 | if (deviceEnum == list[i]) { 23 | return i; 24 | } 25 | } 26 | qCritical() << "Converter::FindIndex returns -1"; 27 | return -1; 28 | } 29 | -------------------------------------------------------------------------------- /src/converter.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIGUICONVERTER_H 2 | #define CONFIGUICONVERTER_H 3 | 4 | #include "deviceconfig.h" 5 | #include "global.h" 6 | 7 | class Converter 8 | { 9 | public: 10 | Converter(); 11 | 12 | static int EnumToIndex(const int deviceEmun, const QVector &list); 13 | static int EnumToIndex(const int deviceEnum, const QVector &list); 14 | }; 15 | 16 | #endif // CONFIGUICONVERTER_H 17 | -------------------------------------------------------------------------------- /src/deviceconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "deviceconfig.h" 2 | 3 | extern "C" { 4 | #include "stm_main.h" 5 | } 6 | 7 | DeviceConfig::DeviceConfig() 8 | { 9 | config = InitConfig(); 10 | //joyReport = {}; 11 | paramsReport = {}; 12 | } 13 | 14 | void DeviceConfig::resetConfig() 15 | { 16 | config = InitConfig(); 17 | } 18 | -------------------------------------------------------------------------------- /src/deviceconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICECONFIG_H 2 | #define DEVICECONFIG_H 3 | 4 | #include "common_defines.h" 5 | #include "common_types.h" 6 | 7 | class DeviceConfig 8 | { 9 | public: 10 | DeviceConfig(); 11 | 12 | void resetConfig(); 13 | 14 | dev_config_t config; 15 | //joy_report_t joyReport; 16 | params_report_t paramsReport; 17 | }; 18 | 19 | #endif // DEVICECONFIG_H 20 | -------------------------------------------------------------------------------- /src/firmwareupdater.cpp: -------------------------------------------------------------------------------- 1 | #include "firmwareupdater.h" 2 | 3 | #include 4 | FirmwareUpdater::FirmwareUpdater() {} 5 | // хз зачем мне статик постоянно висящий в памяти 6 | uint16_t FirmwareUpdater::table[256]{}; 7 | unsigned short FirmwareUpdater::computeChecksum(const QByteArray *fileBytes) 8 | { 9 | // generate crc 10 | uint16_t value; 11 | uint16_t temp; 12 | for (uint16_t i = 0; i < sizeof(table) / sizeof(uint16_t); ++i) { 13 | value = 0; 14 | temp = i; 15 | for (uint8_t j = 0; j < 8; ++j) { 16 | if (((value ^ temp) & 0x0001) != 0) { 17 | value = (uint16_t)((value >> 1) ^ polynomial); 18 | } else { 19 | value >>= 1; 20 | } 21 | temp >>= 1; 22 | } 23 | table[i] = value; 24 | } 25 | 26 | // generate checksum 27 | uint16_t crc = 0; 28 | for (int i = 0; i < fileBytes->size(); ++i) { 29 | uint8_t index = (uint8_t)(crc ^ fileBytes->at(i)); 30 | crc = (uint16_t)((crc >> 8) ^ table[index]); 31 | } 32 | return crc; 33 | } 34 | -------------------------------------------------------------------------------- /src/firmwareupdater.h: -------------------------------------------------------------------------------- 1 | #ifndef FIRMWAREUPDATER_H 2 | #define FIRMWAREUPDATER_H 3 | 4 | #include 5 | 6 | class FirmwareUpdater 7 | { 8 | public: 9 | FirmwareUpdater(); 10 | 11 | static uint16_t computeChecksum(const QByteArray *fileBytes); 12 | 13 | private: 14 | static const uint16_t polynomial = 0xA001; 15 | static uint16_t table[256]; 16 | }; 17 | 18 | #endif // FIRMWAREUPDATER_H 19 | -------------------------------------------------------------------------------- /src/global.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_H 2 | #define GLOBAL_H 3 | 4 | #include //? 5 | #include 6 | 7 | class DeviceConfig; 8 | class QSettings; 9 | class DebugWindow; 10 | class QTranslator; 11 | //class QElapsedTimer; //? 12 | //! CryEngine style global environment 13 | //! Global environment. Contains pointers to all global often needed interfaces. 14 | //! This is a faster way to get interface pointer then calling ISystem interface to retrieve one. 15 | struct GlobalEnvironment 16 | { 17 | QElapsedTimer *pApp_start_time = nullptr; 18 | DeviceConfig *pDeviceConfig = nullptr; 19 | QSettings *pAppSettings = nullptr; 20 | DebugWindow *pDebugWindow = nullptr; 21 | QTranslator *pTranslator = nullptr; 22 | 23 | #ifdef QT_DEBUG 24 | bool readFinished = false; 25 | #endif 26 | }; 27 | extern GlobalEnvironment gEnv; 28 | 29 | // flasher 30 | enum { 31 | FINISHED = 0, 32 | SIZE_ERROR, 33 | CRC_ERROR, 34 | ERASE_ERROR, 35 | 36 | IN_PROCESS = 99, 37 | }; 38 | 39 | struct deviceEnum_guiName_t 40 | { 41 | int deviceEnumIndex; 42 | QString guiName; 43 | }; 44 | 45 | //! Remove pointer indirection. 46 | // ILINE SSystemGlobalEnvironment* operator->() 47 | // { 48 | // return this; 49 | // } 50 | // ILINE SSystemGlobalEnvironment& operator*() 51 | // { 52 | // return *this; 53 | // } 54 | // ILINE const bool operator!() const 55 | // { 56 | // return false; 57 | // } 58 | // ILINE operator bool() const 59 | // { 60 | // return true; 61 | // } 62 | 63 | 64 | #endif // GLOBAL_H 65 | //#if defined(SYS_ENV_AS_STRUCT) 66 | -------------------------------------------------------------------------------- /src/hiddevice.h: -------------------------------------------------------------------------------- 1 | #ifndef HIDDEVICE_H 2 | #define HIDDEVICE_H 3 | 4 | #include 5 | #include 6 | #include "hidapi.h" 7 | 8 | class HidDevice : public QObject 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | void getConfigFromDevice(); 14 | void sendConfigToDevice(); 15 | 16 | bool enterToFlashMode(); 17 | void flashFirmware(const QByteArray *firmware); 18 | 19 | void setIsFinish(bool isFinish); 20 | void setSelectedDevice(int deviceNumber); 21 | 22 | public slots: 23 | void processData(); 24 | 25 | signals: 26 | void deviceDisconnected(); 27 | void deviceConnected(); 28 | void flasherConnected(); 29 | void paramsPacketReceived(bool firmwareCompatible); 30 | 31 | void configReceived(bool isSuccess); 32 | void configSent(bool isSuccess); 33 | 34 | void hidDeviceList(const QList> &deviceNames); 35 | 36 | void flasherFound(bool isFound); 37 | void flashStatus(int status, int percent); 38 | 39 | private: 40 | struct Device 41 | { 42 | ushort vid; 43 | ushort pid; 44 | std::wstring serNum; 45 | std::string path; 46 | 47 | Device (const hid_device_info *hid) { 48 | this->vid = hid->vendor_id; 49 | this->pid = hid->product_id; 50 | this->serNum = hid->serial_number; 51 | this->path = hid->path; 52 | } 53 | 54 | void operator = (const hid_device_info *hid) { 55 | this->vid = hid->vendor_id; 56 | this->pid = hid->product_id; 57 | this->serNum = hid->serial_number; 58 | this->path = hid->path; 59 | } 60 | }; 61 | QList m_hidDevicesList; // should be thread safe 62 | 63 | hid_device *m_paramsRead; 64 | hid_device *m_joyRead; 65 | 66 | int m_selectedDevice = -1; 67 | int m_currentWork; 68 | bool m_oldFirmwareSelected; 69 | bool m_isFinish = false; 70 | 71 | void readConfigFromDevice(uint8_t *buffer); 72 | void writeConfigToDevice(uint8_t *buffer); 73 | void flashFirmwareToDevice(); 74 | 75 | QList> m_deviceNames; 76 | QByteArray m_flasherPath; 77 | const QByteArray *m_firmware; 78 | 79 | mutable std::mutex m_mutex; 80 | }; 81 | 82 | #endif // HIDDEVICE_H 83 | -------------------------------------------------------------------------------- /src/linux/99-hid-FreeJoy.rules: -------------------------------------------------------------------------------- 1 | # Use something like the following line, substituting the VID and PID with 2 | # those of your device. ATTRS{busnum}=="001" is USB - if none = all USB bus 3 | # ATTRS{idProduct}=="5757" - if none = all PID 4 | 5 | # HIDAPI/hidraw 6 | KERNEL=="hidraw*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5757", MODE="0666" 7 | 8 | # Once done, optionally rename this file for your device, and drop it into 9 | # /etc/udev/rules.d and unplug and re-plug your device. This is all that is 10 | # necessary to see the new permissions. Udev does not have to be restarted. 11 | 12 | # Note that the hexadecimal values for VID and PID are case sensitive and 13 | # must be lower case. 14 | 15 | # If you think permissions of 0666 are too loose, then see: 16 | # http://reactivated.net/writing_udev_rules.html for more information on finer 17 | # grained permission setting. For example, it might be sufficient to just 18 | # set the group or user owner for specific devices (for example the plugdev 19 | # group on some systems). 20 | -------------------------------------------------------------------------------- /src/linux/linux build.txt: -------------------------------------------------------------------------------- 1 | //////// Install //////// ????? 2 | 3 | sudo apt-get install qt5-default 4 | sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev 5 | sudo apt-get install libxcb-xinerama0 6 | qmake 7 | make 8 | 9 | //////// Copy //////// 10 | sudo cp 99-hid-FreeJoy.rules /etc/udev/rules.d 11 | 12 | 13 | echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="dbdb", TAG+="udev-acl", TAG+="uaccess"' | sudo tee -a /etc/udev/rules.d/70-boot2qt.rules 14 | -------------------------------------------------------------------------------- /src/linux/readme.txt: -------------------------------------------------------------------------------- 1 | //////// Copy //////// 2 | // copy "99-hid-FreeJoy.rules" to /etc/udev/rules.d 3 | // edit if you will change PID, DO NOT USE PID 5750 4 | 5 | sudo cp 99-hid-FreeJoy.rules /etc/udev/rules.d 6 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "infolabel.h" 13 | 14 | // global environment 15 | #include "global.h" 16 | GlobalEnvironment gEnv; 17 | #include "deviceconfig.h" 18 | 19 | // Get the default Qt message handler. 20 | static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(nullptr); 21 | 22 | // define QT_NO_DEBUG_OUTPUT - no debug info 23 | void CustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) 24 | { 25 | // mutex? 26 | if (gEnv.pDebugWindow != nullptr) { 27 | // для мультипотока, хз правильно ли, но работает // не уверен насчёт ссылки, мб надо копию передавать с мультипотоком 28 | QMetaObject::invokeMethod(gEnv.pDebugWindow, "printMsg", Qt::QueuedConnection, Q_ARG(QString, msg)); 29 | } 30 | 31 | // Call the default handler. 32 | (*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg); 33 | } 34 | 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 39 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 40 | QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); 41 | #endif 42 | //qputenv("QT_SCALE_FACTOR", "0.8"); 43 | qRegisterMetaType> >(); 44 | 45 | QElapsedTimer time; 46 | time.start(); 47 | 48 | QApplication::setStyle(QStyleFactory::create("Fusion")); 49 | QApplication::setStyle(new InfoProxyStyle(qApp->style())); 50 | QApplication a(argc, argv); 51 | 52 | QString docLoc = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); 53 | if (docLoc.isEmpty() == false) { 54 | docLoc+= "/FreeJoy/"; 55 | } 56 | 57 | QDir dir(docLoc); 58 | if (dir.exists() == false) { 59 | dir.mkpath("."); 60 | dir.mkpath("configs"); 61 | } 62 | 63 | QSettings appSettings(docLoc + "FreeJoySettings.conf", QSettings::IniFormat); 64 | 65 | DeviceConfig deviceConfig; 66 | QTranslator translator; 67 | 68 | // global 69 | gEnv.pAppSettings = &appSettings; 70 | gEnv.pDeviceConfig = &deviceConfig; 71 | gEnv.pTranslator = &translator; 72 | 73 | qInstallMessageHandler(CustomMessageHandler); 74 | 75 | gEnv.pApp_start_time = &time; 76 | 77 | // set font size 78 | gEnv.pAppSettings->beginGroup("FontSettings"); 79 | QFont defaultFont = QApplication::font(); 80 | defaultFont.setPointSize(gEnv.pAppSettings->value("FontSize", "8").toInt()); 81 | qApp->setFont(defaultFont); 82 | gEnv.pAppSettings->endGroup(); 83 | 84 | // load language settings 85 | appSettings.beginGroup("LanguageSettings"); 86 | bool ok = false; 87 | if (appSettings.value("Language", "english").toString() == "russian") 88 | { 89 | ok = gEnv.pTranslator->load(":/FreeJoyQt_ru"); 90 | if (ok == false) { 91 | qCritical()<<"failed to load translate file"; 92 | } else { 93 | qApp->installTranslator(gEnv.pTranslator); 94 | } 95 | } 96 | else if (appSettings.value("Language", "english").toString() == "schinese") 97 | { 98 | ok = gEnv.pTranslator->load(":/FreeJoyQt_zh_CN"); 99 | if (ok == false) { 100 | qCritical()<<"failed to load translate file"; 101 | } else { 102 | qApp->installTranslator(gEnv.pTranslator); 103 | } 104 | } 105 | else if (appSettings.value("Language", "english").toString() == "deutsch") 106 | { 107 | ok = gEnv.pTranslator->load(":/FreeJoyQt_de_DE"); 108 | if (ok == false) { 109 | qCritical()<<"failed to load translate file"; 110 | } else { 111 | qApp->installTranslator(gEnv.pTranslator); 112 | } 113 | } 114 | appSettings.endGroup(); 115 | 116 | MainWindow w; 117 | 118 | qDebug() << "Application startup time =" << gEnv.pApp_start_time->elapsed() << "ms"; 119 | w.show(); 120 | 121 | return a.exec(); 122 | } 123 | -------------------------------------------------------------------------------- /src/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "hiddevice.h" 9 | #include "reportconverter.h" 10 | 11 | #include "advancedsettings.h" 12 | #include "axesconfig.h" 13 | #include "axescurvesconfig.h" 14 | #include "buttonconfig.h" 15 | #include "debugwindow.h" 16 | #include "encodersconfig.h" 17 | #include "ledconfig.h" 18 | #include "pinconfig.h" 19 | #include "shiftregistersconfig.h" 20 | #include "switchbutton.h" 21 | 22 | QT_BEGIN_NAMESPACE 23 | namespace Ui { 24 | class MainWindow; 25 | } 26 | QT_END_NAMESPACE 27 | 28 | class MainWindow : public QMainWindow 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | MainWindow(QWidget *parent = nullptr); 34 | ~MainWindow(); 35 | void setDefaultStyleSheet(); 36 | 37 | signals: 38 | void getConfigDone(bool success); 39 | void sendConfigDone(bool success); 40 | 41 | private slots: 42 | void showConnectDeviceInfo(); 43 | void hideConnectDeviceInfo(); 44 | void flasherConnected(); 45 | //void getParamsPacket(uint8_t *buffer); 46 | void getParamsPacket(bool firmwareCompatible); 47 | 48 | void configReceived(bool success); 49 | void configSent(bool success); 50 | void blockWRConfigToDevice(bool block); 51 | 52 | void deviceFlasherController(bool isStartFlash); 53 | 54 | void hidDeviceList(const QList> &deviceNames); 55 | void hidDeviceListChanged(int index); 56 | 57 | void languageChanged(const QString &language); 58 | void setFont(); 59 | 60 | void finalInitialization(); 61 | 62 | void on_pushButton_ResetAllPins_clicked(); 63 | 64 | void on_pushButton_ReadConfig_clicked(); 65 | void on_pushButton_WriteConfig_clicked(); 66 | 67 | void on_pushButton_SaveToFile_clicked(); 68 | void on_pushButton_LoadFromFile_clicked(); 69 | 70 | void on_pushButton_ShowDebug_clicked(); 71 | 72 | void on_pushButton_TestButton_clicked(); 73 | void on_pushButton_TestButton_2_clicked(); 74 | 75 | void on_pushButton_Wiki_clicked(); 76 | 77 | void themeChanged(bool dark); 78 | 79 | void on_toolButton_ConfigsDir_clicked(); 80 | 81 | protected: 82 | void keyPressEvent(QKeyEvent *event) override; 83 | void keyReleaseEvent(QKeyEvent *event) override; 84 | 85 | private: 86 | Ui::MainWindow *ui; 87 | 88 | QThread *m_thread; 89 | HidDevice *m_hidDeviceWorker; 90 | 91 | QThread *m_threadGetSendConfig; 92 | 93 | PinConfig *m_pinConfig; 94 | ButtonConfig *m_buttonConfig; 95 | LedConfig *m_ledConfig; 96 | EncodersConfig *m_encoderConfig; 97 | ShiftRegistersConfig *m_shiftRegConfig; 98 | AxesConfig *m_axesConfig; 99 | AxesCurvesConfig *m_axesCurvesConfig; 100 | AdvancedSettings *m_advSettings; 101 | 102 | DebugWindow *m_debugWindow = nullptr; 103 | bool m_debugIsEnable; 104 | 105 | bool m_deviceChanged; 106 | 107 | QString m_buttonDefaultStyle; // ????????? 108 | 109 | QString m_cfgDirPath; 110 | void curCfgFileChanged(const QString &fileName); 111 | QStringList cfgFilesList(const QString &dirPath); 112 | QIcon pixmapToIcon(QPixmap pixmap, const QColor &color); 113 | void updateColor(); 114 | 115 | void UiReadFromConfig(); 116 | void UiWriteToConfig(); 117 | 118 | void loadAppConfig(); 119 | void saveAppConfig(); 120 | }; 121 | #endif // MAINWINDOW_H 122 | -------------------------------------------------------------------------------- /src/mousewheelguard.cpp: -------------------------------------------------------------------------------- 1 | #include "mousewheelguard.h" 2 | 3 | #include 4 | #include 5 | 6 | MouseWheelGuard::MouseWheelGuard(QObject *parent) 7 | : QObject(parent) 8 | {} 9 | 10 | // protection against the mouse wheel if the widget is not setFocusPolicy(Qt::WheelFocus) 11 | // без протекта можно при прокручивании страницы случайно навести на комбобокс и изменить его колесом мыши 12 | // при установке setFocusPolicy(Qt::StrongFocus) и протекта на комбобокс придётся нажать, для прокручивания колесом 13 | bool MouseWheelGuard::eventFilter(QObject *o, QEvent *e) 14 | { 15 | const QWidget *widget = static_cast(o); 16 | if (e->type() == QEvent::Wheel && widget && !widget->hasFocus()) { 17 | e->ignore(); 18 | return true; 19 | } 20 | 21 | return QObject::eventFilter(o, e); 22 | } 23 | -------------------------------------------------------------------------------- /src/mousewheelguard.h: -------------------------------------------------------------------------------- 1 | #ifndef MOUSEWHEELGUARD_H 2 | #define MOUSEWHEELGUARD_H 3 | 4 | #include 5 | 6 | //class FilterObject:public QObject{ 7 | //public: 8 | // QWidget *target = nullptr;//it holds a pointer to target object 9 | // int goalHeight=0; 10 | // FilterObject(QObject *parent=nullptr):QObject(parent){}//uses QObject constructor 11 | // bool eventFilter(QObject *watched, QEvent *event) override;//and overrides eventFilter function 12 | //}; 13 | 14 | class MouseWheelGuard : public QObject 15 | { 16 | public: 17 | explicit MouseWheelGuard(QObject *parent); 18 | 19 | protected: 20 | bool eventFilter(QObject *o, QEvent *e) override; 21 | }; 22 | 23 | #endif // MOUSEWHEELGUARD_H 24 | -------------------------------------------------------------------------------- /src/reportconverter.cpp: -------------------------------------------------------------------------------- 1 | #include "reportconverter.h" 2 | 3 | #include "deviceconfig.h" 4 | #include "global.h" 5 | 6 | namespace ReportConverter 7 | { 8 | int8_t firmwareCompatible = -1; 9 | // namespace 10 | // { 11 | // int8_t firmwareCompatible = -1; 12 | // } 13 | } 14 | 15 | int ReportConverter::paramReport(uint8_t *paramsBuf) 16 | { 17 | if (paramsBuf != nullptr) { 18 | if (paramsBuf[1] == 0) { 19 | if ((*(uint16_t *)(paramsBuf + 2) & 0xFFF0) == (FIRMWARE_VERSION & 0xFFF0)) { 20 | firmwareCompatible = 1; 21 | memcpy((uint8_t *)&(gEnv.pDeviceConfig->paramsReport), paramsBuf + 2, 62); // paramsBuf +2 skip report ids 22 | return 1; 23 | } else { 24 | firmwareCompatible = 0; 25 | } 26 | } else if (firmwareCompatible == 1) { 27 | memcpy((uint8_t *)&(gEnv.pDeviceConfig->paramsReport) + 62, paramsBuf + 2, sizeof(params_report_t) - 62); 28 | return 1; 29 | } else if (firmwareCompatible == -1) { 30 | return -1; 31 | } 32 | } 33 | return 0; 34 | } 35 | 36 | void ReportConverter::resetReport() 37 | { 38 | firmwareCompatible = -1; 39 | memset(&gEnv.pDeviceConfig->paramsReport, 0, sizeof(params_report_t)); 40 | } 41 | 42 | void ReportConverter::getConfigFromDevice(uint8_t *hidBuf) 43 | { 44 | uint8_t cfg_count = sizeof(dev_config_t) / 62; 45 | uint8_t last_cfg_size = sizeof(dev_config_t) % 62; 46 | if (last_cfg_size > 0) { 47 | cfg_count++; 48 | } 49 | 50 | if (hidBuf[1] == cfg_count && last_cfg_size > 0) { 51 | memcpy((uint8_t *)&(gEnv.pDeviceConfig->config) + 62*(hidBuf[1] - 1), hidBuf + 2, last_cfg_size); 52 | } else { 53 | memcpy((uint8_t *)&(gEnv.pDeviceConfig->config) + 62*(hidBuf[1] - 1), hidBuf + 2, 62); 54 | } 55 | } 56 | 57 | void ReportConverter::sendConfigToDevice(uint8_t *hidBuf, uint8_t requestConfigNumber) 58 | { 59 | uint8_t cfg_count = sizeof(dev_config_t) / 62; 60 | uint8_t last_cfg_size = sizeof(dev_config_t) % 62; 61 | if (last_cfg_size > 0) { 62 | cfg_count++; 63 | } 64 | 65 | hidBuf[0] = REPORT_ID_CONFIG_OUT; 66 | hidBuf[1] = requestConfigNumber; 67 | 68 | if (requestConfigNumber == cfg_count && last_cfg_size > 0) { 69 | memcpy(&hidBuf[2], (uint8_t *)&(gEnv.pDeviceConfig->config) + 62*(requestConfigNumber - 1), last_cfg_size); 70 | } else { 71 | memcpy(&hidBuf[2], (uint8_t *)&(gEnv.pDeviceConfig->config) + 62*(requestConfigNumber - 1), 62); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/reportconverter.h: -------------------------------------------------------------------------------- 1 | #ifndef REPORTCONVERTER_H 2 | #define REPORTCONVERTER_H 3 | 4 | #include "stdint.h" 5 | 6 | #define BUFFERSIZE 64 7 | 8 | namespace ReportConverter 9 | { 10 | int paramReport(uint8_t *paramsBuffer); 11 | void resetReport(); 12 | 13 | void getConfigFromDevice(uint8_t *hidBuffer); 14 | void sendConfigToDevice(uint8_t *hidBuf, uint8_t requestConfigNumber); 15 | } 16 | 17 | #endif // REPORTCONVERTER_H 18 | -------------------------------------------------------------------------------- /src/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | FreeJoyQt_ru.qm 4 | FreeJoyQt_zh_CN.qm 5 | Images/BluePill_render.jpg 6 | Images/icon.png 7 | Images/icon-32.png 8 | styles/default.qss 9 | Images/pinout.png 10 | Images/ST_wiki.png 11 | Images/ST_wiki_dark.png 12 | Images/moon.png 13 | Images/sun.png 14 | Images/warning.png 15 | Images/folder.png 16 | Images/info_icon.png 17 | Images/reset.png 18 | Images/setings.png 19 | Images/flags/china.png 20 | Images/flags/Germany.png 21 | Images/flags/Russia.png 22 | Images/flags/United_Kingdom.png 23 | FreeJoyQt_de_DE.qm 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/src.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | QT += core gui 4 | 5 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 6 | 7 | CONFIG += static \ 8 | c++17 9 | 10 | RC_ICONS = Images/icon.ico 11 | 12 | TARGET = FreeJoyQt 13 | 14 | # The following define makes your compiler emit warnings if you use 15 | # any Qt feature that has been marked deprecated (the exact warnings 16 | # depend on your compiler). Please consult the documentation of the 17 | # deprecated API in order to know how to port your code away from it. 18 | DEFINES += QT_DEPRECATED_WARNINGS \ 19 | WIN_DESKTOP 20 | 21 | # You can also make your code fail to compile if it uses deprecated APIs. 22 | # In order to do so, uncomment the following line. 23 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 24 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 25 | 26 | INCLUDEPATH +="widgets" \ 27 | "widgets/adv-settings" \ 28 | "widgets/axes" \ 29 | "widgets/axes-curves" \ 30 | "widgets/buttons" \ 31 | "widgets/encoders" \ 32 | "widgets/led" \ 33 | "widgets/pins" \ 34 | "widgets/shift-reg" 35 | 36 | SOURCES += \ 37 | mainwindow_style.cpp \ 38 | widgets/axes-curves/axescurvesbutton.cpp \ 39 | widgets/axes-curves/axescurvesprofiles.cpp \ 40 | widgets/centered_cbox.cpp \ 41 | configtofile.cpp \ 42 | converter.cpp \ 43 | deviceconfig.cpp \ 44 | firmwareupdater.cpp \ 45 | hiddevice.cpp \ 46 | main.cpp \ 47 | mainwindow.cpp \ 48 | mousewheelguard.cpp \ 49 | reportconverter.cpp \ 50 | stm_main.c \ 51 | widgets/infolabel.cpp \ 52 | widgets/selectfolder.cpp \ 53 | widgets/switchbutton.cpp \ 54 | widgets/adv-settings/advancedsettings.cpp \ 55 | widgets/axes/axes.cpp \ 56 | widgets/axes/axesconfig.cpp \ 57 | widgets/axes-curves/axescurves.cpp \ 58 | widgets/axes-curves/axescurvesconfig.cpp \ 59 | widgets/axes-curves/axescurvesplot.cpp \ 60 | widgets/axes/axesextended.cpp \ 61 | widgets/axes/axestobuttonsslider.cpp \ 62 | widgets/buttons/buttonconfig.cpp \ 63 | widgets/buttons/buttonlogical.cpp \ 64 | widgets/buttons/buttonphysical.cpp \ 65 | widgets/pins/currentconfig.cpp \ 66 | widgets/debugwindow.cpp \ 67 | widgets/encoders/encoders.cpp \ 68 | widgets/encoders/encodersconfig.cpp \ 69 | widgets/adv-settings/flasher.cpp \ 70 | widgets/led/led.cpp \ 71 | widgets/led/ledconfig.cpp \ 72 | widgets/pins/pincombobox.cpp \ 73 | widgets/pins/pinconfig.cpp \ 74 | widgets/pins/pinsbluepill.cpp \ 75 | widgets/pins/pinscontrlite.cpp \ 76 | widgets/shift-reg/shiftregisters.cpp \ 77 | widgets/shift-reg/shiftregistersconfig.cpp 78 | 79 | HEADERS += \ 80 | widgets/axes-curves/axescurvesbutton.h \ 81 | widgets/axes-curves/axescurvesprofiles.h \ 82 | widgets/centered_cbox.h \ 83 | common_defines.h \ 84 | common_types.h \ 85 | configtofile.h \ 86 | converter.h \ 87 | deviceconfig.h \ 88 | firmwareupdater.h \ 89 | global.h \ 90 | hidapi.h \ 91 | hiddevice.h \ 92 | mainwindow.h \ 93 | mousewheelguard.h \ 94 | reportconverter.h \ 95 | stm_main.h \ 96 | widgets/infolabel.h \ 97 | widgets/selectfolder.h \ 98 | widgets/switchbutton.h \ 99 | version.h \ 100 | widgets/adv-settings/advancedsettings.h \ 101 | widgets/axes/axes.h \ 102 | widgets/axes/axesconfig.h \ 103 | widgets/axes-curves/axescurves.h \ 104 | widgets/axes-curves/axescurvesconfig.h \ 105 | widgets/axes-curves/axescurvesplot.h \ 106 | widgets/axes/axesextended.h \ 107 | widgets/axes/axestobuttonsslider.h \ 108 | widgets/buttons/buttonconfig.h \ 109 | widgets/buttons/buttonlogical.h \ 110 | widgets/buttons/buttonphysical.h \ 111 | widgets/pins/currentconfig.h \ 112 | widgets/debugwindow.h \ 113 | widgets/encoders/encoders.h \ 114 | widgets/encoders/encodersconfig.h \ 115 | widgets/adv-settings/flasher.h \ 116 | widgets/led/led.h \ 117 | widgets/led/ledconfig.h \ 118 | widgets/pins/pincombobox.h \ 119 | widgets/pins/pinconfig.h \ 120 | widgets/pins/pinsbluepill.h \ 121 | widgets/pins/pinscontrlite.h \ 122 | widgets/shift-reg/shiftregisters.h \ 123 | widgets/shift-reg/shiftregistersconfig.h 124 | 125 | FORMS += \ 126 | mainwindow.ui \ 127 | widgets/adv-settings/advancedsettings.ui \ 128 | widgets/axes-curves/axescurvesprofiles.ui \ 129 | widgets/axes/axes.ui \ 130 | widgets/axes/axesconfig.ui \ 131 | widgets/axes-curves/axescurves.ui \ 132 | widgets/axes-curves/axescurvesconfig.ui \ 133 | widgets/axes/axesextended.ui \ 134 | widgets/axes/axestobuttonsslider.ui \ 135 | widgets/buttons/buttonconfig.ui \ 136 | widgets/buttons/buttonlogical.ui \ 137 | widgets/buttons/buttonphysical.ui \ 138 | widgets/pins/currentconfig.ui \ 139 | widgets/debugwindow.ui \ 140 | widgets/encoders/encoders.ui \ 141 | widgets/encoders/encodersconfig.ui \ 142 | widgets/adv-settings/flasher.ui \ 143 | widgets/led/led.ui \ 144 | widgets/led/ledconfig.ui \ 145 | widgets/pins/pincombobox.ui \ 146 | widgets/pins/pinconfig.ui \ 147 | widgets/pins/pinsbluepill.ui \ 148 | widgets/pins/pinscontrlite.ui \ 149 | widgets/selectfolder.ui \ 150 | widgets/shift-reg/shiftregisters.ui \ 151 | widgets/shift-reg/shiftregistersconfig.ui 152 | 153 | TRANSLATIONS += \ 154 | FreeJoyQt_ru.ts \ 155 | FreeJoyQt_zh_CN.ts \ 156 | FreeJoyQt_de_DE.ts 157 | 158 | 159 | # Default rules for deployment. 160 | qnx: target.path = /tmp/$${TARGET}/bin 161 | else: unix:!android: target.path = /opt/$${TARGET}/bin 162 | !isEmpty(target.path): INSTALLS += target 163 | 164 | RESOURCES += \ 165 | resources.qrc 166 | 167 | linux { 168 | QMAKE_LFLAGS += -no-pie 169 | LIBS += -ludev 170 | SOURCES += \ 171 | linux/hidapi.c 172 | } 173 | 174 | win32 { 175 | RC_FILE = winapp.rc 176 | LIBS += -lhid -lsetupapi 177 | SOURCES += \ 178 | windows/hidapi.c 179 | } 180 | 181 | macx { 182 | LIBS += -framework CoreFoundation -framework IOkit 183 | SOURCES += \ 184 | mac/hidapi.c 185 | } 186 | -------------------------------------------------------------------------------- /src/stm_main.h: -------------------------------------------------------------------------------- 1 | #ifndef STM_MAIN_H 2 | #define STM_MAIN_H 3 | 4 | #include "common_types.h" 5 | 6 | dev_config_t InitConfig(void); 7 | //void InitConfig (dev_config_t * config); 8 | 9 | #endif // STM_MAIN_H 10 | -------------------------------------------------------------------------------- /src/styles/default.qss: -------------------------------------------------------------------------------- 1 | QGroupBox { 2 | background: none; 3 | border: 1px solid #414246; 4 | border-radius: 3px; 5 | margin-top: 2ex; 6 | padding: 6px 0px 0px 0px ; 7 | } 8 | 9 | QGroupBox::title 10 | { 11 | color:#ffffff; 12 | left:10px; 13 | subcontrol-origin: margin; 14 | subcontrol-position: top left; 15 | padding: -2px 2px 0px 2px; 16 | background: none; 17 | } 18 | 19 | QComboBox:disabled 20 | { 21 | background-color: #28292d; 22 | } -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | #ifndef VERSION_H 2 | #define VERSION_H 3 | 4 | #define MAJOR_VERSION 1 5 | #define MINOR_VERSION 7 6 | #define PATCH_VERSION 1 7 | #define BUILD_VERSION 5 8 | 9 | #ifdef INNO_SETUP 10 | #define APP_VERSION Str(MAJOR_VERSION) + "." + Str(MINOR_VERSION) + "." + Str(PATCH_VERSION) + "." + "b" + Str(BUILD_VERSION) 11 | #else 12 | #define str(s) #s 13 | #define xstr(s) str(s) 14 | #define APP_VERSION xstr(MAJOR_VERSION) "." xstr(MINOR_VERSION) "." xstr(PATCH_VERSION) "b" xstr(BUILD_VERSION) 15 | 16 | // If it is defined by the compiler, then it is a nightly build, and in the YYYYMMDD format. 17 | #ifndef BUILD_VERSION 18 | #define BUILD_VERSION 0 19 | #endif 20 | #endif 21 | 22 | #endif // VERSION_H 23 | -------------------------------------------------------------------------------- /src/widgets/adv-settings/advancedsettings.h: -------------------------------------------------------------------------------- 1 | #ifndef ADVANCEDSETTINGS_H 2 | #define ADVANCEDSETTINGS_H 3 | 4 | #include "flasher.h" 5 | #include 6 | 7 | QT_BEGIN_NAMESPACE 8 | class QFile; 9 | class QPushButton; 10 | QT_END_NAMESPACE 11 | 12 | namespace Ui { 13 | class AdvancedSettings; 14 | } 15 | 16 | class AdvancedSettings : public QWidget 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit AdvancedSettings(QWidget *parent = nullptr); 22 | ~AdvancedSettings(); 23 | 24 | void setStyle(bool isDark); 25 | 26 | void readFromConfig(); 27 | void writeToConfig(); 28 | 29 | void retranslateUi(); 30 | 31 | Flasher *flasher() const; // const? 32 | 33 | signals: 34 | void languageChanged(const QString &language); 35 | void themeChanged(bool dark); 36 | 37 | void fontChanged(); 38 | 39 | private slots: 40 | void on_pushButton_LangEnglish_clicked(); 41 | void on_pushButton_LangRussian_clicked(); 42 | void on_pushButton_LangSChinese_clicked(); 43 | 44 | void on_spinBox_FontSize_valueChanged(int fontSize); 45 | void on_pushButton_About_clicked(); 46 | 47 | void on_pushButton_removeName_clicked(); 48 | 49 | void on_pushButton_RestartApp_clicked(); 50 | 51 | void on_pushButton_LangDeutsch_clicked(); 52 | 53 | private: 54 | Ui::AdvancedSettings *ui; 55 | 56 | Flasher *m_flasher; 57 | 58 | QString m_default_text; 59 | QString m_default_style; 60 | }; 61 | 62 | #endif // ADVANCEDSETTINGS_H 63 | -------------------------------------------------------------------------------- /src/widgets/adv-settings/flasher.cpp: -------------------------------------------------------------------------------- 1 | #include "flasher.h" 2 | #include "ui_flasher.h" 3 | 4 | #include 5 | #include 6 | 7 | #include "deviceconfig.h" 8 | #include "global.h" 9 | 10 | #include 11 | 12 | Flasher::Flasher(QWidget *parent) 13 | : QWidget(parent) 14 | , ui(new Ui::Flasher) 15 | { 16 | ui->setupUi(this); 17 | m_enterToFlash_BtnText = ui->pushButton_FlasherMode->text(); 18 | m_flashButtonText = ui->pushButton_FlashFirmware->text(); 19 | } 20 | 21 | Flasher::~Flasher() 22 | { 23 | delete ui; 24 | } 25 | 26 | void Flasher::retranslateUi() 27 | { 28 | ui->retranslateUi(this); 29 | } 30 | 31 | void Flasher::deviceConnected(bool isConnect) 32 | { 33 | if (isConnect == true) { // disable enter to flash button if flasher connected 34 | ui->pushButton_FlasherMode->setEnabled(true); 35 | } else { 36 | ui->pushButton_FlasherMode->setEnabled(false); 37 | } 38 | } 39 | 40 | void Flasher::flasherFound(bool isFound) 41 | { 42 | ui->pushButton_FlashFirmware->setEnabled(isFound); 43 | // disable enter to flash button if flasher connected 44 | ui->pushButton_FlasherMode->setEnabled(!isFound); 45 | if (isFound == true) { 46 | qDebug()<< "Flasher found"; 47 | ui->pushButton_FlasherMode->setStyleSheet(m_defaultButtonStyle + "color: white; background-color: rgb(0, 128, 0);"); 48 | ui->pushButton_FlasherMode->setText(tr("Ready to flash")); 49 | } else { 50 | ui->pushButton_FlasherMode->setStyleSheet(m_defaultButtonStyle); 51 | ui->pushButton_FlasherMode->setText(m_enterToFlash_BtnText); 52 | } 53 | } 54 | 55 | void Flasher::on_pushButton_FlasherMode_clicked() 56 | { 57 | emit flashModeClicked(false); 58 | } 59 | 60 | void Flasher::on_pushButton_FlashFirmware_clicked() 61 | { 62 | QFile file( 63 | QFileDialog::getOpenFileName(this, tr("Open Config"), QDir::currentPath() + "/", tr("Binary files (.bin) (*.bin)"))); 64 | 65 | if (file.open(QIODevice::ReadWrite)) { 66 | ui->pushButton_FlashFirmware->setEnabled(false); 67 | m_defaultButtonStyle = ui->pushButton_FlashFirmware->styleSheet(); 68 | m_fileArray = file.readAll(); 69 | qDebug() << "file array size =" << m_fileArray.size(); 70 | emit startFlash(true); 71 | } else { 72 | qDebug() << "cant open file"; 73 | } 74 | } 75 | 76 | const QByteArray *Flasher::fileArray() const 77 | { 78 | return &m_fileArray; 79 | } 80 | 81 | void Flasher::flashStatus(int status, int percent) 82 | { 83 | ui->progressBar_Flash->setValue(percent); 84 | 85 | if (percent == 1) { 86 | ui->pushButton_FlasherMode->setText(tr("Firmware flashing..")); 87 | } 88 | 89 | if (status == FINISHED) { 90 | ui->pushButton_FlashFirmware->setText(tr("Finished")); 91 | ui->pushButton_FlashFirmware->setStyleSheet(m_defaultButtonStyle 92 | + "color: white; background-color: rgb(0, 128, 0);"); 93 | flashDone(); 94 | } else if (status == SIZE_ERROR) { 95 | ui->pushButton_FlashFirmware->setText(tr("SIZE ERROR")); 96 | ui->pushButton_FlashFirmware->setStyleSheet(m_defaultButtonStyle 97 | + "color: white; background-color: rgb(200, 0, 0);"); 98 | flashDone(); 99 | } else if (status == CRC_ERROR) { 100 | ui->pushButton_FlashFirmware->setText(tr("CRC ERROR")); 101 | ui->pushButton_FlashFirmware->setStyleSheet(m_defaultButtonStyle 102 | + "color: white; background-color: rgb(200, 0, 0);"); 103 | flashDone(); 104 | } else if (status == ERASE_ERROR) { 105 | ui->pushButton_FlashFirmware->setText(tr("ERASE ERROR")); 106 | ui->pushButton_FlashFirmware->setStyleSheet(m_defaultButtonStyle 107 | + "color: white; background-color: rgb(200, 128, 0);"); 108 | flashDone(); 109 | } else if (status == 666) { 110 | ui->pushButton_FlashFirmware->setText(tr("ERROR")); 111 | ui->pushButton_FlashFirmware->setStyleSheet(m_defaultButtonStyle 112 | + "color: white; background-color: rgb(200, 0, 0);"); 113 | flashDone(); 114 | } 115 | } 116 | 117 | void Flasher::flashDone() 118 | { 119 | QTimer::singleShot(1000, [&] { 120 | ui->pushButton_FlashFirmware->setStyleSheet(m_defaultButtonStyle); 121 | ui->pushButton_FlashFirmware->setEnabled(false); 122 | ui->pushButton_FlashFirmware->setText(m_flashButtonText); 123 | ui->pushButton_FlasherMode->setEnabled(true); 124 | ui->pushButton_FlasherMode->setStyleSheet(m_defaultButtonStyle); 125 | ui->pushButton_FlasherMode->setText(m_enterToFlash_BtnText); 126 | m_fileArray.clear(); 127 | m_fileArray.shrink_to_fit(); 128 | }); 129 | } 130 | -------------------------------------------------------------------------------- /src/widgets/adv-settings/flasher.h: -------------------------------------------------------------------------------- 1 | #ifndef FLASHER_H 2 | #define FLASHER_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class Flasher; 8 | } 9 | 10 | class Flasher : public QWidget 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit Flasher(QWidget *parent = nullptr); 16 | ~Flasher(); 17 | 18 | void retranslateUi(); 19 | 20 | void deviceConnected(bool isConnect); 21 | 22 | const QByteArray *fileArray() const; 23 | 24 | signals: 25 | void flashModeClicked(bool is_start_flash); 26 | void startFlash(bool is_start_flash); 27 | 28 | public slots: 29 | void flasherFound(bool isFound); 30 | void flashStatus(int status, int percent); 31 | private slots: 32 | void on_pushButton_FlasherMode_clicked(); 33 | void on_pushButton_FlashFirmware_clicked(); 34 | 35 | private: 36 | Ui::Flasher *ui; 37 | 38 | QByteArray m_fileArray; 39 | QString m_flashButtonText; 40 | QString m_enterToFlash_BtnText; 41 | QString m_defaultButtonStyle; 42 | void flashDone(); 43 | }; 44 | 45 | #endif // FLASHER_H 46 | -------------------------------------------------------------------------------- /src/widgets/adv-settings/flasher.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Flasher 4 | 5 | 6 | 7 | 0 8 | 0 9 | 562 10 | 182 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | Qt::Horizontal 33 | 34 | 35 | 36 | 135 37 | 20 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 0 50 | 0 51 | 52 | 53 | 54 | Enter Flasher Mode 55 | 56 | 57 | 58 | 59 | 60 | 61 | Qt::Horizontal 62 | 63 | 64 | 65 | 134 66 | 20 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | false 75 | 76 | 77 | 78 | 0 79 | 0 80 | 81 | 82 | 83 | Flash Firmware 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 0 92 | 0 93 | 94 | 95 | 96 | 0 97 | 98 | 99 | Qt::AlignCenter 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurves.cpp: -------------------------------------------------------------------------------- 1 | #include "axescurves.h" 2 | #include "ui_axescurves.h" 3 | #include 4 | #include 5 | #include 6 | #include "axes.h" 7 | 8 | #include 9 | 10 | AxesCurves::AxesCurves(QWidget *parent) 11 | : QWidget(parent) 12 | , ui(new Ui::AxesCurves) 13 | , m_ctrlActivated(false) 14 | , m_lastSelectedIndex(-1) 15 | { 16 | ui->setupUi(this); 17 | Q_ASSERT(sizeof(gEnv.pDeviceConfig->config.axis_config[0].curve_shape) == CURVE_PLOT_POINTS_COUNT); 18 | 19 | connect(ui->widget_AxesCurvesPlot, SIGNAL(pointValueChanged(int, int)), 20 | this, SLOT(pointValueChanged(int, int))); 21 | 22 | 23 | // should be X-Y-Z-Rx-Ry-Rz-Slider1-Slider2 !!! 24 | m_curvesList << ui->widget_CurveX << ui->widget_CurveY << ui->widget_CurveZ << 25 | ui->widget_CurveRx << ui->widget_CurveRy << ui->widget_CurveRz << 26 | ui->widget_CurveSlider1 << ui->widget_CurveSlider2; 27 | 28 | for (int i = 0; i < m_curvesList.size(); ++i) 29 | { 30 | m_curvesList[i]->setProperty("index", i); 31 | m_curvesList[i]->setAutoExclusive(true); 32 | m_curvesList[i]->setCheckable(true); 33 | 34 | connect(m_curvesList[i], &AxesCurvesButton::toggled, this, [this](bool checked){ 35 | if (checked) { 36 | int index = sender()->property("index").toInt(); 37 | m_lastSelectedIndex = index; 38 | ui->widget_AxesCurvesPlot->setPointValues(m_curvesList[index]->pointValues()); 39 | //ui->label_CurrentAxis->setText(axesList()[index].guiName); 40 | } 41 | }); 42 | } 43 | 44 | ui->widget_CurveX->setChecked(true); 45 | } 46 | 47 | AxesCurves::~AxesCurves() 48 | { 49 | delete ui; 50 | } 51 | 52 | 53 | void AxesCurves::retranslateUi() 54 | { 55 | ui->retranslateUi(this); 56 | } 57 | 58 | void AxesCurves::pointValueChanged(int pointNumber, int value) 59 | { 60 | Q_UNUSED(pointNumber) 61 | Q_UNUSED(value) 62 | for (int i = 0; i < m_curvesList.size(); ++i) { 63 | if (m_curvesList[i]->isChecked()) { 64 | for (int j = 0; j < CURVE_PLOT_POINTS_COUNT; ++j) { // can be optimized 65 | m_curvesList[i]->setPointValue(j, ui->widget_AxesCurvesPlot->pointValue(j)); 66 | } 67 | } 68 | } 69 | } 70 | 71 | 72 | int AxesCurves::pointValue(int pointNumber) const 73 | { 74 | return ui->widget_AxesCurvesPlot->pointValue(pointNumber); 75 | } 76 | 77 | QVector AxesCurves::pointValues() const 78 | { 79 | return ui->widget_AxesCurvesPlot->pointValues(); 80 | } 81 | 82 | void AxesCurves::setPointValue(int pointNumber, int value) 83 | { 84 | ui->widget_AxesCurvesPlot->setPointValue(pointNumber, value); 85 | } 86 | 87 | void AxesCurves::setPointValues(const QVector &values) 88 | { 89 | ui->widget_AxesCurvesPlot->setPointValues(values); 90 | } 91 | 92 | void AxesCurves::setExclusive(bool exclusive) 93 | { 94 | m_ctrlActivated = !exclusive; 95 | for (int i = 0; i < m_curvesList.size(); ++i) { 96 | m_curvesList[i]->setAutoExclusive(exclusive); 97 | } 98 | } 99 | 100 | 101 | void AxesCurves::updateAxis() 102 | { 103 | // static int tmp_raw_data = 0; // оптимизация или? 104 | // static int tmp_data = 0; 105 | // if ((tmp_raw_data != gEnv.pDeviceConfig->gamepad_report.raw_axis_data[axis_number_] || tmp_data != gEnv.pDeviceConfig->gamepad_report.axis_data[axis_number_])) 106 | // { 107 | // tmp_raw_data = gEnv.pDeviceConfig->gamepad_report.raw_axis_data[axis_number_]; 108 | // tmp_data = gEnv.pDeviceConfig->gamepad_report.axis_data[axis_number_]; 109 | // } 110 | 111 | // if (gEnv.pDeviceConfig->config.axis_config[axis_number_].out_enabled == 1) 112 | // { 113 | 114 | if (m_lastSelectedIndex > -1) { 115 | params_report_t *paramsRep = &gEnv.pDeviceConfig->paramsReport; 116 | int min = gEnv.pDeviceConfig->config.axis_config[m_lastSelectedIndex].calib_min; 117 | int max = gEnv.pDeviceConfig->config.axis_config[m_lastSelectedIndex].calib_max; 118 | int value_x; 119 | int value_y; 120 | 121 | if (paramsRep->axis_data[m_lastSelectedIndex] < AXIS_CENTER_VALUE) { 122 | value_y = round(paramsRep->axis_data[m_lastSelectedIndex] / (float) AXIS_MIN_VALUE * CURVES_MIN_VALUE); 123 | } else { 124 | value_y = round(paramsRep->axis_data[m_lastSelectedIndex] / (float) AXIS_MAX_VALUE * CURVES_MAX_VALUE); 125 | } 126 | 127 | value_x = abs(round((paramsRep->raw_axis_data[m_lastSelectedIndex] - min) / (float)(max - min) * 200.0f)); 128 | 129 | ui->widget_AxesCurvesPlot->setCurAxisPos(value_x, value_y); 130 | } 131 | // } 132 | } 133 | 134 | void AxesCurves::deviceStatus(bool isConnect) 135 | { 136 | if (gEnv.pDeviceConfig->config.axis_config[m_lastSelectedIndex].source_main != -1 && 137 | gEnv.pDeviceConfig->config.axis_config[m_lastSelectedIndex].out_enabled == 1) 138 | { 139 | ui->widget_AxesCurvesPlot->deviceStatus(isConnect); 140 | } else { 141 | ui->widget_AxesCurvesPlot->deviceStatus(false); 142 | } 143 | } 144 | 145 | 146 | void AxesCurves::readFromConfig() 147 | { 148 | dev_config_t *cfg = &gEnv.pDeviceConfig->config; 149 | 150 | for (int i = 0; i < m_curvesList.size(); ++i) 151 | { 152 | AxesCurvesButton *curve = m_curvesList[i]; 153 | 154 | if (i == 0) { 155 | curve->setChecked(true); 156 | } else { 157 | curve->setChecked(false); 158 | } 159 | 160 | for (int j = 0; j < curve->pointCount(); ++j) { 161 | curve->setPointValue(j, cfg->axis_config[i].curve_shape[j]); 162 | if (curve->isChecked()) { 163 | ui->widget_AxesCurvesPlot->setPointValue(j, cfg->axis_config[i].curve_shape[j]); 164 | } 165 | } 166 | } 167 | } 168 | 169 | void AxesCurves::writeToConfig() 170 | { 171 | dev_config_t *cfg = &gEnv.pDeviceConfig->config; 172 | for (int i = 0; i < m_curvesList.size(); ++i) { 173 | for (int j = 0; j < m_curvesList[i]->pointCount(); ++j) { 174 | cfg->axis_config[i].curve_shape[j] = m_curvesList[i]->pointValue(j); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurves.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESCURVES_H 2 | #define AXESCURVES_H 3 | 4 | #include 5 | #include "axescurvesplot.h" 6 | 7 | #include "deviceconfig.h" 8 | #include "global.h" 9 | 10 | namespace Ui { 11 | class AxesCurves; 12 | } 13 | class AxesCurvesButton; 14 | 15 | class AxesCurves : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit AxesCurves(QWidget *parent = nullptr); 21 | ~AxesCurves(); 22 | 23 | void readFromConfig(); 24 | void writeToConfig(); 25 | 26 | void retranslateUi(); 27 | 28 | void setDarkIcon(bool isDark); 29 | 30 | int pointValue(int pointNumber) const; 31 | QVector pointValues() const; 32 | 33 | void setPointValue(int pointNumber, int value); 34 | void setPointValues(const QVector &values); 35 | 36 | void setExclusive(bool exclusive); 37 | 38 | void updateAxis(); 39 | void deviceStatus(bool isConnect); 40 | 41 | signals: 42 | void deviceStatusChanged(bool isConnect); 43 | 44 | void axisCurveIndexChanged(int axisNumber, int index); 45 | void curvePointValueChanged(int axisNumber, int pointNumber, int value); 46 | //void resetCurvesProfiles(); 47 | 48 | private slots: 49 | void pointValueChanged(int pointNumber, int value); 50 | 51 | private: 52 | Ui::AxesCurves *ui; 53 | QList m_curvesList; 54 | bool m_ctrlActivated; 55 | int m_lastSelectedIndex; 56 | int m_curvePointsValue[CURVE_PLOT_POINTS_COUNT]; 57 | }; 58 | 59 | #endif // AXESCURVES_H 60 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurves.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AxesCurves 4 | 5 | 6 | 7 | 0 8 | 0 9 | 965 10 | 600 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | X 33 | 34 | 35 | Qt::AlignCenter 36 | 37 | 38 | 39 | 40 | 41 | 42 | Rx 43 | 44 | 45 | Qt::AlignCenter 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | Y 59 | 60 | 61 | Qt::AlignCenter 62 | 63 | 64 | 65 | 66 | 67 | 68 | Ry 69 | 70 | 71 | Qt::AlignCenter 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Z 85 | 86 | 87 | Qt::AlignCenter 88 | 89 | 90 | 91 | 92 | 93 | 94 | Rz 95 | 96 | 97 | Qt::AlignCenter 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | Slider 1 111 | 112 | 113 | Qt::AlignCenter 114 | 115 | 116 | 117 | 118 | 119 | 120 | Slider 2 121 | 122 | 123 | Qt::AlignCenter 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | AxesCurvesPlot 141 | QWidget 142 |
axescurvesplot.h
143 | 1 144 |
145 | 146 | AxesCurvesButton 147 | QWidget 148 |
axescurvesbutton.h
149 | 1 150 |
151 |
152 | 153 | 154 |
155 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurvesbutton.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESCURVESBUTTON_H 2 | #define AXESCURVESBUTTON_H 3 | 4 | #include 5 | #include "axescurvesplot.h" 6 | 7 | class AxesCurvesButton : public AxesCurvesPlot 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | explicit AxesCurvesButton(QWidget *parent = nullptr); 13 | 14 | bool isChecked() const; 15 | bool autoExclusive() const; 16 | void setAutoExclusive(bool enabled); 17 | void setCheckable(bool chackable); 18 | void setDraggable(bool draggable); 19 | 20 | public slots: 21 | void setChecked(bool checked); 22 | 23 | signals: 24 | void toggled(bool checked); 25 | void clicked(bool checked = false); 26 | 27 | protected: 28 | void mouseMoveEvent(QMouseEvent *event) override; 29 | void mousePressEvent(QMouseEvent *event) override; 30 | void mouseReleaseEvent(QMouseEvent *event) override; 31 | void paintEvent(QPaintEvent *event) override; 32 | 33 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 34 | void enterEvent(QEvent *event) override; 35 | #else 36 | void enterEvent(QEnterEvent *event) override; 37 | #endif 38 | void leaveEvent(QEvent *event) override; 39 | 40 | void dragEnterEvent(QDragEnterEvent *event) override; 41 | void dragLeaveEvent(QDragLeaveEvent *event) override; 42 | void dropEvent(QDropEvent *event) override; 43 | 44 | bool eventFilter(QObject *obj, QEvent *event) override; 45 | private: 46 | void installStyleSheet(); 47 | QList queryButtonList() const; 48 | AxesCurvesButton *queryCheckedButton() const; 49 | 50 | QPoint m_dragStartPos; 51 | bool m_toggled; 52 | bool m_autoExclusive; 53 | bool m_checkable; 54 | bool m_draggable; 55 | }; 56 | 57 | #endif // AXESCURVESBUTTON_H 58 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurvesconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "axescurvesconfig.h" 2 | #include "ui_axescurvesconfig.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "axescurves.h" 10 | #include "axescurvesprofiles.h" 11 | #include "deviceconfig.h" 12 | #include "global.h" 13 | 14 | static const int PROFILES_COUNT = 8; 15 | 16 | AxesCurvesConfig::AxesCurvesConfig(QWidget *parent) : 17 | QWidget(parent), 18 | ui(new Ui::AxesCurvesConfig) 19 | { 20 | ui->setupUi(this); 21 | 22 | for (int i = 0; i < PROFILES_COUNT; ++i) { 23 | AxesCurvesProfiles *p = new AxesCurvesProfiles(this); 24 | m_profiles.append(p); 25 | p->setProperty("index", i); 26 | ui->layoutH_Profiles->addWidget(p); 27 | switch (i) { 28 | case 0 : p->setLinear(); 29 | break; 30 | case 1 : p->setLinearInvert(); 31 | break; 32 | case 2 : p->setExponent(); 33 | break; 34 | case 3 : p->setExponentInvert(); 35 | break; 36 | case 4 : p->setShape(); 37 | break; 38 | case 5 : p->setShape2(); 39 | break; 40 | case 6 : p->setIDK(); 41 | break; 42 | case 7 : p->setIDK2(); 43 | break; 44 | default: 45 | break; 46 | } 47 | connect(p, &AxesCurvesProfiles::presetClicked, ui->widget_AxesCurves, &AxesCurves::setPointValues); 48 | connect(p, &AxesCurvesProfiles::setClicked, [this, p](){ 49 | p->setPointValues(ui->widget_AxesCurves->pointValues()); 50 | }); 51 | } 52 | 53 | // load curves profiles from app config file 54 | QSettings *appS = gEnv.pAppSettings; 55 | appS->beginGroup("CurvesProfiles"); 56 | bool reset = appS->value("Reset", true).toBool(); 57 | if (reset == false) { 58 | for (int i = 0; i < PROFILES_COUNT; ++i) { 59 | appS->beginReadArray("Curve_" + QString::number(i + 1)); 60 | for (int j = 0; j < m_profiles[i]->pointCount(); ++j) { 61 | appS->setArrayIndex(j); 62 | m_profiles[i]->setPointValue(j, appS->value("Point_" + QString::number(j), AXIS_MIN_VALUE + 20*j).toInt()); 63 | } 64 | appS->endArray(); 65 | } 66 | } 67 | appS->endGroup(); 68 | 69 | ui->layoutV_Help->setAlignment(Qt::AlignBottom); 70 | setFocusPolicy(Qt::StrongFocus); 71 | 72 | m_toolTip = ui->info->toolTip(); 73 | updateColor(); 74 | installEventFilter(this); 75 | } 76 | 77 | AxesCurvesConfig::~AxesCurvesConfig() 78 | { 79 | // save curves profiles to app config file 80 | QSettings *appS = gEnv.pAppSettings; 81 | appS->beginGroup("CurvesProfiles"); 82 | appS->setValue("Reset", false); 83 | for (int i = 0; i < PROFILES_COUNT; ++i) { 84 | appS->beginWriteArray("Curve_" + QString::number(i + 1)); 85 | for (int j = 0; j < m_profiles[i]->pointCount(); ++j) { 86 | appS->setArrayIndex(j); 87 | appS->setValue("Point_" + QString::number(j), m_profiles[i]->pointValue(j)); 88 | } 89 | appS->endArray(); 90 | } 91 | appS->endGroup(); 92 | delete ui; 93 | } 94 | 95 | 96 | void AxesCurvesConfig::retranslateUi() 97 | { 98 | ui->retranslateUi(this); 99 | ui->widget_AxesCurves->retranslateUi(); 100 | for (int i = 0; i < m_profiles.size(); ++i) { 101 | m_profiles[i]->retranslateUi(); 102 | } 103 | } 104 | 105 | void AxesCurvesConfig::setPoints(const QVector &values) 106 | { 107 | ui->widget_AxesCurves->setPointValues(values); 108 | } 109 | 110 | void AxesCurvesConfig::setExclusive(bool exclusive) 111 | { 112 | ui->widget_AxesCurves->setExclusive(exclusive); 113 | 114 | if (sender() != ui->toolButton_Ctrl) { 115 | ui->toolButton_Ctrl->setChecked(!exclusive); 116 | } 117 | if (exclusive) { 118 | ui->toolButton_Ctrl->setPalette(window()->palette()); 119 | } else { 120 | QPalette pal(window()->palette()); 121 | pal.setColor(QPalette::Button, QColor(0, 128, 0)); 122 | ui->toolButton_Ctrl->setPalette(pal); 123 | } 124 | } 125 | 126 | void AxesCurvesConfig::on_toolButton_Ctrl_toggled(bool checked) 127 | { 128 | setExclusive(!checked); 129 | } 130 | 131 | 132 | void AxesCurvesConfig::updateAxesCurves() 133 | { 134 | ui->widget_AxesCurves->updateAxis(); 135 | } 136 | 137 | void AxesCurvesConfig::deviceStatus(bool isConnect) 138 | { 139 | ui->widget_AxesCurves->deviceStatus(isConnect); 140 | } 141 | 142 | //! QPixmap gray-scale image (an alpha map) to colored QPixmap 143 | QPixmap AxesCurvesConfig::coloringPixmap(QPixmap pixmap, const QColor &color) 144 | { 145 | // initialize painter to draw on a pixmap and set composition mode 146 | QPainter painter(&pixmap); 147 | painter.setCompositionMode(QPainter::CompositionMode_SourceIn); 148 | // set color 149 | painter.setBrush(color); 150 | painter.setPen(color); 151 | // paint rect 152 | painter.drawRect(pixmap.rect()); 153 | // here is our new colored icon 154 | return pixmap; 155 | } 156 | 157 | void AxesCurvesConfig::updateColor() 158 | { 159 | QColor col = QApplication::palette().color(QPalette::Text); 160 | QPixmap pix = coloringPixmap(QPixmap(":/Images/reset.png"), col); 161 | 162 | QByteArray arr; 163 | QBuffer buf(&arr); 164 | pix.save(&buf, "PNG"); 165 | QString url = QString("data:image/png;base64,") + arr.toBase64(); 166 | QString tt = m_toolTip; 167 | tt.replace(":/Images/reset.png", url); 168 | 169 | ui->info->setToolTip(tt); 170 | } 171 | 172 | bool AxesCurvesConfig::eventFilter(QObject *object, QEvent *event) 173 | { 174 | Q_UNUSED(object) 175 | if (event->type() == QEvent::PaletteChange) { 176 | updateColor(); 177 | return false; 178 | } 179 | return false; 180 | } 181 | 182 | 183 | void AxesCurvesConfig::readFromConfig() 184 | { 185 | ui->widget_AxesCurves->readFromConfig(); 186 | } 187 | 188 | void AxesCurvesConfig::writeToConfig() 189 | { 190 | ui->widget_AxesCurves->writeToConfig(); 191 | } 192 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurvesconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESCURVESCONFIG_H 2 | #define AXESCURVESCONFIG_H 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | class QComboBox; 8 | QT_END_NAMESPACE 9 | class AxesCurvesProfiles; 10 | 11 | namespace Ui { 12 | class AxesCurvesConfig; 13 | } 14 | 15 | class AxesCurvesConfig : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit AxesCurvesConfig(QWidget *parent = nullptr); 21 | ~AxesCurvesConfig(); 22 | 23 | void readFromConfig(); 24 | void writeToConfig(); 25 | 26 | void retranslateUi(); 27 | 28 | void setExclusive(bool exclusive); 29 | 30 | void updateAxesCurves(); 31 | void deviceStatus(bool isConnect); 32 | 33 | protected: 34 | bool eventFilter(QObject *obj, QEvent *event) override; 35 | 36 | private slots: 37 | void setPoints(const QVector &values); 38 | void on_toolButton_Ctrl_toggled(bool checked); 39 | 40 | private: 41 | Ui::AxesCurvesConfig *ui; 42 | QList m_profiles; 43 | 44 | void updateColor(); 45 | QPixmap coloringPixmap(QPixmap pixmap, const QColor &color); 46 | QString m_toolTip; 47 | }; 48 | 49 | #endif // AXESCURVESCONFIG_H 50 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurvesconfig.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AxesCurvesConfig 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1062 10 | 600 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | Curve profiles 33 | 34 | 35 | Qt::AlignCenter 36 | 37 | 38 | 39 | 6 40 | 41 | 42 | 6 43 | 44 | 45 | 6 46 | 47 | 48 | 6 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 0 57 | 58 | 59 | 60 | 61 | 62 | 0 63 | 0 64 | 65 | 66 | 67 | 68 | 0 69 | 0 70 | 71 | 72 | 73 | 74 | 999 75 | 999 76 | 77 | 78 | 79 | <html><head/><body><p>Curve profiles are saves in the application configuration.</p><p><span style=" font-size:10pt; font-weight:600;">Set </span><span style=" font-weight:600;">-</span> sets profile to the current value of the curve.</p><p><img src=":/Images/reset.png" height="16"/> - resets profile value.</p><p>Use <span style=" font-weight:600;">CTRL</span> for multiple selection.</p><p>You can <span style=" font-weight:600;">drag</span> curves with the <span style=" font-weight:600;">mouse.</span></p></body></html> 80 | 81 | 82 | Qt::AlignBottom|Qt::AlignHCenter 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 0 91 | 0 92 | 93 | 94 | 95 | Ctrl 96 | 97 | 98 | true 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | AxesCurves 112 | QWidget 113 |
axescurves.h
114 | 1 115 |
116 | 117 | InfoLabel 118 | QLabel 119 |
infolabel.h
120 |
121 |
122 | 123 | 124 |
125 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurvesplot.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESCURVESPLOT_H 2 | #define AXESCURVESPLOT_H 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | class QLabel; 8 | QT_END_NAMESPACE 9 | //#include 10 | 11 | #define CURVE_PLOT_POINTS_COUNT 11 //? 12 | 13 | #define CURVES_MIN_VALUE -100 //? 14 | #define CURVES_MAX_VALUE 100 15 | 16 | class AxesCurvesPlot : public QWidget 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit AxesCurvesPlot(bool labelEnabled = true, QWidget *parent = nullptr); 22 | 23 | void setBorderOffset(int offset); 24 | void setPointRadius(int radius); 25 | 26 | void setLineWidth(int width); 27 | int lineWidth() const; 28 | 29 | void setGridEnabled(bool enabled); 30 | bool gridEnabled() const; 31 | 32 | int pointCount() const; 33 | int pointValue(int pointIndex) const; 34 | QVector pointValues() const; 35 | 36 | void setPointValue(int pointIndex, int value); 37 | void setPointValues(const QVector &values); 38 | 39 | int maximum() const; 40 | int minimum() const; 41 | 42 | void setCurAxisPos(int posX, int posY); 43 | void deviceStatus(bool isConnect); 44 | 45 | signals: 46 | void pointValueChanged(int point, int value); 47 | //void pointValuesChanged(QVector values); 48 | 49 | protected: 50 | void mouseMoveEvent(QMouseEvent *event) override; 51 | void mousePressEvent(QMouseEvent *event) override; 52 | void mouseReleaseEvent(QMouseEvent *event) override; 53 | void paintEvent(QPaintEvent *event) override; 54 | void resizeEvent(QResizeEvent *event) override; 55 | 56 | private: 57 | int calcPointValue(int currentPos) const; 58 | float calcPointPosY(int value) const; 59 | float calcPointPosX(int value) const; 60 | void movePoint(int pos_y, int point_number); 61 | void updateLabelPos(); 62 | 63 | bool m_gridEnabled = true; 64 | int m_radius = 8; 65 | int m_lineWidth = 2; 66 | int m_offset = 20; 67 | int m_currentPosRadius = 6; 68 | const int m_kPointsCount = CURVE_PLOT_POINTS_COUNT; 69 | const int m_kColumnsCount = CURVE_PLOT_POINTS_COUNT - 1; 70 | const int m_kRowsCount = CURVE_PLOT_POINTS_COUNT - 1; 71 | const int m_kLabelWidth = 20; 72 | bool m_isDeviceConnect; 73 | 74 | float m_columnWidth; 75 | float m_rowHeight; 76 | int m_width; 77 | int m_height; 78 | 79 | const int m_kMaxPointValue = CURVES_MAX_VALUE; 80 | const int m_kMinPointValue = CURVES_MIN_VALUE; 81 | 82 | const QColor m_kPointCurrentPosColor = QColor(190, 0, 0, 220); 83 | const QColor m_kPointInactiveColor = QColor(1, 119, 215); 84 | const QColor m_kPointActiveColor = Qt::black; 85 | const QColor m_kPointMoveColor = Qt::lightGray; 86 | const QColor m_kCurveColor = QColor(1, 119, 215); 87 | 88 | struct AxesCurve_currentPos 89 | { 90 | QColor color; 91 | int posX; 92 | int posY; 93 | }; 94 | AxesCurve_currentPos m_curAxisPos; 95 | 96 | struct AxesCurve_point 97 | { 98 | QColor color; 99 | QRect area; 100 | float posX; 101 | float posY; 102 | int current_value; 103 | bool is_drag; 104 | //QLabel text_label; 105 | }; 106 | QList m_pointPtrList; 107 | QList m_labelPtrList; 108 | }; 109 | 110 | #endif // AXESCURVESPLOT_H 111 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurvesprofiles.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESCURVESPROFILES_H 2 | #define AXESCURVESPROFILES_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Ui { 8 | class AxesCurvesProfiles; 9 | } 10 | 11 | class AxesCurvesProfiles : public QWidget 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit AxesCurvesProfiles(QWidget *parent = nullptr); 17 | ~AxesCurvesProfiles(); 18 | void retranslateUi(); 19 | 20 | void setPointValue(int pointIndex, int value); 21 | void setPointValues(const QVector &values); 22 | 23 | int pointCount() const; 24 | int pointValue(int pointIndex) const; 25 | QVector pointValues() const; 26 | 27 | void setLinear(); 28 | void setLinearInvert(); 29 | void setExponent(); 30 | void setExponentInvert(); 31 | void setShape(); 32 | void setShape2(); 33 | void setIDK(); 34 | void setIDK2(); 35 | 36 | signals: 37 | void presetClicked(QVector values); 38 | void setClicked(); 39 | void resetClicked(); 40 | 41 | protected: 42 | bool eventFilter(QObject *obj, QEvent *event) override; 43 | 44 | private slots: 45 | void CurveClicked(); 46 | 47 | void on_toolButton_Set_clicked(); 48 | void on_toolButton_Reset_clicked(); 49 | 50 | private: 51 | Ui::AxesCurvesProfiles *ui; 52 | //void (AxesCurvesProfiles::*m_pPresetFunc)(); 53 | std::function m_pPresetFunc; 54 | void updateColor(); 55 | QIcon pixmapToIcon(QPixmap pixmap, const QColor &color); 56 | }; 57 | 58 | #endif // AXESCURVESPROFILES_H 59 | -------------------------------------------------------------------------------- /src/widgets/axes-curves/axescurvesprofiles.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AxesCurvesProfiles 4 | 5 | 6 | 7 | 0 8 | 0 9 | 114 10 | 93 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 9 39 | 40 | 41 | 9 42 | 43 | 44 | 9 45 | 46 | 47 | 48 | 49 | 50 | 0 51 | 0 52 | 53 | 54 | 55 | Set 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 0 65 | 66 | 67 | 68 | 69 | :/Images/reset.png:/Images/reset.png 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | AxesCurvesButton 80 | QWidget 81 |
axescurvesbutton.h
82 | 1 83 |
84 |
85 | 86 | 87 | 88 | 89 |
90 | -------------------------------------------------------------------------------- /src/widgets/axes/axes.h: -------------------------------------------------------------------------------- 1 | #ifndef AXES_H 2 | #define AXES_H 3 | 4 | #include 5 | #include "axesextended.h" 6 | #include "axestobuttonsslider.h" 7 | 8 | #include "deviceconfig.h" 9 | #include "global.h" 10 | 11 | const QVector &axesList(); 12 | 13 | namespace Ui { 14 | class Axes; 15 | } 16 | 17 | class Axes : public QWidget 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit Axes(int axisNumber, QWidget *parent = nullptr); 23 | ~Axes(); 24 | 25 | void readFromConfig(); 26 | void writeToConfig(); 27 | 28 | void retranslateUi(); 29 | 30 | void updateAxisRaw(); 31 | void updateAxisOut(); 32 | 33 | void addOrDeleteMainSource(int sourceEnum, QString sourceName, bool isAdd); 34 | 35 | signals: 36 | void a2bCountChanged(int count, int previousCount); 37 | 38 | private slots: 39 | void calibMinMaxValueChanged(int value); 40 | void calibrationStarted(int rawValue); 41 | void mainSourceIndexChanged(int index); 42 | 43 | void a2bSpinBoxChanged(int count); 44 | 45 | void outputValueChanged(bool isChecked); 46 | 47 | void on_pushButton_StartCalib_clicked(bool checked); 48 | void on_pushButton_SetCenter_clicked(); 49 | void on_checkBox_Center_stateChanged(int state); 50 | 51 | void on_pushButton_ResetCalib_clicked(); 52 | 53 | void on_checkBox_ShowExtend_stateChanged(int state); 54 | 55 | private: 56 | Ui::Axes *ui; 57 | const int m_kMinA2bButtons = 1;//2 58 | bool m_calibrationStarted; 59 | bool m_outputEnabled; 60 | int m_a2bButtonsCount; 61 | int m_lastA2bCount; 62 | int m_axisNumber; 63 | const QString m_kStartCalStr = tr("Calibrate"); 64 | const QString m_kStopCalStr = tr("Stop && Save"); 65 | AxesExtended *m_axesExtend; 66 | 67 | QVector m_mainSource_enumIndex; 68 | 69 | enum 70 | { 71 | Encoder = -3, 72 | I2C = -2, 73 | None = -1, 74 | A0 = 0, 75 | A1, 76 | A2, 77 | A3, 78 | A4, 79 | A5, 80 | A6, 81 | A7, 82 | A8, 83 | A9, 84 | A10, 85 | A15, 86 | B0, 87 | B1, 88 | B3, 89 | B4, 90 | B5, 91 | B6, 92 | B7, 93 | B8, 94 | B9, 95 | B10, 96 | B11, 97 | B12, 98 | B13, 99 | B14, 100 | B15, 101 | C13, 102 | C14, 103 | C15, 104 | }; 105 | 106 | 107 | const QVector m_axesPinList = // любая последовательность, но первые 2 добавляются в конструкторе 108 | {{ 109 | {None, tr("None")}, 110 | {Encoder, tr("Encoder")}, 111 | {I2C, "I2C"}, 112 | {A0, "A0"}, 113 | {A1, "A1"}, 114 | {A2, "A2"}, 115 | {A3, "A3"}, 116 | {A4, "A4"}, 117 | {A5, "A5"}, 118 | {A6, "A6"}, 119 | {A7, "A7"}, 120 | {A8, "A8"}, 121 | {A9, "A9"}, 122 | {A10, "A10"}, 123 | {A15, "A15"}, 124 | {B0, "B0"}, 125 | {B1, "B1"}, 126 | {B3, "B3"}, 127 | {B4, "B4"}, 128 | {B5, "B5"}, 129 | {B6, "B6"}, 130 | {B7, "B7"}, 131 | {B8, "B8"}, 132 | {B9, "B9"}, 133 | {B10, "B10"}, 134 | {B11, "B11"}, 135 | {B12, "B12"}, 136 | {B13, "B13"}, 137 | {B14, "B14"}, 138 | {B15, "B15"}, 139 | {C13, "C13"}, 140 | {C14, "C14"}, 141 | {C15, "C15"}, 142 | }}; 143 | 144 | const QVector m_axisSourceMain = // порядов обязан быть как в common_types.h!!!!!!!!!!! 145 | {{ 146 | {None, tr("None")}, 147 | {Encoder, tr("Encoder")}, 148 | }}; 149 | }; 150 | 151 | #endif // AXES_H 152 | -------------------------------------------------------------------------------- /src/widgets/axes/axesconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "axesconfig.h" 2 | #include "ui_axesconfig.h" 3 | #include 4 | #include 5 | #include "global.h" 6 | 7 | AxesConfig::AxesConfig(QWidget *parent) 8 | : QWidget(parent) 9 | , ui(new Ui::AxesConfig) 10 | { 11 | ui->setupUi(this); 12 | m_a2bButtonsCount = 0; 13 | 14 | ui->layoutV_Axes->setAlignment(Qt::AlignTop); 15 | // axes spawn 16 | for (int i = 0; i < MAX_AXIS_NUM; i++) { 17 | Axes *axis = new Axes(i, this); 18 | ui->layoutV_Axes->addWidget(axis); 19 | m_axesPtrList.append(axis); 20 | connect(axis, SIGNAL(a2bCountChanged(int, int)), 21 | this, SLOT(a2bCountCalc(int, int))); 22 | // added hidden axes checkboxes 23 | QCheckBox *chb = new QCheckBox(axesList()[i].guiName, this); 24 | ui->layoutH_HiddenAxes->addWidget(chb); 25 | chb->setProperty("index", i); 26 | m_hideChBoxes.append(chb); 27 | connect(chb, &QCheckBox::toggled, this, [&](bool hide) { 28 | hideAxis(sender()->property("index").toInt(), hide); 29 | }); 30 | } 31 | 32 | gEnv.pAppSettings->beginGroup("OtherSettings"); 33 | for (int i = 0; i < m_hideChBoxes.size(); ++i) { 34 | m_hideChBoxes[i]->setChecked(gEnv.pAppSettings->value(axesList()[i].guiName, "false").toBool()); 35 | } 36 | gEnv.pAppSettings->endGroup(); 37 | } 38 | 39 | AxesConfig::~AxesConfig() 40 | { 41 | gEnv.pAppSettings->beginGroup("OtherSettings"); 42 | for (int i = 0; i < m_hideChBoxes.size(); ++i) { 43 | gEnv.pAppSettings->setValue(axesList()[i].guiName, m_hideChBoxes[i]->isChecked()); 44 | } 45 | gEnv.pAppSettings->endGroup(); 46 | delete ui; 47 | } 48 | 49 | void AxesConfig::retranslateUi() 50 | { 51 | ui->retranslateUi(this); 52 | for (int i = 0; i < MAX_AXIS_NUM; ++i) { 53 | m_axesPtrList[i]->retranslateUi(); 54 | } 55 | } 56 | 57 | void AxesConfig::a2bCountCalc(int count, int previousCount) 58 | { 59 | m_a2bButtonsCount += count - previousCount; 60 | emit a2bCountChanged(m_a2bButtonsCount); 61 | } 62 | 63 | void AxesConfig::addOrDeleteMainSource(int sourceEnum, QString sourceName, bool isAdd) 64 | { 65 | for (int i = 0; i < MAX_AXIS_NUM; ++i) { 66 | m_axesPtrList[i]->addOrDeleteMainSource(sourceEnum, sourceName, isAdd); 67 | } 68 | } 69 | 70 | void AxesConfig::axesValueChanged() 71 | { 72 | for (int i = 0; i < MAX_AXIS_NUM; ++i) { 73 | m_axesPtrList[i]->updateAxisOut(); 74 | m_axesPtrList[i]->updateAxisRaw(); 75 | } 76 | } 77 | 78 | void AxesConfig::hideAxis(int index, bool hide) 79 | { 80 | if (index < 0) index = 0; 81 | else if (index >= m_axesPtrList.size()) index = m_axesPtrList.size() -1; 82 | 83 | if (hide) { 84 | m_axesPtrList[index]->hide(); 85 | } else { 86 | m_axesPtrList[index]->show(); 87 | } 88 | } 89 | 90 | void AxesConfig::readFromConfig() 91 | { 92 | for (int i = 0; i < MAX_AXIS_NUM; i++) { 93 | m_axesPtrList[i]->readFromConfig(); 94 | } 95 | } 96 | 97 | void AxesConfig::writeToConfig() 98 | { 99 | for (int i = 0; i < MAX_AXIS_NUM; i++) { 100 | m_axesPtrList[i]->writeToConfig(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/widgets/axes/axesconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESCONFIG_H 2 | #define AXESCONFIG_H 3 | 4 | #include "axes.h" 5 | #include 6 | 7 | #include "deviceconfig.h" 8 | #include "global.h" 9 | 10 | namespace Ui { 11 | class AxesConfig; 12 | } 13 | 14 | class QCheckBox; 15 | 16 | class AxesConfig : public QWidget 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit AxesConfig(QWidget *parent = nullptr); 22 | ~AxesConfig(); 23 | 24 | void readFromConfig(); 25 | void writeToConfig(); 26 | 27 | void retranslateUi(); 28 | 29 | void axesValueChanged(); 30 | 31 | signals: 32 | void axisRawValueChanged(int); 33 | void axisOutValueChanged(int); 34 | void a2bCountChanged(int count); 35 | 36 | public slots: 37 | void addOrDeleteMainSource(int sourceEnum, QString sourceName, bool isAdd); 38 | private slots: 39 | void a2bCountCalc(int count, int previousCount); 40 | void hideAxis(int index, bool hide); 41 | // void axesValueChanged(int value); 42 | 43 | private: 44 | Ui::AxesConfig *ui; 45 | int m_a2bButtonsCount; 46 | 47 | QList m_axesPtrList; 48 | QList m_hideChBoxes; 49 | }; 50 | 51 | #endif // AXESCONFIG_H 52 | -------------------------------------------------------------------------------- /src/widgets/axes/axesconfig.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AxesConfig 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1062 10 | 638 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | 35 | QFrame::NoFrame 36 | 37 | 38 | true 39 | 40 | 41 | 42 | 43 | 0 44 | 0 45 | 1062 46 | 620 47 | 48 | 49 | 50 | 51 | 10 52 | 53 | 54 | 0 55 | 56 | 57 | 0 58 | 59 | 60 | 0 61 | 62 | 63 | 0 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | Qt::Horizontal 73 | 74 | 75 | 76 | 77 | 78 | 79 | 0 80 | 81 | 82 | 83 | 84 | Hidden axes: 85 | 86 | 87 | Qt::AlignCenter 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/widgets/axes/axesextended.cpp: -------------------------------------------------------------------------------- 1 | #include "axesextended.h" 2 | #include "ui_axesextended.h" 3 | 4 | #include "converter.h" 5 | #include "axes.h" 6 | 7 | AxesExtended::AxesExtended(int axisNumber, QWidget *parent) 8 | : QWidget(parent) 9 | , ui(new Ui::AxesExtended) 10 | { 11 | ui->setupUi(this); 12 | 13 | m_axisNumber = axisNumber; 14 | 15 | // I2C 16 | m_i2c_enumIndex.reserve(m_i2cPtrList.size()); 17 | for (int i = 0; i < m_i2cPtrList.size(); ++i) { 18 | ui->comboBox_I2cAddress->addItem(m_i2cPtrList[i].guiName); 19 | m_i2c_enumIndex.push_back(m_i2cPtrList[i].deviceEnumIndex); 20 | } 21 | // function 22 | m_function_enumIndex.reserve(m_functionList.size()); 23 | for (int i = 0; i < m_functionList.size(); ++i) { 24 | ui->comboBox_Function->addItem(m_functionList[i].guiName); 25 | m_function_enumIndex.push_back(m_functionList[i].deviceEnumIndex); 26 | } 27 | // button 1 and 3 28 | m_button_1_3_enumIndex.reserve(m_button_1_3_list.size()); 29 | for (int i = 0; i < m_button_1_3_list.size(); ++i) { 30 | ui->comboBox_Button1->addItem(m_button_1_3_list[i].guiName); 31 | ui->comboBox_Button3->addItem(m_button_1_3_list[i].guiName); 32 | m_button_1_3_enumIndex.push_back(m_button_1_3_list[i].deviceEnumIndex); 33 | } 34 | // button 2 35 | m_button_2_enumIndex.reserve(m_button_2_list.size()); 36 | for (int i = 0; i < m_button_2_list.size(); ++i) { 37 | ui->comboBox_Button2->addItem(m_button_2_list[i].guiName); 38 | m_button_2_enumIndex.push_back(m_button_2_list[i].deviceEnumIndex); 39 | } 40 | // function axis 41 | for (int i = 0; i < axesList().size(); ++i) { 42 | ui->comboBox_AxisSource2->addItem(axesList()[i].guiName); 43 | } 44 | 45 | ui->comboBox_Button1->setCurrentIndex(AXIS_BUTTON_DOWN); 46 | ui->comboBox_Button2->setCurrentIndex(AXIS_BUTTON_RESET); 47 | ui->comboBox_Button3->setCurrentIndex(AXIS_BUTTON_UP); 48 | // set ADS1115_00 selected 49 | ui->comboBox_I2cAddress->setCurrentIndex(1); 50 | 51 | // set filter text 52 | ui->label_Filter->setText(tr("Filter") + " " + m_filterList[ui->sliderH_Filter->value()].guiName); 53 | 54 | // filter changed 55 | connect(ui->sliderH_Filter, &QSlider::valueChanged, this, &AxesExtended::filterChanged); 56 | // function changed 57 | connect(ui->comboBox_Function, qOverload(&QComboBox::currentIndexChanged), 58 | this, &AxesExtended::functionIndexChanged); 59 | } 60 | 61 | AxesExtended::~AxesExtended() 62 | { 63 | delete ui; 64 | } 65 | 66 | void AxesExtended::retranslateUi() 67 | { 68 | ui->retranslateUi(this); 69 | } 70 | 71 | void AxesExtended::setI2CEnabled(bool isEnable) 72 | { 73 | ui->comboBox_I2cAddress->setEnabled(isEnable); 74 | } 75 | 76 | void AxesExtended::filterChanged(int filterLevel) 77 | { 78 | ui->label_Filter->setText(tr("Filter") + " " + m_filterList[filterLevel].guiName); 79 | } 80 | 81 | void AxesExtended::functionIndexChanged(int index) 82 | { 83 | if (index > 0) { 84 | ui->comboBox_AxisSource2->setEnabled(true); 85 | } else { 86 | ui->comboBox_AxisSource2->setEnabled(false); 87 | } 88 | } 89 | 90 | void AxesExtended::readFromConfig() 91 | { 92 | //ui->comboBox_I2cAddress->setCurrentIndex(Converter::EnumToIndex(axisCfg->i2c_address, m_i2c_enumIndex)); 93 | axis_config_t *axisCfg = &gEnv.pDeviceConfig->config.axis_config[m_axisNumber]; 94 | // I2C, sources, function 95 | ui->comboBox_I2cAddress->setCurrentIndex(Converter::EnumToIndex(axisCfg->i2c_address, m_i2c_enumIndex)); 96 | ui->comboBox_AxisSource2->setCurrentIndex(Converter::EnumToIndex(axisCfg->source_secondary, axesList())); 97 | ui->comboBox_Function->setCurrentIndex(Converter::EnumToIndex(axisCfg->function, m_function_enumIndex)); 98 | // chanel 99 | ui->spinBox_ChanelEncoder->setValue(axisCfg->channel); 100 | // buttons 101 | ui->comboBox_Button1->setCurrentIndex(Converter::EnumToIndex(axisCfg->button1_type, m_button_1_3_enumIndex)); 102 | ui->spinBox_Button1->setValue(axisCfg->button1 + 1); 103 | ui->comboBox_Button2->setCurrentIndex(Converter::EnumToIndex(axisCfg->button2_type, m_button_2_enumIndex)); 104 | ui->spinBox_Button2->setValue(axisCfg->button2 + 1); 105 | ui->comboBox_Button3->setCurrentIndex(Converter::EnumToIndex(axisCfg->button3_type, m_button_1_3_enumIndex)); 106 | ui->spinBox_Button3->setValue(axisCfg->button3 + 1); 107 | // divider, prescaler 108 | ui->spinBox_StepDiv->setValue(axisCfg->divider); 109 | ui->spinBox_Prescaler->setValue(axisCfg->prescaler); 110 | // resolution, offset 111 | ui->spinBox_Resolution->setValue(axisCfg->resolution + 1); 112 | ui->spinBox_Offset->setValue(axisCfg->offset_angle * 15); 113 | //deadband 114 | ui->checkBox_DynDeadband->setChecked(axisCfg->is_dynamic_deadband); 115 | ui->spinBox_Deadband->setValue(axisCfg->deadband_size); 116 | // filter 117 | ui->sliderH_Filter->setValue(axisCfg->filter); 118 | } 119 | 120 | void AxesExtended::writeToConfig() 121 | { 122 | axis_config_t *axisCfg = &gEnv.pDeviceConfig->config.axis_config[m_axisNumber]; 123 | // I2C, sources, function 124 | axisCfg->i2c_address = m_i2cPtrList[ui->comboBox_I2cAddress->currentIndex()].deviceEnumIndex; 125 | axisCfg->source_secondary = axesList()[ui->comboBox_AxisSource2->currentIndex()].deviceEnumIndex; 126 | axisCfg->function = m_functionList[ui->comboBox_Function->currentIndex()].deviceEnumIndex; 127 | // chanel 128 | axisCfg->channel = ui->spinBox_ChanelEncoder->value(); 129 | // buttons 130 | axisCfg->button1_type = m_button_1_3_list[ui->comboBox_Button1->currentIndex()].deviceEnumIndex; 131 | axisCfg->button1 = ui->spinBox_Button1->value() - 1; 132 | axisCfg->button2_type = m_button_2_list[ui->comboBox_Button2->currentIndex()].deviceEnumIndex; 133 | axisCfg->button2 = ui->spinBox_Button2->value() - 1; 134 | axisCfg->button3_type = m_button_1_3_list[ui->comboBox_Button3->currentIndex()].deviceEnumIndex; 135 | axisCfg->button3 = ui->spinBox_Button3->value() - 1; 136 | // divider, prescaler 137 | axisCfg->divider = ui->spinBox_StepDiv->value(); 138 | axisCfg->prescaler = ui->spinBox_Prescaler->value(); 139 | // resolution, offset 140 | axisCfg->resolution = ui->spinBox_Resolution->value() - 1; 141 | axisCfg->offset_angle = ui->spinBox_Offset->value() / 15; 142 | // deadband 143 | axisCfg->is_dynamic_deadband = ui->checkBox_DynDeadband->isChecked(); 144 | axisCfg->deadband_size = ui->spinBox_Deadband->value(); 145 | // filter 146 | axisCfg->filter = ui->sliderH_Filter->value(); 147 | } 148 | -------------------------------------------------------------------------------- /src/widgets/axes/axesextended.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESEXTENDED_H 2 | #define AXESEXTENDED_H 3 | 4 | #include 5 | 6 | #include "deviceconfig.h" 7 | #include "global.h" 8 | 9 | namespace Ui { 10 | class AxesExtended; 11 | } 12 | 13 | class AxesExtended : public QWidget 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit AxesExtended(int axisNumber, QWidget *parent = nullptr); 19 | ~AxesExtended(); 20 | 21 | void readFromConfig(); 22 | void writeToConfig(); 23 | 24 | void retranslateUi(); 25 | 26 | void setI2CEnabled(bool isEnable); 27 | 28 | private slots: 29 | void filterChanged(int filterLevel); 30 | void functionIndexChanged(int index); 31 | 32 | private: 33 | Ui::AxesExtended *ui; 34 | 35 | int m_axisNumber; 36 | QVector m_i2c_enumIndex; 37 | QVector m_function_enumIndex; 38 | QVector m_button_1_3_enumIndex; 39 | QVector m_button_2_enumIndex; 40 | 41 | enum 42 | { 43 | AS5600 = 0x36, //54 44 | ADS1115_00 = 0x48, //72 45 | ADS1115_01, 46 | ADS1115_10, 47 | ADS1115_11, 48 | }; 49 | 50 | const QVector m_i2cPtrList = // static? 51 | {{ 52 | {AS5600, "AS 5600"}, 53 | {ADS1115_00, "ADS 1115_00"}, 54 | {ADS1115_01, "ADS 1115_01"}, 55 | {ADS1115_10, "ADS 1115_10"}, 56 | {ADS1115_11, "ADS 1115_11"}, 57 | }}; 58 | 59 | const QVector m_functionList = // static? 60 | {{ 61 | {NO_FUNCTION, tr("None")}, 62 | {FUNCTION_PLUS, tr("Plus")}, 63 | {FUNCTION_MINUS, tr("Minus")}, 64 | {FUNCTION_EQUAL, tr("Equal")}, 65 | }}; 66 | 67 | const QVector m_button_1_3_list = // static? 68 | {{ 69 | {AXIS_BUTTON_FUNC_EN, tr("Function enable")}, 70 | {AXIS_BUTTON_PRESCALER_EN, tr("Prescale enable")}, 71 | {AXIS_BUTTON_CENTER, tr("Center")}, 72 | {AXIS_BUTTON_RESET, tr("Reset")}, 73 | {AXIS_BUTTON_DOWN, tr("Down")}, 74 | {AXIS_BUTTON_UP, tr("Up")}, 75 | }}; 76 | 77 | const QVector m_button_2_list = // static? 78 | {{ 79 | {AXIS_BUTTON_FUNC_EN, tr("Function enable")}, 80 | {AXIS_BUTTON_PRESCALER_EN, tr("Prescale enable")}, 81 | {AXIS_BUTTON_CENTER, tr("Center")}, 82 | {AXIS_BUTTON_RESET, tr("Reset")}, 83 | }}; 84 | 85 | const QVector m_filterList = // порядок обязан быть как в common_types.h!!!!!!!!!!! // static? 86 | {{ 87 | {FILTER_NO, tr("off")}, 88 | {FILTER_LEVEL_1, tr("level 1")}, 89 | {FILTER_LEVEL_2, tr("level 2")}, 90 | {FILTER_LEVEL_3, tr("level 3")}, 91 | {FILTER_LEVEL_4, tr("level 4")}, 92 | {FILTER_LEVEL_5, tr("level 5")}, 93 | {FILTER_LEVEL_6, tr("level 6")}, 94 | {FILTER_LEVEL_7, tr("level 7")}, 95 | }}; 96 | }; 97 | 98 | #endif // AXESEXTENDED_H 99 | -------------------------------------------------------------------------------- /src/widgets/axes/axestobuttonsconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "axestobuttonsconfig.h" 2 | #include "ui_axestobuttonsconfig.h" 3 | 4 | AxesToButtonsConfig::AxesToButtonsConfig(QWidget *parent) : 5 | QWidget(parent), 6 | ui(new Ui::AxesToButtonsConfig) 7 | { 8 | ui->setupUi(this); 9 | 10 | a2b_buttons_count_ = 0; 11 | ui->layoutV_AxesToButtons->setAlignment(Qt::AlignTop); 12 | 13 | // for (int i = 0; i < MAX_AXIS_NUM; ++i) 14 | // { 15 | // AxesToButtons* a2b = new AxesToButtons(this); 16 | // ui->layoutV_AxesToButtons->addWidget(a2b); 17 | // A2bAdrList.append(a2b); 18 | // connect(a2b, SIGNAL(a2bCountChanged(int, int)), 19 | // this, SLOT(a2bCountCalc(int, int))); 20 | // } 21 | } 22 | 23 | AxesToButtonsConfig::~AxesToButtonsConfig() 24 | { 25 | delete ui; 26 | } 27 | 28 | void AxesToButtonsConfig::RetranslateUi() 29 | { 30 | ui->retranslateUi(this); 31 | for (int i = 0; i < A2bAdrList.size(); ++i) { 32 | A2bAdrList[i]->RetranslateUi(); 33 | } 34 | } 35 | 36 | void AxesToButtonsConfig::a2bCountCalc(int count, int previous_count) 37 | { 38 | a2b_buttons_count_ += count - previous_count; 39 | emit a2bCountChanged(a2b_buttons_count_); 40 | } 41 | 42 | void AxesToButtonsConfig::ReadFromConfig() 43 | { 44 | for (int i = 0; i < A2bAdrList.size(); ++i) { 45 | A2bAdrList[i]->ReadFromConfig(); 46 | } 47 | } 48 | 49 | void AxesToButtonsConfig::WriteToConfig() 50 | { 51 | for (int i = 0; i < A2bAdrList.size(); ++i) { 52 | A2bAdrList[i]->WriteToConfig(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/widgets/axes/axestobuttonsslider.h: -------------------------------------------------------------------------------- 1 | #ifndef AXESTOBUTTONSSLIDER_H 2 | #define AXESTOBUTTONSSLIDER_H 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | class QLabel; 8 | QT_END_NAMESPACE 9 | //#include 10 | 11 | #include "deviceconfig.h" 12 | #include "global.h" 13 | 14 | #define MAX_A2B_BUTTONS 12 15 | 16 | namespace Ui { 17 | class AxesToButtonsSlider; 18 | } 19 | 20 | class AxesToButtonsSlider : public QWidget 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | explicit AxesToButtonsSlider(QWidget *parent = nullptr); 26 | ~AxesToButtonsSlider(); 27 | 28 | void setPointsCount(uint count); 29 | uint pointsCount() const; 30 | 31 | void setPointValue(uint value, uint pointNumber); 32 | uint pointValue(uint pointNumber) const; 33 | 34 | void setAxisOutputValue(int outValue, bool isEnable); 35 | 36 | protected: 37 | void mouseMoveEvent(QMouseEvent *event) override; 38 | void mousePressEvent(QMouseEvent *event) override; 39 | void mouseReleaseEvent(QMouseEvent *event) override; 40 | void paintEvent(QPaintEvent *event) override; 41 | void resizeEvent(QResizeEvent *) override; 42 | bool event(QEvent *event) override; 43 | 44 | private: 45 | Ui::AxesToButtonsSlider *ui; 46 | void drawPoint(const QPoint &pointPos, uint pointNumber); // QPoint &point_pos 47 | void movePointer(uint posX, uint pointNumber); 48 | uint calcPointValue(int currentPos) const; 49 | void pointsPositionReset(); 50 | //void setLableValue(int pointPos, uint pointNumber); 51 | 52 | float m_lineSpacing; 53 | 54 | float m_axisOutputValue; 55 | int m_axisOutputWidth; 56 | bool m_isOutEnabled; 57 | 58 | const QColor m_kAxisRectColor = QColor(160, 0, 0); 59 | const QColor m_kAxisRectColor_dis = QColor(160, 0, 0, 80); 60 | const QColor m_kPointRawActivColor = QColor(0, 170, 0); 61 | QColor m_axisRectColor; 62 | 63 | const int m_kHalfPointerWidth = 4; 64 | 65 | const QColor m_kPointerColor = QColor(1, 119, 215); 66 | const uint m_kMaxPointValue = 255; 67 | const int m_kOffset = 10; 68 | const int m_kRangeBetween = 13; // минимальное расстояние между ближайшими указателями 69 | const int m_kLabelWidth = 20; 70 | const int m_kMinHeight = 40; //45 71 | 72 | const int m_kPaddingTop = 7; 73 | const QPoint m_kPointer[5] = { 74 | QPoint(-m_kHalfPointerWidth, 2), // + padding_top_ 75 | QPoint(-m_kHalfPointerWidth, 12), 76 | QPoint(0, 20), 77 | QPoint(m_kHalfPointerWidth, 12), 78 | QPoint(m_kHalfPointerWidth, 2), 79 | }; 80 | 81 | uint m_pointsCount; 82 | 83 | QList m_labelPtrList; 84 | 85 | struct A2B_point // uint гемороя наделал 86 | { 87 | QPolygon polygon; 88 | QColor color; 89 | QLabel *text_label; 90 | uint posX; 91 | uint current_value; 92 | bool is_drag; 93 | }; 94 | QList m_pointPtrList; 95 | }; 96 | 97 | #endif // AXESTOBUTTONSSLIDER_H 98 | -------------------------------------------------------------------------------- /src/widgets/axes/axestobuttonsslider.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AxesToButtonsSlider 4 | 5 | 6 | 7 | 0 8 | 0 9 | 960 10 | 86 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 40 20 | 50 21 | 47 22 | 13 23 | 24 | 25 | 26 | TextLabel 27 | 28 | 29 | 30 | 31 | 32 | 110 33 | 50 34 | 47 35 | 13 36 | 37 | 38 | 39 | TextLabel 40 | 41 | 42 | 43 | 44 | 45 | 180 46 | 50 47 | 47 48 | 13 49 | 50 | 51 | 52 | TextLabel 53 | 54 | 55 | 56 | 57 | 58 | 250 59 | 50 60 | 47 61 | 13 62 | 63 | 64 | 65 | TextLabel 66 | 67 | 68 | 69 | 70 | 71 | 320 72 | 50 73 | 47 74 | 13 75 | 76 | 77 | 78 | TextLabel 79 | 80 | 81 | 82 | 83 | 84 | 380 85 | 50 86 | 47 87 | 13 88 | 89 | 90 | 91 | TextLabel 92 | 93 | 94 | 95 | 96 | 97 | 440 98 | 50 99 | 47 100 | 13 101 | 102 | 103 | 104 | TextLabel 105 | 106 | 107 | 108 | 109 | 110 | 500 111 | 50 112 | 47 113 | 13 114 | 115 | 116 | 117 | TextLabel 118 | 119 | 120 | 121 | 122 | 123 | 570 124 | 50 125 | 47 126 | 13 127 | 128 | 129 | 130 | TextLabel 131 | 132 | 133 | 134 | 135 | 136 | 640 137 | 50 138 | 47 139 | 13 140 | 141 | 142 | 143 | TextLabel 144 | 145 | 146 | 147 | 148 | 149 | 700 150 | 50 151 | 47 152 | 13 153 | 154 | 155 | 156 | TextLabel 157 | 158 | 159 | 160 | 161 | 162 | 760 163 | 50 164 | 47 165 | 13 166 | 167 | 168 | 169 | TextLabel 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /src/widgets/buttons/buttonconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef BUTTONCONFIG_H 2 | #define BUTTONCONFIG_H 3 | 4 | #include 5 | 6 | #include "buttonlogical.h" 7 | #include "buttonphysical.h" 8 | 9 | #include "common_defines.h" 10 | #include "common_types.h" 11 | 12 | #include "deviceconfig.h" 13 | #include "global.h" 14 | 15 | //#define DYNAMIC_CREATION 16 | #ifdef DYNAMIC_CREATION 17 | //#define DYNAMIC_CREATION_ALL 18 | #endif 19 | namespace Ui { 20 | class ButtonConfig; 21 | } 22 | 23 | class ButtonConfig : public QWidget 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | explicit ButtonConfig(QWidget *parent = nullptr); 29 | ~ButtonConfig(); 30 | 31 | void readFromConfig(); 32 | void writeToConfig(); 33 | void buttonStateChanged(); 34 | 35 | void retranslateUi(); 36 | 37 | signals: 38 | void encoderInputChanged(int ecoder_A, int ecoder_B); 39 | void logicalButtonsCreated(); 40 | 41 | public slots: 42 | void setUiOnOff(int value); 43 | 44 | private slots: 45 | void functionTypeChanged(button_type_t current, button_type_t previous, int buttonIndex); 46 | void setPhysicButton(int buttonIndex); 47 | void typeLimit(button_type_t current, button_type_t previous); 48 | 49 | #ifdef DYNAMIC_CREATION 50 | private slots: 51 | void logScrollValueChanged(int value); 52 | void createLogButtons(int count); 53 | protected: 54 | void resizeEvent(QResizeEvent *event) override; 55 | #endif 56 | 57 | void on_checkBox_AutoPhysBut_toggled(bool checked); 58 | 59 | private: 60 | Ui::ButtonConfig *ui; 61 | void physButtonsCreator(int count); 62 | QString m_defaultShiftStyle; 63 | 64 | int m_logicButtonInFocus; 65 | bool m_autoPhysButEnabled; 66 | 67 | bool m_isShifts_act; 68 | bool m_shift1_act; 69 | bool m_shift2_act; 70 | bool m_shift3_act; 71 | bool m_shift4_act; 72 | bool m_shift5_act; 73 | 74 | void logicaButtonsCreator(); 75 | 76 | QList m_logicButtonPtrList; 77 | QList m_PhysButtonPtrList; 78 | 79 | struct pinTypeLimit_t 80 | { 81 | button_type_t type; 82 | int maxCount; 83 | }; 84 | 85 | static const int m_typeLimCount = 2; 86 | const pinTypeLimit_t m_ButtonsTypeLimit[m_typeLimCount] = 87 | { 88 | {ENCODER_INPUT_A, 15}, 89 | {ENCODER_INPUT_B, 15}, 90 | }; 91 | }; 92 | 93 | #endif // BUTTONCONFIG_H 94 | -------------------------------------------------------------------------------- /src/widgets/buttons/buttonlogical.h: -------------------------------------------------------------------------------- 1 | #ifndef BUTTONLOGICAL_H 2 | #define BUTTONLOGICAL_H 3 | 4 | #include "common_types.h" 5 | #include 6 | 7 | #include "deviceconfig.h" 8 | #include "global.h" 9 | //#include 10 | 11 | #define TIMER_COUNT 4 // "NO timer" + count 12 | #define SHIFT_COUNT 6 13 | 14 | namespace Ui { 15 | class ButtonLogical; 16 | } 17 | 18 | class ButtonLogical : public QWidget 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit ButtonLogical(int buttonIndex, QWidget *parent = nullptr); 24 | ~ButtonLogical(); 25 | void readFromConfig(); 26 | void writeToConfig(); 27 | 28 | void initialization(); 29 | 30 | void setMaxPhysButtons(int maxPhysButtons); 31 | void setSpinBoxOnOff(int maxPhysButtons); 32 | 33 | void setButtonState(bool setState); 34 | 35 | void setPhysicButton(int buttonIndex); 36 | void setAutoPhysBut(bool enabled); 37 | int currentFocus() const; 38 | 39 | void disableButtonType(button_type_t type, bool disable); 40 | button_type_t currentButtonType(); 41 | 42 | void retranslateUi(); 43 | 44 | signals: 45 | void functionTypeChanged(button_type_t current, button_type_t previous, int buttonIndex); 46 | 47 | private slots: 48 | void editingOnOff(int value); 49 | void functionIndexChanged(int index); 50 | 51 | protected: 52 | bool eventFilter(QObject *obj, QEvent *event) override; 53 | 54 | private: 55 | Ui::ButtonLogical *ui; 56 | int m_functionPrevType; 57 | bool m_currentState; 58 | bool m_debugState; 59 | int m_buttonIndex; 60 | static int m_currentFocus; 61 | static bool m_autoPhysButEnabled; 62 | QElapsedTimer m_lastAct; 63 | 64 | QVector m_logicFunc_enumIndex; 65 | 66 | const deviceEnum_guiName_t m_timerList[TIMER_COUNT] = // order must be as in common_types.h!!!!!!!!!!! // static ? 67 | { 68 | {BUTTON_TIMER_OFF, tr("-")}, 69 | {BUTTON_TIMER_1, tr("Timer 1")}, 70 | {BUTTON_TIMER_2, tr("Timer 2")}, 71 | {BUTTON_TIMER_3, tr("Timer 3")}, 72 | }; 73 | 74 | const deviceEnum_guiName_t m_shiftList[SHIFT_COUNT] = // order must be as in common_types.h!!!!!!!!!!! // static ? 75 | { 76 | {0, tr("-")}, 77 | {1, tr("Shift 1")}, 78 | {2, tr("Shift 2")}, 79 | {3, tr("Shift 3")}, 80 | {4, tr("Shift 4")}, 81 | {5, tr("Shift 5")}, 82 | }; 83 | //static deviceEnum_guiName_t logical_function_list_[LOGICAL_FUNCTION_COUNT]; 84 | 85 | const QVector m_logicFunctionList = // any order // static ? 86 | {{ 87 | {BUTTON_NORMAL, tr("Button normal")}, 88 | {BUTTON_TOGGLE, tr("Button toggle")}, 89 | {TOGGLE_SWITCH, tr("Toggle switch ON/OFF")}, 90 | {TOGGLE_SWITCH_ON, tr("Toggle switch ON")}, 91 | {TOGGLE_SWITCH_OFF, tr("Toggle switch OFF")}, 92 | {POV1_UP, tr("POV1 Up")}, 93 | {POV1_RIGHT, tr("POV1 Right")}, 94 | {POV1_DOWN, tr("POV1 Down")}, 95 | {POV1_LEFT, tr("POV1 Left")}, 96 | {POV1_CENTER, tr("POV1 Center")}, 97 | {POV2_UP, tr("POV2 Up")}, 98 | {POV2_RIGHT, tr("POV2 Right")}, 99 | {POV2_DOWN, tr("POV2 Down")}, 100 | {POV2_LEFT, tr("POV2 Left")}, 101 | {POV2_CENTER, tr("POV2 Center")}, 102 | {POV3_UP, tr("POV3 Up")}, 103 | {POV3_RIGHT, tr("POV3 Right")}, 104 | {POV3_DOWN, tr("POV3 Down")}, 105 | {POV3_LEFT, tr("POV3 Left")}, 106 | {POV4_UP, tr("POV4 Up")}, 107 | {POV4_RIGHT, tr("POV4 Right")}, 108 | {POV4_DOWN, tr("POV4 Down")}, 109 | {POV4_LEFT, tr("POV4 Left")}, 110 | {ENCODER_INPUT_A, tr("Encoder A")}, 111 | {ENCODER_INPUT_B, tr("Encoder B")}, 112 | {RADIO_BUTTON1, tr("Radio button 1")}, 113 | {RADIO_BUTTON2, tr("Radio button 2")}, 114 | {RADIO_BUTTON3, tr("Radio button 3")}, 115 | {RADIO_BUTTON4, tr("Radio button 4")}, 116 | {SEQUENTIAL_TOGGLE, tr("Sequential toggle")}, 117 | {SEQUENTIAL_BUTTON, tr("Sequential button")}, 118 | }}; 119 | }; 120 | 121 | #endif // BUTTONLOGICAL_H 122 | -------------------------------------------------------------------------------- /src/widgets/buttons/buttonphysical.cpp: -------------------------------------------------------------------------------- 1 | #include "buttonphysical.h" 2 | #include "ui_buttonphysical.h" 3 | 4 | const QString ButtonPhysical::m_whiteStyleOff = QStringLiteral(R"( 5 | QLabel { 6 | border-radius: 13px; 7 | min-height: 26px; 8 | min-width: 26px; 9 | background-color: rgb(170, 60, 60); 10 | color: rgb(220, 221, 222); 11 | } 12 | )"); 13 | 14 | //background-color: rgb(170, 70, 40); // background-color: rgb(90, 0, 0); 15 | //border: 1px solid #4b4b4b; 16 | const QString ButtonPhysical::m_darkStyleOff = QStringLiteral(R"( 17 | QLabel { 18 | border-radius: 13px; 19 | min-height: 26px; 20 | min-width: 26px; 21 | background-color: rgb(90, 90, 90); 22 | color: rgb(220, 221, 222); 23 | } 24 | )"); 25 | 26 | const QString ButtonPhysical::m_styleOn = QStringLiteral(R"( 27 | QLabel { 28 | border-radius: 13px; 29 | min-height: 26px; 30 | min-width: 26px; 31 | background-color: rgb(0, 128, 0); 32 | color: rgb(220, 221, 222); 33 | } 34 | )"); 35 | 36 | ButtonPhysical::ButtonPhysical(int buttonNumber, QWidget *parent) 37 | : QWidget(parent) 38 | , ui(new Ui::ButtonPhysical) 39 | { 40 | ui->setupUi(this); 41 | m_currentState = false; 42 | m_buttonIndex = buttonNumber; 43 | ui->label_PhysicalButton->setNum(m_buttonIndex + 1); 44 | 45 | updateStyleColor(); 46 | installEventFilter(this); 47 | } 48 | 49 | ButtonPhysical::~ButtonPhysical() 50 | { 51 | delete ui; 52 | } 53 | 54 | void ButtonPhysical::setButtonState(bool state) 55 | { 56 | if (state != m_currentState) { 57 | if (state) { 58 | ui->label_PhysicalButton->setStyleSheet(m_styleOn); 59 | emit physButtonPressed(m_buttonIndex); 60 | m_lastAct.start(); 61 | m_currentState = state; 62 | } else { 63 | // sometimes state dont have time to render. e.g. encoder press time 10ms and monitor refresh time 17ms(60fps) 64 | if (m_lastAct.hasExpired(30)) { 65 | updateStyleColor(); 66 | m_currentState = state; 67 | } 68 | } 69 | } 70 | } 71 | 72 | void ButtonPhysical::updateStyleColor() 73 | { 74 | if (QApplication::palette().color(QWidget::backgroundRole()).value() < 100) { 75 | ui->label_PhysicalButton->setStyleSheet(m_darkStyleOff); 76 | } else { 77 | ui->label_PhysicalButton->setStyleSheet(m_whiteStyleOff); 78 | } 79 | update(); 80 | } 81 | 82 | bool ButtonPhysical::eventFilter(QObject *object, QEvent *event) 83 | { 84 | Q_UNUSED(object) 85 | if (event->type() == QEvent::PaletteChange) { 86 | updateStyleColor(); 87 | return false; 88 | } 89 | return false; 90 | } 91 | -------------------------------------------------------------------------------- /src/widgets/buttons/buttonphysical.h: -------------------------------------------------------------------------------- 1 | #ifndef BUTTONPHYSICAL_H 2 | #define BUTTONPHYSICAL_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Ui { 8 | class ButtonPhysical; 9 | } 10 | 11 | class ButtonPhysical : public QWidget 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit ButtonPhysical(int buttonNumber, QWidget *parent = nullptr); 17 | ~ButtonPhysical(); 18 | void setButtonState(bool state); 19 | 20 | signals: 21 | void physButtonPressed(int number); 22 | 23 | protected: 24 | bool eventFilter(QObject *object, QEvent *event) override; 25 | 26 | private: 27 | Ui::ButtonPhysical *ui; 28 | int m_buttonIndex; 29 | bool m_currentState; 30 | 31 | static const QString m_whiteStyleOff; 32 | static const QString m_darkStyleOff; 33 | static const QString m_styleOn; 34 | void updateStyleColor(); 35 | 36 | QElapsedTimer m_lastAct; 37 | }; 38 | 39 | #endif // BUTTONPHYSICAL_H 40 | -------------------------------------------------------------------------------- /src/widgets/buttons/buttonphysical.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ButtonPhysical 4 | 5 | 6 | 7 | 0 8 | 0 9 | 28 10 | 28 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 28 22 | 28 23 | 24 | 25 | 26 | 27 | 999 28 | 999 29 | 30 | 31 | 32 | Form 33 | 34 | 35 | 36 | 0 37 | 38 | 39 | 0 40 | 41 | 42 | 0 43 | 44 | 45 | 0 46 | 47 | 48 | 0 49 | 50 | 51 | 52 | 53 | 54 | 0 55 | 0 56 | 57 | 58 | 59 | 60 | 0 61 | 0 62 | 63 | 64 | 65 | 66 | 67 | 68 | 1 69 | 70 | 71 | Qt::AlignCenter 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/widgets/centered_cbox.cpp: -------------------------------------------------------------------------------- 1 | #include "centered_cbox.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | CenteredCBox::CenteredCBox(QWidget *parent) 9 | : QComboBox(parent) 10 | { 11 | m_arrowWidth = 0; 12 | } 13 | 14 | // setting text approximately centered 15 | void CenteredCBox::paintEvent(QPaintEvent *event) 16 | { 17 | Q_UNUSED(event) 18 | 19 | QStylePainter painter(this); 20 | painter.setPen(palette().color(QPalette::Text)); 21 | 22 | QStyleOptionComboBox option; 23 | initStyleOption(&option); 24 | painter.drawComplexControl(QStyle::CC_ComboBox, option); 25 | 26 | option.direction = Qt::LeftToRight; 27 | 28 | if (style()) { 29 | QRect rect = style()->subControlRect(QStyle::CC_ComboBox, &option, QStyle::SC_ComboBoxArrow, this); 30 | m_arrowWidth = rect.width(); 31 | } 32 | 33 | QFontMetricsF font_metric(property("font").value()); 34 | // походу width измеряется по центрам букв и она короче, чем есть на самом 35 | // деле. умножаю на 1.1 36 | qreal font_width = font_metric.horizontalAdvance(option.currentText);// * 1.1f; 37 | font_metric.averageCharWidth(); 38 | 39 | // если сделать по центру всего комбобокса, то будет ощущение, что слева 40 | // больше свободного места из-за стрелки справа. Если по центру не считая 41 | // стрелки, то тоже выглядит криво arrow_width_/3 тут я сделал промежуточный 42 | // вариант 43 | int offset = option.rect.center().x() - m_arrowWidth / 3.2f - font_width / 2; 44 | 45 | // если длина комбобокса меньше длины текста, сдвиг слева уменьшается 46 | if (offset + font_width*1.1f > option.rect.right() - m_arrowWidth) { 47 | offset -= ((offset + font_width*1.1f) - (option.rect.right() - m_arrowWidth)); 48 | if (offset < 0) 49 | offset = 0; 50 | } 51 | option.rect.setLeft(offset); 52 | 53 | painter.drawControl(QStyle::CE_ComboBoxLabel, option); 54 | } 55 | -------------------------------------------------------------------------------- /src/widgets/centered_cbox.h: -------------------------------------------------------------------------------- 1 | #ifndef CENTEREDCBOX_H 2 | #define CENTEREDCBOX_H 3 | 4 | #include 5 | 6 | class CenteredCBox : public QComboBox 7 | { 8 | //Q_OBJECT 9 | public: 10 | explicit CenteredCBox(QWidget *parent = nullptr); //, int arrow_width = 18 11 | 12 | protected: 13 | void paintEvent(QPaintEvent *event) override; 14 | 15 | private: 16 | int m_arrowWidth; 17 | }; 18 | 19 | #endif // CENTEREDCBOX_H 20 | -------------------------------------------------------------------------------- /src/widgets/debugwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "debugwindow.h" 2 | #include "ui_debugwindow.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "global.h" 12 | #include 13 | #include 14 | DebugWindow::DebugWindow(QWidget *parent) 15 | : QWidget(parent) 16 | , ui(new Ui::DebugWindow) 17 | { 18 | ui->setupUi(this); 19 | 20 | m_packetsCount = 0; 21 | m_writeToFile = false; 22 | 23 | QString docLoc = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); 24 | if (docLoc.isEmpty() == false) { 25 | docLoc+= "/FreeJoy/"; 26 | } 27 | QSettings s(docLoc + "FreeJoySettings.conf", QSettings::IniFormat); 28 | 29 | s.beginGroup("OtherSettings"); 30 | ui->checkBox_WriteLog->setChecked(s.value("LogEnabled", "false").toBool()); 31 | s.endGroup(); 32 | } 33 | 34 | DebugWindow::~DebugWindow() 35 | { 36 | delete ui; 37 | } 38 | 39 | void DebugWindow::retranslateUi() 40 | { 41 | ui->retranslateUi(this); 42 | } 43 | 44 | void DebugWindow::devicePacketReceived() 45 | { 46 | // if (isVisible()){ 47 | // } 48 | static int count = 0; 49 | static QElapsedTimer packet_timer; 50 | 51 | m_packetsCount++; 52 | if (packet_timer.hasExpired(100)) { 53 | ui->label_PacketsCount->setNum(m_packetsCount); 54 | packet_timer.start(); 55 | } 56 | 57 | if (m_timer.hasExpired(5000) && m_timer.isValid()) { 58 | ui->label_PacketsSpeed->setText(QString::number((double(m_timer.restart()) / double(count)), 'f', 3) 59 | + tr(" ms")); 60 | count = 0; 61 | } else if (m_timer.isValid() == false) { // валид-инвалид для правильного отображения при подключении-отключении девайса 62 | m_timer.start(); 63 | } 64 | 65 | count++; 66 | } 67 | 68 | void DebugWindow::resetPacketsCount() 69 | { 70 | m_packetsCount = 0; 71 | ui->label_PacketsCount->setNum(m_packetsCount); 72 | 73 | m_timer.invalidate(); 74 | ui->label_PacketsSpeed->setText(tr("0 ms")); 75 | 76 | buttonLogReset(); 77 | } 78 | 79 | void DebugWindow::printMsg(const QString &msg) 80 | { 81 | QString log(QDateTime::currentDateTime().toString("hh:mm:ss.zzz") + ": " + msg + '\n'); 82 | ui->textBrowser_DebugMsg->insertPlainText(log); // append? 83 | ui->textBrowser_DebugMsg->moveCursor(QTextCursor::End); // с plainTextEdit криво пашет 84 | 85 | if (m_writeToFile) { 86 | QString date(QDateTime::currentDateTime().toString("YYYY-MM-DDTHH:MM")); 87 | QFile file(gEnv.pAppSettings->fileName().remove("FreeJoySettings.conf") + "log/" + "FJLog" + date + ".txt"); 88 | if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) { 89 | qWarning() << "cant open file"; 90 | return; 91 | } 92 | QTextStream out(&file); 93 | out << log; 94 | } 95 | } 96 | 97 | void DebugWindow::logicalButtonState(int buttonNumber, bool state) 98 | { 99 | if (state) { 100 | ui->textBrowser_ButtonsPressLog->insertPlainText( 101 | QDateTime::currentDateTime().toString("hh:mm:ss.zzz") + ": " + tr("Logical button ") 102 | + QString::number(buttonNumber) + tr(" pressed") + '\n'); 103 | 104 | ui->textBrowser_ButtonsPressLog->moveCursor(QTextCursor::End); 105 | } else { 106 | ui->textBrowser_ButtonsUnpressLog->insertPlainText( 107 | QDateTime::currentDateTime().toString("hh:mm:ss.zzz") + ": " + tr("Logical button ") 108 | + QString::number(buttonNumber) + tr(" unpressed") + '\n'); 109 | 110 | ui->textBrowser_ButtonsUnpressLog->moveCursor(QTextCursor::End); 111 | } 112 | } 113 | 114 | void DebugWindow::buttonLogReset() 115 | { 116 | ui->textBrowser_ButtonsPressLog->clear(); 117 | ui->textBrowser_ButtonsUnpressLog->clear(); // need to improve 118 | } 119 | 120 | void DebugWindow::on_checkBox_WriteLog_clicked(bool checked) 121 | { 122 | gEnv.pAppSettings->beginGroup("OtherSettings"); 123 | gEnv.pAppSettings->setValue("LogEnabled", checked); 124 | gEnv.pAppSettings->endGroup(); 125 | 126 | m_writeToFile = checked; 127 | } 128 | -------------------------------------------------------------------------------- /src/widgets/debugwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUGWINDOW_H 2 | #define DEBUGWINDOW_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Ui { 8 | class DebugWindow; 9 | } 10 | 11 | class DebugWindow : public QWidget 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit DebugWindow(QWidget *parent = nullptr); 17 | ~DebugWindow(); 18 | 19 | void retranslateUi(); 20 | 21 | void devicePacketReceived(); 22 | void resetPacketsCount(); 23 | 24 | void logicalButtonState(int buttonNumber, bool state); 25 | 26 | Q_INVOKABLE // для мультипотока, хз правильно ли, но работает. CustomMessageHandler in main 27 | void printMsg(const QString &msg); // не уверен насчёт ссылки, мб надо копию получать с мультипотоком 28 | 29 | private slots: 30 | void on_checkBox_WriteLog_clicked(bool checked); 31 | 32 | private: 33 | Ui::DebugWindow *ui; 34 | void buttonLogReset(); 35 | 36 | int m_packetsCount; 37 | QElapsedTimer m_timer; 38 | bool m_writeToFile; 39 | }; 40 | 41 | #endif // DEBUGWINDOW_H 42 | -------------------------------------------------------------------------------- /src/widgets/debugwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DebugWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1037 10 | 98 11 | 12 | 13 | 14 | Debug 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 31 | 32 | Debug packets speed within 5 seconds 33 | 34 | 35 | Packets speed: 36 | 37 | 38 | Qt::AlignBottom|Qt::AlignHCenter 39 | 40 | 41 | 42 | 43 | 44 | 45 | Application log 46 | 47 | 48 | 49 | 6 50 | 51 | 52 | 6 53 | 54 | 55 | 6 56 | 57 | 58 | 6 59 | 60 | 61 | 62 | 63 | 64 | 0 65 | 0 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 0 77 | 78 | 79 | Qt::AlignHCenter|Qt::AlignTop 80 | 81 | 82 | 83 | 84 | 85 | 86 | Write log to file 87 | 88 | 89 | 90 | 91 | 92 | 93 | within 5 seconds 94 | 95 | 96 | 0 ms 97 | 98 | 99 | Qt::AlignHCenter|Qt::AlignTop 100 | 101 | 102 | 103 | 104 | 105 | 106 | Packets received: 107 | 108 | 109 | Qt::AlignBottom|Qt::AlignHCenter 110 | 111 | 112 | 113 | 114 | 115 | 116 | Buttons log 117 | 118 | 119 | 120 | 6 121 | 122 | 123 | 6 124 | 125 | 126 | 6 127 | 128 | 129 | 6 130 | 131 | 132 | 133 | 134 | 135 | 0 136 | 0 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /src/widgets/encoders/encoders.cpp: -------------------------------------------------------------------------------- 1 | #include "encoders.h" 2 | #include "ui_encoders.h" 3 | 4 | Encoders::Encoders(int encodersNumber, QWidget *parent) 5 | : QWidget(parent) 6 | , ui(new Ui::Encoders) 7 | { 8 | ui->setupUi(this); 9 | m_input_A = 0; 10 | m_input_B = 0; 11 | m_notDefined = tr("Not defined"); 12 | 13 | m_encodersNumber = encodersNumber + 1; // fast encoder index 0 14 | ui->label_EncoderIndex->setNum(m_encodersNumber); 15 | 16 | for (int i = 0; i < ENCODER_TYPE_COUNT; ++i) { 17 | ui->comboBox_EncoderType->addItem(m_encoderTypeList[i].guiName); 18 | ui->label_ButtonNumberA->setText(m_notDefined); 19 | ui->label_ButtonNumberB->setText(m_notDefined); 20 | } 21 | } 22 | 23 | Encoders::~Encoders() 24 | { 25 | delete ui; 26 | } 27 | 28 | void Encoders::retranslateUi() 29 | { 30 | ui->retranslateUi(this); 31 | } 32 | 33 | int Encoders::inputA() const 34 | { 35 | return m_input_A; 36 | } 37 | 38 | int Encoders::inputB() const 39 | { 40 | return m_input_B; 41 | } 42 | 43 | void Encoders::setInputA(int input_A) 44 | { 45 | if (input_A != 0) { 46 | m_input_A = input_A; 47 | QString name_template(tr("Button № %1")); 48 | ui->label_ButtonNumberA->setText(name_template.arg(m_input_A)); 49 | } else { 50 | m_input_A = 0; 51 | ui->label_ButtonNumberA->setText(m_notDefined); 52 | } 53 | setUiOnOff(); 54 | } 55 | 56 | void Encoders::setInputB(int input_B) 57 | { 58 | if (input_B != 0) { 59 | m_input_B = input_B; 60 | QString name_template(tr("Button № %1")); 61 | ui->label_ButtonNumberB->setText(name_template.arg(m_input_B)); 62 | } else { 63 | m_input_B = 0; 64 | ui->label_ButtonNumberB->setText(m_notDefined); 65 | } 66 | setUiOnOff(); 67 | } 68 | 69 | void Encoders::setUiOnOff() 70 | { 71 | if (m_input_A > 0 && m_input_B > 0) { 72 | for (auto &&child : this->findChildren()) { 73 | child->setEnabled(true); 74 | } 75 | } else { 76 | for (auto &&child : this->findChildren()) { 77 | child->setEnabled(false); 78 | } 79 | } 80 | } 81 | 82 | void Encoders::readFromConfig() 83 | { 84 | ui->comboBox_EncoderType->setCurrentIndex(gEnv.pDeviceConfig->config.encoders[m_encodersNumber]); 85 | } 86 | 87 | void Encoders::writeToConfig() 88 | { 89 | gEnv.pDeviceConfig->config.encoders[m_encodersNumber] = ui->comboBox_EncoderType->currentIndex(); 90 | } 91 | -------------------------------------------------------------------------------- /src/widgets/encoders/encoders.h: -------------------------------------------------------------------------------- 1 | #ifndef ENCODERS_H 2 | #define ENCODERS_H 3 | 4 | #include 5 | 6 | #include "deviceconfig.h" 7 | #include "global.h" 8 | 9 | #define ENCODER_TYPE_COUNT 3 10 | namespace Ui { 11 | class Encoders; 12 | } 13 | 14 | class Encoders : public QWidget 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit Encoders(int encodersNumber, QWidget *parent = nullptr); 20 | ~Encoders(); 21 | 22 | void readFromConfig(); 23 | void writeToConfig(); 24 | 25 | void retranslateUi(); 26 | 27 | int inputA() const; 28 | int inputB() const; 29 | 30 | void setInputA(int); 31 | void setInputB(int); 32 | 33 | private: 34 | Ui::Encoders *ui; 35 | void setUiOnOff(); 36 | 37 | int m_encodersNumber; 38 | int m_input_A; 39 | int m_input_B; 40 | QString m_notDefined; 41 | 42 | const deviceEnum_guiName_t m_encoderTypeList[ENCODER_TYPE_COUNT] = // порядов обязан быть как в common_types.h!!!!!!!!!!! 43 | { 44 | {ENCODER_CONF_1x, tr("Encoder 1x")}, 45 | {ENCODER_CONF_2x, tr("Encoder 2x")}, 46 | {ENCODER_CONF_4x, tr("Encoder 4x")}, 47 | }; 48 | }; 49 | 50 | #endif // ENCODERS_H 51 | -------------------------------------------------------------------------------- /src/widgets/encoders/encoders.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Encoders 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1062 10 | 90 11 | 12 | 13 | 14 | 15 | 0 16 | 90 17 | 18 | 19 | 20 | Form 21 | 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 0 31 | 32 | 33 | 0 34 | 35 | 36 | 6 37 | 38 | 39 | 15 40 | 41 | 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 0 49 | 0 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | false 58 | 59 | 60 | Not defined 61 | 62 | 63 | Qt::AlignCenter 64 | 65 | 66 | 67 | 68 | 69 | 70 | false 71 | 72 | 73 | Encoder type 74 | 75 | 76 | Qt::AlignCenter 77 | 78 | 79 | 80 | 81 | 82 | 83 | false 84 | 85 | 86 | Input A 87 | 88 | 89 | Qt::AlignCenter 90 | 91 | 92 | 93 | 94 | 95 | 96 | false 97 | 98 | 99 | Not defined 100 | 101 | 102 | Qt::AlignCenter 103 | 104 | 105 | 106 | 107 | 108 | 109 | Qt::Horizontal 110 | 111 | 112 | 113 | 40 114 | 20 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | false 123 | 124 | 125 | Input B 126 | 127 | 128 | Qt::AlignCenter 129 | 130 | 131 | 132 | 133 | 134 | 135 | false 136 | 137 | 138 | 1 139 | 140 | 141 | Qt::AlignCenter 142 | 143 | 144 | 145 | 146 | 147 | 148 | QFrame::Sunken 149 | 150 | 151 | Qt::Horizontal 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | CenteredCBox 160 | QComboBox 161 |
centered_cbox.h
162 |
163 |
164 | 165 | 166 |
167 | -------------------------------------------------------------------------------- /src/widgets/encoders/encodersconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef ENCODERSCONFIG_H 2 | #define ENCODERSCONFIG_H 3 | 4 | #include 5 | 6 | #include "deviceconfig.h" 7 | #include "encoders.h" 8 | #include "global.h" 9 | 10 | namespace Ui { 11 | class EncodersConfig; 12 | } 13 | 14 | class EncodersConfig : public QWidget 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit EncodersConfig(QWidget *parent = nullptr); 20 | ~EncodersConfig(); 21 | 22 | void readFromConfig(); 23 | void writeToConfig(); 24 | 25 | void retranslateUi(); 26 | 27 | public slots: 28 | void encoderInputChanged(int encoder_A, int encoder_B); 29 | void fastEncoderSelected(const QString &pinGuiName, bool isSelected); 30 | 31 | private: 32 | Ui::EncodersConfig *ui; 33 | void setUiOnOff(); 34 | 35 | QList m_encodersPtrList; 36 | int m_encodersInput_A_count; 37 | int m_encodersInput_B_count; 38 | QString m_notDefined; 39 | 40 | int m_fastEncoderInput_A; 41 | int m_fastEncoderInput_B; 42 | 43 | const deviceEnum_guiName_t m_fastEncoderTypeList[ENCODER_TYPE_COUNT] = // порядов обязан быть как в common_types.h!!!!!!!!!!! 44 | { 45 | {ENCODER_CONF_1x, tr("Encoder 1x")}, 46 | {ENCODER_CONF_2x, tr("Encoder 2x")}, 47 | {ENCODER_CONF_4x, tr("Encoder 4x")}, 48 | }; 49 | }; 50 | 51 | #endif // ENCODERSCONFIG_H 52 | -------------------------------------------------------------------------------- /src/widgets/infolabel.cpp: -------------------------------------------------------------------------------- 1 | #include "infolabel.h" 2 | 3 | InfoLabel::InfoLabel(QWidget *parent) 4 | : QLabel(parent) 5 | { 6 | setMaximumSize(12, 12); 7 | setScaledContents(false); 8 | setPixmap(QPixmap(":/Images/info_icon.png")); 9 | } 10 | 11 | void InfoLabel::setPixmap(const QPixmap &p) 12 | { 13 | pix = p; 14 | QLabel::setPixmap(scaledPixmap()); 15 | } 16 | 17 | int InfoLabel::heightForWidth(int width) const 18 | { 19 | return pix.isNull() ? height() : ((qreal)pix.height()*width)/pix.width(); 20 | } 21 | 22 | QSize InfoLabel::sizeHint() const 23 | { 24 | int w = width(); 25 | return QSize(w, heightForWidth(w)); 26 | } 27 | 28 | QPixmap InfoLabel::scaledPixmap() const 29 | { 30 | return pix.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); 31 | } 32 | 33 | void InfoLabel::resizeEvent(QResizeEvent *event) 34 | { 35 | Q_UNUSED(event) 36 | if(!pix.isNull()) { 37 | QLabel::setPixmap(scaledPixmap()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/widgets/infolabel.h: -------------------------------------------------------------------------------- 1 | #ifndef INFOLABEL_H 2 | #define INFOLABEL_H 3 | 4 | #include 5 | #include 6 | 7 | class InfoLabel : public QLabel 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit InfoLabel(QWidget *parent = nullptr); 12 | virtual int heightForWidth(int width) const; 13 | virtual QSize sizeHint() const; 14 | QPixmap scaledPixmap() const; 15 | 16 | public slots: 17 | void setPixmap(const QPixmap &p); 18 | void resizeEvent(QResizeEvent *event); 19 | 20 | private: 21 | QPixmap pix; 22 | }; 23 | 24 | 25 | //! instant tooltip for InfoLabel 26 | class InfoProxyStyle : public QProxyStyle 27 | { 28 | public: 29 | using QProxyStyle::QProxyStyle; 30 | 31 | int styleHint(StyleHint hint, const QStyleOption* option = nullptr, 32 | const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override 33 | { 34 | if (hint == QStyle::SH_ToolTip_WakeUpDelay && widget && widget->inherits(InfoLabel::staticMetaObject.className())) 35 | { 36 | return 0; 37 | } 38 | 39 | return QProxyStyle::styleHint(hint, option, widget, returnData); 40 | } 41 | }; 42 | 43 | #endif // INFOLABEL_H 44 | -------------------------------------------------------------------------------- /src/widgets/led/led.cpp: -------------------------------------------------------------------------------- 1 | #include "led.h" 2 | #include "ui_led.h" 3 | 4 | LED::LED(int ledNumber, QWidget *parent) 5 | : QWidget(parent) 6 | , ui(new Ui::LED) 7 | { 8 | ui->setupUi(this); 9 | m_ledNumber = ledNumber; 10 | ui->label_LEDNumber->setNum(ledNumber + 1); 11 | 12 | for (int i = 0; i < LED_FUNCTION_COUNT; ++i) { 13 | ui->comboBox_Function->addItem(m_ledList[i].guiName); 14 | } 15 | } 16 | 17 | LED::~LED() 18 | { 19 | delete ui; 20 | } 21 | 22 | void LED::retranslateUi() 23 | { 24 | ui->retranslateUi(this); 25 | } 26 | 27 | int LED::currentButtonSelected() const 28 | { 29 | return ui->spinBox_InputNumber->value() - 1; 30 | } 31 | 32 | void LED::setLedState(bool state) 33 | { 34 | static QString default_style; 35 | 36 | if (state != m_currentState) { 37 | if (state) { 38 | default_style = ui->label_LEDNumber->styleSheet(); 39 | ui->label_LEDNumber->setStyleSheet(default_style + QStringLiteral("background-color: rgb(0, 128, 0);")); 40 | } else { 41 | ui->label_LEDNumber->setStyleSheet(default_style); 42 | } 43 | m_currentState = state; 44 | } 45 | } 46 | 47 | void LED::readFromConfig() 48 | { 49 | ui->spinBox_InputNumber->setValue(gEnv.pDeviceConfig->config.leds[m_ledNumber].input_num + 1); 50 | ui->comboBox_Function->setCurrentIndex(gEnv.pDeviceConfig->config.leds[m_ledNumber].type); 51 | } 52 | 53 | void LED::writeToConfig() 54 | { 55 | gEnv.pDeviceConfig->config.leds[m_ledNumber].input_num = ui->spinBox_InputNumber->value() - 1; 56 | gEnv.pDeviceConfig->config.leds[m_ledNumber].type = ui->comboBox_Function->currentIndex(); 57 | } 58 | -------------------------------------------------------------------------------- /src/widgets/led/led.h: -------------------------------------------------------------------------------- 1 | #ifndef LED_H 2 | #define LED_H 3 | 4 | #include 5 | 6 | #include "deviceconfig.h" 7 | #include "global.h" 8 | 9 | #define LED_FUNCTION_COUNT 2 10 | namespace Ui { 11 | class LED; 12 | } 13 | 14 | class LED : public QWidget 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit LED(int ledNumber, QWidget *parent = nullptr); 20 | ~LED(); 21 | 22 | int currentButtonSelected() const; 23 | 24 | void setLedState(bool state); 25 | 26 | void readFromConfig(); 27 | void writeToConfig(); 28 | 29 | void retranslateUi(); 30 | 31 | private: 32 | Ui::LED *ui; 33 | int m_ledNumber; 34 | 35 | bool m_currentState; 36 | 37 | const deviceEnum_guiName_t m_ledList[LED_FUNCTION_COUNT] = // порядов обязан быть как в common_types.h!!!!!!!!!!! 38 | { 39 | {LED_NORMAL, tr("Normal")}, 40 | {LED_INVERTED, tr("Inverted")}, 41 | }; 42 | }; 43 | 44 | #endif // LED_H 45 | -------------------------------------------------------------------------------- /src/widgets/led/led.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LED 4 | 5 | 6 | 7 | 0 8 | 0 9 | 580 10 | 45 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | 35 | QFrame::Box 36 | 37 | 38 | QFrame::Sunken 39 | 40 | 41 | 42 | 77 43 | 44 | 45 | 46 | 47 | 1 48 | 49 | 50 | Qt::AlignCenter 51 | 52 | 53 | 54 | 55 | 56 | 57 | Qt::AlignCenter 58 | 59 | 60 | QAbstractSpinBox::CorrectToNearestValue 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | CenteredCBox 75 | QComboBox 76 |
centered_cbox.h
77 |
78 |
79 | 80 | 81 |
82 | -------------------------------------------------------------------------------- /src/widgets/led/ledconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "ledconfig.h" 2 | #include "ui_ledconfig.h" 3 | 4 | //#include 5 | #include "axes.h" 6 | #include "common_types.h" 7 | #include "deviceconfig.h" 8 | #include "global.h" 9 | 10 | #include 11 | LedConfig::LedConfig(QWidget *parent) 12 | : QWidget(parent) 13 | , ui(new Ui::LedConfig) 14 | { 15 | ui->setupUi(this); 16 | ui->layoutV_LED->setAlignment(Qt::AlignTop); 17 | 18 | // LEDs spawn and hide 19 | for (int i = 0; i < MAX_LEDS_NUM; i++) { 20 | LED *led = new LED(i, this); 21 | ui->layoutV_LED->addWidget(led); 22 | m_ledPtrList.append(led); 23 | led->hide(); 24 | } 25 | for (int i = 0; i < MAX_AXIS_NUM; ++i) { 26 | ui->comboBox_axisConPA8->addItem(axesList()[i].guiName); 27 | ui->comboBox_axisConPB0->addItem(axesList()[i].guiName); 28 | ui->comboBox_axisConPB1->addItem(axesList()[i].guiName); 29 | ui->comboBox_axisConPB4->addItem(axesList()[i].guiName); 30 | } 31 | } 32 | 33 | LedConfig::~LedConfig() 34 | { 35 | delete ui; 36 | } 37 | 38 | void LedConfig::retranslateUi() 39 | { 40 | ui->retranslateUi(this); 41 | for (int i = 0; i < m_ledPtrList.size(); ++i) { 42 | m_ledPtrList[i]->retranslateUi(); 43 | } 44 | } 45 | 46 | void LedConfig::spawnLeds(int ledCount) 47 | { 48 | if (ledCount > MAX_LEDS_NUM) return; 49 | 50 | for (int i = 0; i < MAX_LEDS_NUM; i++) // или проверка на скрытие и break; ? 51 | { 52 | m_ledPtrList[i]->hide(); 53 | } 54 | for (int i = 0; i < ledCount; i++) { 55 | m_ledPtrList[i]->show(); 56 | } 57 | } 58 | 59 | void LedConfig::setLedsState() 60 | { 61 | for (int i = 0; gEnv.pDeviceConfig->config.leds[i].input_num > -1; ++i) // можно улучшить 62 | { 63 | if (i >= m_ledPtrList.size()) { 64 | break; 65 | } 66 | if (m_ledPtrList[i]->currentButtonSelected() == gEnv.pDeviceConfig->config.leds[i].input_num) { 67 | // logical buttons state 68 | int index = gEnv.pDeviceConfig->config.leds[i].input_num / 8; 69 | int bit = gEnv.pDeviceConfig->config.leds[i].input_num - index * 8; 70 | 71 | if ((gEnv.pDeviceConfig->paramsReport.log_button_data[index] & (1 << (bit & 0x07)))) { 72 | m_ledPtrList[i]->setLedState(true); 73 | } else if ((gEnv.pDeviceConfig->paramsReport.log_button_data[index] & (1 << (bit & 0x07))) == false) { 74 | m_ledPtrList[i]->setLedState(false); 75 | } 76 | } 77 | } 78 | } 79 | 80 | void LedConfig::readFromConfig() 81 | { 82 | led_pwm_config_t *pwm = gEnv.pDeviceConfig->config.led_pwm_config; 83 | ui->spinBox_LedPA8->setValue(pwm[0].duty_cycle); 84 | ui->spinBox_LedPB0->setValue(pwm[1].duty_cycle); 85 | ui->spinBox_LedPB1->setValue(pwm[2].duty_cycle); 86 | ui->spinBox_LedPB4->setValue(pwm[3].duty_cycle); 87 | 88 | ui->checkBox_connectedPA8->setChecked(pwm[0].is_axis); 89 | ui->checkBox_connectedPB0->setChecked(pwm[1].is_axis); 90 | ui->checkBox_connectedPB1->setChecked(pwm[2].is_axis); 91 | ui->checkBox_connectedPB4->setChecked(pwm[3].is_axis); 92 | 93 | ui->comboBox_axisConPA8->setCurrentIndex(pwm[0].axis_num); 94 | ui->comboBox_axisConPB0->setCurrentIndex(pwm[1].axis_num); 95 | ui->comboBox_axisConPB1->setCurrentIndex(pwm[2].axis_num); 96 | ui->comboBox_axisConPB4->setCurrentIndex(pwm[3].axis_num); 97 | 98 | for (int i = 0; i < MAX_LEDS_NUM; ++i) { 99 | m_ledPtrList[i]->readFromConfig(); 100 | } 101 | } 102 | 103 | void LedConfig::writeToConfig() 104 | { 105 | led_pwm_config_t *pwm = gEnv.pDeviceConfig->config.led_pwm_config; 106 | pwm[0].duty_cycle = ui->spinBox_LedPA8->value(); 107 | pwm[1].duty_cycle = ui->spinBox_LedPB0->value(); 108 | pwm[2].duty_cycle = ui->spinBox_LedPB1->value(); 109 | pwm[3].duty_cycle = ui->spinBox_LedPB4->value(); 110 | 111 | pwm[0].is_axis = ui->checkBox_connectedPA8->isChecked(); 112 | pwm[1].is_axis = ui->checkBox_connectedPB0->isChecked(); 113 | pwm[2].is_axis = ui->checkBox_connectedPB1->isChecked(); 114 | pwm[3].is_axis = ui->checkBox_connectedPB4->isChecked(); 115 | 116 | pwm[0].axis_num = ui->comboBox_axisConPA8->currentIndex(); 117 | pwm[1].axis_num = ui->comboBox_axisConPB0->currentIndex(); 118 | pwm[2].axis_num = ui->comboBox_axisConPB1->currentIndex(); 119 | pwm[3].axis_num = ui->comboBox_axisConPB4->currentIndex(); 120 | 121 | for (int i = 0; i < MAX_LEDS_NUM; ++i) { 122 | if (m_ledPtrList[i]->isHidden()) { 123 | break; 124 | } 125 | m_ledPtrList[i]->writeToConfig(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/widgets/led/ledconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef LEDCONFIG_H 2 | #define LEDCONFIG_H 3 | 4 | #include "led.h" 5 | #include 6 | 7 | namespace Ui { 8 | class LedConfig; 9 | } 10 | 11 | class LedConfig : public QWidget 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit LedConfig(QWidget *parent = nullptr); 17 | ~LedConfig(); 18 | 19 | void setLedsState(); 20 | 21 | void readFromConfig(); 22 | void writeToConfig(); 23 | 24 | void retranslateUi(); 25 | 26 | //void ButtonLEDStateChanged(); // future 27 | 28 | public slots: 29 | void spawnLeds(int ledCount); 30 | 31 | private: 32 | Ui::LedConfig *ui; 33 | 34 | QList m_ledPtrList; 35 | int m_currentLedCount; 36 | }; 37 | 38 | #endif // LEDCONFIG_H 39 | -------------------------------------------------------------------------------- /src/widgets/pins/currentconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "currentconfig.h" 2 | #include "ui_currentconfig.h" 3 | #include "common_defines.h" 4 | 5 | CurrentConfig::CurrentConfig(QWidget *parent) : 6 | QWidget(parent), 7 | ui(new Ui::CurrentConfig) 8 | { 9 | ui->setupUi(this); 10 | 11 | m_defaultLabelStyle = ""; 12 | m_maxButtonsWarning = false; 13 | m_axisSources = 0; 14 | m_buttonsFromAxes = 0; 15 | m_buttonsFromShiftRegs = 0; 16 | m_singleButtons = 0; 17 | m_rowsOfButtons = 0; 18 | m_columnsOfButtons = 0; 19 | m_singleLed = 0; 20 | m_rowsOfLed = 0; 21 | m_columnsOfLed = 0; 22 | 23 | m_limit = false; 24 | } 25 | 26 | CurrentConfig::~CurrentConfig() 27 | { 28 | delete ui; 29 | } 30 | 31 | 32 | void CurrentConfig::setConfig(int type, int changedHowMuch) 33 | { 34 | if (type == AXIS_SOURCE){ //int source_enum, bool is_add axesSourceChanged 35 | m_axisSources += changedHowMuch; 36 | ui->label_AxisSources->setNum(m_axisSources); 37 | // if (changedHowMuch > 0){ 38 | // emit axesSourceChanged(pinNumber - 1, true); 39 | // } else { 40 | // emit axesSourceChanged(pinNumber - 1, false); 41 | // } 42 | } 43 | else if (type == SINGLE_BUTTON){ 44 | m_singleButtons += changedHowMuch; 45 | ui->label_SingleButtons->setNum(m_singleButtons); 46 | ui->label_TotalButtons->setNum(m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons)); 47 | totalButtonsChanged(m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons)); 48 | } 49 | else if (type == ROW_OF_BUTTONS){ 50 | m_rowsOfButtons += changedHowMuch; 51 | ui->label_RowsOfButtons->setNum(m_rowsOfButtons); 52 | ui->label_ButtonsFromMatrix->setNum(m_columnsOfButtons * m_rowsOfButtons); 53 | ui->label_TotalButtons->setNum(m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons)); 54 | totalButtonsChanged(m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons)); 55 | } 56 | else if (type == COLUMN_OF_BUTTONS){ 57 | m_columnsOfButtons += changedHowMuch; 58 | ui->label_ColumnsOfButtons->setNum(m_columnsOfButtons); 59 | ui->label_ButtonsFromMatrix->setNum(m_columnsOfButtons * m_rowsOfButtons); 60 | ui->label_TotalButtons->setNum(m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons)); 61 | totalButtonsChanged(m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons)); 62 | } 63 | else if (type == SINGLE_LED){ 64 | m_singleLed += changedHowMuch; 65 | ui->label_TotalLEDs->setNum(m_singleLed + (m_rowsOfLed * m_columnsOfLed)); 66 | totalLEDsChanged(m_singleLed + (m_rowsOfLed * m_columnsOfLed)); 67 | } 68 | else if (type == ROW_OF_LED){ 69 | m_rowsOfLed += changedHowMuch; 70 | ui->label_TotalLEDs->setNum(m_singleLed + (m_rowsOfLed * m_columnsOfLed)); 71 | totalLEDsChanged(m_singleLed + (m_rowsOfLed * m_columnsOfLed)); 72 | } 73 | else if (type == COLUMN_OF_LED){ 74 | m_columnsOfLed += changedHowMuch; 75 | ui->label_TotalLEDs->setNum(m_singleLed + (m_rowsOfLed * m_columnsOfLed)); 76 | totalLEDsChanged(m_singleLed + (m_rowsOfLed * m_columnsOfLed)); 77 | } 78 | } 79 | 80 | void CurrentConfig::a2bCountChanged(int count) 81 | { 82 | m_buttonsFromAxes = count; 83 | ui->label_ButtonFromAxes->setNum(m_buttonsFromAxes); 84 | int totalButtons = m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons); 85 | ui->label_TotalButtons->setNum(totalButtons); 86 | totalButtonsChanged(totalButtons); 87 | } 88 | 89 | void CurrentConfig::shiftRegButtonsCountChanged(int count) 90 | { 91 | m_buttonsFromShiftRegs = count; 92 | ui->label_ButtonsFromShiftRegs->setNum(m_buttonsFromShiftRegs); 93 | int totalButtons = m_buttonsFromShiftRegs + m_buttonsFromAxes + m_singleButtons + (m_columnsOfButtons * m_rowsOfButtons); 94 | ui->label_TotalButtons->setNum(totalButtons); 95 | totalButtonsChanged(totalButtons); 96 | } 97 | 98 | void CurrentConfig::totalButtonsChanged(int count) 99 | { 100 | if (count > MAX_BUTTONS_NUM){ 101 | m_defaultLabelStyle = ui->label_TotalButtons->styleSheet(); 102 | ui->label_TotalButtons->setStyleSheet(m_defaultLabelStyle + QStringLiteral("background-color: rgb(200, 0, 0);")); 103 | ui->text_TotalButtons->setStyleSheet(m_defaultLabelStyle + QStringLiteral("background-color: rgb(200, 0, 0);")); 104 | m_maxButtonsWarning = true; 105 | if (m_limit == false) { 106 | m_limit = true; 107 | emit limitReached(true); 108 | } 109 | } else if (m_maxButtonsWarning == true){ // && count <= MAX_BUTTONS_NUM 110 | ui->text_TotalButtons->setStyleSheet(m_defaultLabelStyle); 111 | m_maxButtonsWarning = false; 112 | if (m_limit) { 113 | m_limit = false; 114 | emit limitReached(false); 115 | } 116 | } 117 | emit totalButtonsValueChanged(count); 118 | } 119 | 120 | void CurrentConfig::totalLEDsChanged(int count) 121 | { 122 | if (count > MAX_LEDS_NUM){ 123 | m_defaultLabelStyle = ui->label_TotalLEDs->styleSheet(); 124 | ui->label_TotalLEDs->setStyleSheet(m_defaultLabelStyle + QStringLiteral("background-color: rgb(200, 0, 0);")); 125 | ui->text_TotalLEDs->setStyleSheet(m_defaultLabelStyle + QStringLiteral("background-color: rgb(200, 0, 0);")); 126 | if (m_limit == false) { 127 | m_limit = true; 128 | emit limitReached(true); 129 | } 130 | } else { 131 | ui->text_TotalLEDs->setStyleSheet(m_defaultLabelStyle); 132 | if (m_limit) { 133 | m_limit = false; 134 | emit limitReached(false); 135 | } 136 | } 137 | emit totalLEDsValueChanged(count); 138 | } 139 | 140 | bool CurrentConfig::limitIsReached() 141 | { 142 | return m_limit; 143 | } 144 | -------------------------------------------------------------------------------- /src/widgets/pins/currentconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef CURRENTCONFIG_H 2 | #define CURRENTCONFIG_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class CurrentConfig; 8 | } 9 | 10 | class CurrentConfig : public QWidget 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit CurrentConfig(QWidget *parent = nullptr); 16 | ~CurrentConfig(); 17 | 18 | void setConfig(int type, int changedHowMuch); 19 | bool limitIsReached(); 20 | 21 | signals: 22 | void totalLEDsValueChanged(int totalLed); 23 | void totalButtonsValueChanged(int count); 24 | void limitReached(bool limit); 25 | 26 | public slots: 27 | void a2bCountChanged(int count); 28 | void shiftRegButtonsCountChanged(int count); 29 | void totalButtonsChanged(int count); 30 | void totalLEDsChanged(int count); 31 | 32 | private: 33 | Ui::CurrentConfig *ui; 34 | 35 | QString m_defaultLabelStyle; 36 | bool m_maxButtonsWarning; 37 | int m_axisSources; 38 | int m_buttonsFromAxes; 39 | int m_buttonsFromShiftRegs; 40 | int m_singleButtons; 41 | int m_rowsOfButtons; 42 | int m_columnsOfButtons; 43 | int m_singleLed; 44 | int m_rowsOfLed; 45 | int m_columnsOfLed; 46 | 47 | bool m_limit; 48 | 49 | enum 50 | { 51 | AXIS_SOURCE = 0, 52 | BUTTON_FROM_AXES, 53 | SINGLE_BUTTON, 54 | ROW_OF_BUTTONS, 55 | COLUMN_OF_BUTTONS, 56 | SINGLE_LED, 57 | ROW_OF_LED, 58 | COLUMN_OF_LED, 59 | }; 60 | }; 61 | 62 | #endif // CURRENTCONFIG_H 63 | -------------------------------------------------------------------------------- /src/widgets/pins/pincombobox.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PinComboBox 4 | 5 | 6 | 7 | 0 8 | 0 9 | 69 10 | 20 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | 35 | 36 | 0 37 | 0 38 | 39 | 40 | 41 | 25 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | CenteredCBox 50 | QComboBox 51 |
centered_cbox.h
52 |
53 |
54 | 55 | 56 |
57 | -------------------------------------------------------------------------------- /src/widgets/pins/pinconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef PINCONFIG_H 2 | #define PINCONFIG_H 3 | 4 | #include 5 | 6 | #include "pincombobox.h" 7 | #include "pinscontrlite.h" 8 | #include "pinsbluepill.h" 9 | //#include "currentconfig.h" 10 | 11 | QT_BEGIN_NAMESPACE 12 | class QGridLayout; 13 | QT_END_NAMESPACE 14 | 15 | #define SOURCE_COUNT 8 16 | #define PIN_TYPE_LIMIT_COUNT 3 17 | 18 | namespace Ui { 19 | class PinConfig; 20 | } 21 | 22 | class PinConfig : public QWidget 23 | { 24 | Q_OBJECT 25 | 26 | public: 27 | explicit PinConfig(QWidget *parent = nullptr); 28 | ~PinConfig(); 29 | void writeToConfig(); 30 | void readFromConfig(); 31 | 32 | bool limitIsReached(); 33 | 34 | void retranslateUi(); 35 | 36 | void resetAllPins(); 37 | 38 | signals: 39 | void totalButtonsValueChanged(int count); 40 | void totalLEDsValueChanged(int totalLed); 41 | void fastEncoderSelected(const QString &pinGuiName, bool isSelected); 42 | void shiftRegSelected(int latchPin, int clkPin, int dataPin, const QString &pinGuiName); 43 | void i2cSelected(bool i2cSelected); 44 | void axesSourceChanged(int sourceEnum, const QString &sourceName, bool isAdd); 45 | void limitReached(bool limit); 46 | 47 | //protected: 48 | // void resizeEvent(QResizeEvent*) override; 49 | 50 | public slots: 51 | void a2bCountChanged(int); 52 | void shiftRegButtonsCountChanged(int count); 53 | private slots: 54 | void pinInteraction(int index, int senderIndex, int pin); 55 | void pinIndexChanged(int currentDeviceEnum, int previousDeviceEnum, int pinNumber, QString pinName); 56 | void boardChanged(int index); 57 | 58 | private: 59 | Ui::PinConfig *ui; 60 | 61 | PinsBluePill *m_bluePill; 62 | PinsContrLite *m_contrLite; 63 | int m_lastBoard; 64 | 65 | //! PinComboBox widget list 66 | QList m_pinCBoxPtrList; 67 | 68 | QString m_defaultLabelStyle; 69 | bool m_maxButtonsWarning; 70 | 71 | int m_shiftLatchCount; 72 | int m_shiftDataCount; 73 | int m_shiftClkCount; 74 | 75 | void signalsForWidgets(int currentDeviceEnum, int previousDeviceEnum, int pinNumber, QString pinName); 76 | void pinTypeLimit(int currentDeviceEnum, int previousDeviceEnum); 77 | void setCurrentConfig(int currentDeviceEnum, int previousDeviceEnum, int pinNumber, QString pinName); 78 | void blockPA8PWM(int currentDeviceEnum, int previousDeviceEnum); 79 | 80 | struct source_t 81 | { 82 | int type; 83 | int pinType[PIN_TYPE_COUNT]; 84 | }; 85 | 86 | struct pinTypeLimit_t 87 | { 88 | int deviceEnumIndex; 89 | int maxCount; 90 | }; 91 | 92 | const source_t m_source[SOURCE_COUNT] = 93 | { 94 | {AXIS_SOURCE, {AXIS_ANALOG, TLE5011_CS, MCP3201_CS, MCP3202_CS, MCP3204_CS, MCP3208_CS, MLX90393_CS, MLX90363_CS, AS5048A_CS, TLE5012_CS}}, 95 | 96 | {BUTTON_FROM_AXES, {678}}, // 678 в DeviceConfig 97 | 98 | {SINGLE_BUTTON, {BUTTON_VCC, BUTTON_GND}}, 99 | {ROW_OF_BUTTONS, {BUTTON_ROW}}, 100 | {COLUMN_OF_BUTTONS, {BUTTON_COLUMN}}, 101 | 102 | {SINGLE_LED, {LED_SINGLE}}, 103 | {ROW_OF_LED, {LED_ROW}}, 104 | {COLUMN_OF_LED, {LED_COLUMN}}, 105 | }; 106 | 107 | const pinTypeLimit_t m_pinTypeLimit[PIN_TYPE_LIMIT_COUNT] = // static ? 108 | { 109 | {SHIFT_REG_LATCH, 4}, 110 | {SHIFT_REG_DATA, 4}, 111 | {SHIFT_REG_CLK, 4}, 112 | }; 113 | 114 | enum // and in current config 115 | { 116 | AXIS_SOURCE = 0, 117 | BUTTON_FROM_AXES, 118 | SINGLE_BUTTON, 119 | ROW_OF_BUTTONS, 120 | COLUMN_OF_BUTTONS, 121 | SINGLE_LED, 122 | ROW_OF_LED, 123 | COLUMN_OF_LED, 124 | }; 125 | }; 126 | 127 | #endif // PINCONFIG_H 128 | -------------------------------------------------------------------------------- /src/widgets/pins/pinconfig.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PinConfig 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1009 10 | 668 11 | 12 | 13 | 14 | 15 | 0 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 6 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Qt::Horizontal 39 | 40 | 41 | QSizePolicy::Fixed 42 | 43 | 44 | 45 | 16 46 | 10 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Select board 55 | 56 | 57 | Qt::AlignCenter 58 | 59 | 60 | 61 | 62 | 63 | 64 | 0 65 | 66 | 67 | 68 | 69 | 70 | 71 | Qt::Vertical 72 | 73 | 74 | QSizePolicy::Preferred 75 | 76 | 77 | 78 | 20 79 | 40 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Qt::Horizontal 88 | 89 | 90 | QSizePolicy::Fixed 91 | 92 | 93 | 94 | 16 95 | 10 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | CenteredCBox 108 | QComboBox 109 |
centered_cbox.h
110 |
111 | 112 | CurrentConfig 113 | QWidget 114 |
currentconfig.h
115 | 1 116 |
117 |
118 | 119 | 120 |
121 | -------------------------------------------------------------------------------- /src/widgets/pins/pinsbluepill.cpp: -------------------------------------------------------------------------------- 1 | #include "pinsbluepill.h" 2 | #include "ui_pinsbluepill.h" 3 | #include 4 | 5 | PinsBluePill::PinsBluePill(QWidget *parent) : 6 | QWidget(parent), 7 | ui(new Ui::PinsBluePill) 8 | { 9 | ui->setupUi(this); 10 | 11 | ui->label_ControllerImage->contentsMargins(); 12 | } 13 | 14 | PinsBluePill::~PinsBluePill() 15 | { 16 | delete ui; 17 | } 18 | 19 | void PinsBluePill::addPinComboBox(QList pinList) 20 | { 21 | QElapsedTimer timer; 22 | timer.start(); 23 | int tmp = 0; 24 | int labelColumn; 25 | int pinsColumn; 26 | // left layout 27 | labelColumn = 1; 28 | pinsColumn = 0; 29 | QComboBox *prevCBox = nullptr; 30 | for (int i = 0; i < ui->layoutG_pinsLeft->rowCount(); ++i) { 31 | // continue if no label or pin row not empty 32 | if (!ui->layoutG_pinsLeft->itemAtPosition(i, labelColumn) || ui->layoutG_pinsLeft->itemAtPosition(i, pinsColumn)) { 33 | continue; 34 | } 35 | // search label in column 1 36 | QLabel *label = qobject_cast(ui->layoutG_pinsLeft->itemAtPosition(i, labelColumn)->widget()); 37 | if (label) { 38 | // add widget to column 0 39 | for (int k = 0; k < pinList.size(); ++k) { 40 | if (pinList[k]->objectName() == label->text()) {// clone pinList and remove item if addWidget? 41 | ui->layoutG_pinsLeft->addWidget(pinList[k], i, pinsColumn); 42 | tmp++; 43 | // tab order 44 | QComboBox *child = pinList[k]->findChild(); 45 | if (!prevCBox) { 46 | child->setTabOrder(this, child); 47 | prevCBox = child; 48 | } else { 49 | child->setTabOrder(prevCBox, child); 50 | prevCBox = child; 51 | } 52 | break; 53 | } 54 | } 55 | } 56 | } 57 | // right layout 58 | labelColumn = 0; 59 | pinsColumn = 1; 60 | for (int i = 0; i < ui->layoutG_pinsRight->rowCount(); ++i) { 61 | // continue if no label or pin row not empty 62 | if (!ui->layoutG_pinsRight->itemAtPosition(i, labelColumn) || ui->layoutG_pinsRight->itemAtPosition(i, pinsColumn)) { 63 | continue; 64 | } 65 | // search label in column 0 66 | QLabel *label = qobject_cast(ui->layoutG_pinsRight->itemAtPosition(i, labelColumn)->widget()); 67 | if (label) { 68 | // add widget to column 1 69 | for (int k = 0; k < pinList.size(); ++k) { 70 | if (pinList[k]->objectName() == label->text()) {// clone pinList and remove item if addWidget? 71 | ui->layoutG_pinsRight->addWidget(pinList[k], i, pinsColumn); 72 | tmp++; 73 | // tab order 74 | QComboBox *child = pinList[k]->findChild(); 75 | if (!prevCBox) { 76 | child->setTabOrder(this, child); 77 | prevCBox = child; 78 | } else { 79 | child->setTabOrder(prevCBox, child); 80 | prevCBox = child; 81 | } 82 | break; 83 | } 84 | } 85 | } 86 | } 87 | Q_ASSERT(tmp == PINS_COUNT); 88 | } 89 | -------------------------------------------------------------------------------- /src/widgets/pins/pinsbluepill.h: -------------------------------------------------------------------------------- 1 | #ifndef PINBLUEPILL_H 2 | #define PINBLUEPILL_H 3 | 4 | #include 5 | #include "pincombobox.h" 6 | 7 | QT_BEGIN_NAMESPACE 8 | class QGridLayout; 9 | QT_END_NAMESPACE 10 | 11 | namespace Ui { 12 | class PinsBluePill; 13 | } 14 | 15 | class PinsBluePill : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit PinsBluePill(QWidget *parent = nullptr); 21 | ~PinsBluePill(); 22 | 23 | void addPinComboBox (QList pinList); 24 | 25 | private: 26 | Ui::PinsBluePill *ui; 27 | }; 28 | 29 | #endif // PINBLUEPILL_H 30 | -------------------------------------------------------------------------------- /src/widgets/pins/pinscontrlite.cpp: -------------------------------------------------------------------------------- 1 | #include "pinscontrlite.h" 2 | #include "ui_pinscontrlite.h" 3 | #include 4 | 5 | PinsContrLite::PinsContrLite(QWidget *parent) : 6 | QWidget(parent), 7 | ui(new Ui::PinsContrLite) 8 | { 9 | ui->setupUi(this); 10 | } 11 | 12 | PinsContrLite::~PinsContrLite() 13 | { 14 | delete ui; 15 | } 16 | 17 | void PinsContrLite::addPinComboBox(QList pinList) 18 | { 19 | int tmp = 0; 20 | QComboBox *prevCBox = nullptr; 21 | for (int i = 0; i < 5; ++i) { 22 | for (int j = 0; j < ui->layoutG_pins->rowCount(); ++j) { 23 | if (!ui->layoutG_pins->itemAtPosition(j, i*3)) { 24 | continue; 25 | } 26 | QLabel *label = qobject_cast(ui->layoutG_pins->itemAtPosition(j, i*3)->widget()); 27 | if (label) { 28 | for (int k = 0; k < pinList.size(); ++k) { 29 | if (pinList[k]->objectName() == label->text()) {// clone pinList and remove if addWidget? 30 | ui->layoutG_pins->addWidget(pinList[k], j, i*3+1); 31 | tmp++; 32 | // tab order 33 | QComboBox *child = pinList[k]->findChild(); 34 | if (!prevCBox) { 35 | child->setTabOrder(this, child); 36 | prevCBox = child; 37 | } else { 38 | child->setTabOrder(prevCBox, child); 39 | prevCBox = child; 40 | } 41 | break; 42 | } 43 | } 44 | } 45 | } 46 | } 47 | Q_ASSERT(tmp == PINS_COUNT); 48 | } 49 | -------------------------------------------------------------------------------- /src/widgets/pins/pinscontrlite.h: -------------------------------------------------------------------------------- 1 | #ifndef PINCONTRLITE_H 2 | #define PINCONTRLITE_H 3 | 4 | #include 5 | #include "pincombobox.h" 6 | 7 | QT_BEGIN_NAMESPACE 8 | class QGridLayout; 9 | QT_END_NAMESPACE 10 | 11 | namespace Ui { 12 | class PinsContrLite; 13 | } 14 | 15 | class PinsContrLite : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit PinsContrLite(QWidget *parent = nullptr); 21 | ~PinsContrLite(); 22 | 23 | void addPinComboBox (QList pinList); 24 | 25 | private: 26 | Ui::PinsContrLite *ui; 27 | }; 28 | 29 | #endif // PINCONTRLITE_H 30 | -------------------------------------------------------------------------------- /src/widgets/selectfolder.cpp: -------------------------------------------------------------------------------- 1 | #include "selectfolder.h" 2 | #include "ui_selectfolder.h" 3 | #include 4 | 5 | SelectFolder::SelectFolder(const QString &folderPath, QWidget *parent) : 6 | QDialog(parent), 7 | ui(new Ui::SelectFolder) 8 | { 9 | ui->setupUi(this); 10 | 11 | setWindowTitle(tr("Configs folder path")); 12 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); 13 | 14 | ui->lineEdit_currentFolder->setReadOnly(true); 15 | ui->lineEdit_currentFolder->setText(folderPath); 16 | 17 | connect(ui->pushButton_ok, &QPushButton::clicked, this, &SelectFolder::accept); 18 | 19 | connect(ui->toolButton_selFolder, &QPushButton::clicked, this, &SelectFolder::selectFolder); 20 | } 21 | 22 | SelectFolder::~SelectFolder() 23 | { 24 | delete ui; 25 | } 26 | 27 | QString SelectFolder::folderPath() const 28 | { 29 | return ui->lineEdit_currentFolder->text(); 30 | } 31 | 32 | void SelectFolder::setFolderPath(const QString &path) 33 | { 34 | if (path == ui->lineEdit_currentFolder->text()) { ////////// ???????????????? 35 | return; 36 | } 37 | ui->lineEdit_currentFolder->setText(path); 38 | QStringList list = cfgFilesList(path); 39 | } 40 | 41 | void SelectFolder::selectFolder() 42 | { 43 | QString folder = QFileDialog::getExistingDirectory(0, 44 | (tr("Select configs folder")), 45 | ui->lineEdit_currentFolder->text()); 46 | if (folder.isEmpty()) { 47 | return; 48 | } 49 | setFolderPath(folder); 50 | } 51 | 52 | // get config file list 53 | QStringList SelectFolder::cfgFilesList(const QString &dirPath) 54 | { 55 | QDir dir(dirPath); 56 | QStringList cfgs = dir.entryList(QStringList() << "*.cfg", QDir::Files); 57 | for (auto &line : cfgs) { 58 | line.remove(line.size() - 4, 4);// 4 = ".cfg" characters count 59 | } 60 | cfgs.sort(Qt::CaseInsensitive); 61 | return cfgs; 62 | } 63 | -------------------------------------------------------------------------------- /src/widgets/selectfolder.h: -------------------------------------------------------------------------------- 1 | #ifndef SELECTFOLDER_H 2 | #define SELECTFOLDER_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class SelectFolder; 8 | } 9 | 10 | class SelectFolder : public QDialog 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit SelectFolder(const QString &folderPath, QWidget *parent = nullptr); 16 | ~SelectFolder(); 17 | 18 | QString folderPath() const; 19 | void setFolderPath(const QString &path); 20 | 21 | private: 22 | Ui::SelectFolder *ui; 23 | void selectFolder(); 24 | QStringList cfgFilesList(const QString &dirPath); 25 | }; 26 | 27 | #endif // SELECTFOLDER_H 28 | -------------------------------------------------------------------------------- /src/widgets/selectfolder.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SelectFolder 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 80 11 | 12 | 13 | 14 | 15 | 300 16 | 80 17 | 18 | 19 | 20 | 21 | 650 22 | 100 23 | 24 | 25 | 26 | Dialog 27 | 28 | 29 | 30 | 6 31 | 32 | 33 | 6 34 | 35 | 36 | 6 37 | 38 | 39 | 6 40 | 41 | 42 | 43 | 44 | Ok 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Current folder: 54 | 55 | 56 | 57 | 58 | 59 | 60 | true 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | :/Images/folder.png:/Images/folder.png 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/widgets/shift-reg/shiftregisters.cpp: -------------------------------------------------------------------------------- 1 | #include "shiftregisters.h" 2 | #include "ui_shiftregisters.h" 3 | #include 4 | 5 | QString ShiftRegisters::m_notDefined = nullptr; 6 | 7 | ShiftRegisters::ShiftRegisters(int shiftRegNumber, QWidget *parent) 8 | : QWidget(parent) 9 | , ui(new Ui::ShiftRegisters) 10 | { 11 | ui->setupUi(this); 12 | 13 | // для перевода при старте приложения, надо определить после старта транслятора 14 | if (m_notDefined == nullptr) { 15 | m_notDefined = tr("Not defined"); 16 | } 17 | 18 | m_buttonsCount = 0; 19 | m_latchPin = 0; 20 | m_dataPin = 0; 21 | m_shiftRegNumber = shiftRegNumber; 22 | ui->label_ShiftIndex->setNum(shiftRegNumber + 1); 23 | 24 | for (int i = 0; i < SHIFT_REG_TYPES; ++i) { 25 | ui->comboBox_ShiftRegType->addItem(m_shiftRegistersList[i].guiName); 26 | ui->label_DataPin->setText(m_notDefined); 27 | ui->label_ClkPin->setText(m_notDefined); 28 | ui->label_LatchPin->setText(m_notDefined); 29 | } 30 | 31 | connect(ui->spinBox_ButtonCount, SIGNAL(valueChanged(int)), this, SLOT(calcRegistersCount(int))); 32 | } 33 | 34 | ShiftRegisters::~ShiftRegisters() 35 | { 36 | delete ui; 37 | } 38 | 39 | void ShiftRegisters::retranslateUi() 40 | { 41 | ui->retranslateUi(this); 42 | } 43 | 44 | void ShiftRegisters::calcRegistersCount(int count) 45 | { 46 | ui->label_RegistersCount->setNum(ceil(count / 8.0)); 47 | 48 | if (ui->spinBox_ButtonCount->isEnabled() == true) { 49 | emit buttonCountChanged(count, m_buttonsCount); 50 | m_buttonsCount = count; 51 | } 52 | } 53 | 54 | void ShiftRegisters::setLatchPin(int latchPin, QString pinGuiName) 55 | { 56 | if (latchPin != 0) { 57 | m_latchPin = latchPin; 58 | ui->label_LatchPin->setText(pinGuiName); 59 | } else { 60 | m_latchPin = 0; 61 | ui->label_LatchPin->setText(m_notDefined); 62 | } 63 | setUiOnOff(); 64 | } 65 | 66 | void ShiftRegisters::setClkPin(int clkPin, QString pinGuiName) 67 | { 68 | if (clkPin != 0) { 69 | m_clkPin = clkPin; 70 | ui->label_ClkPin->setText(pinGuiName); 71 | } else { 72 | m_clkPin = 0; 73 | ui->label_ClkPin->setText(m_notDefined); 74 | } 75 | setUiOnOff(); 76 | } 77 | 78 | void ShiftRegisters::setDataPin(int dataPin, QString pinGuiName) 79 | { 80 | if (dataPin != 0) { 81 | m_dataPin = dataPin; 82 | ui->label_DataPin->setText(pinGuiName); 83 | } else { 84 | m_dataPin = 0; 85 | ui->label_DataPin->setText(m_notDefined); 86 | } 87 | setUiOnOff(); 88 | } 89 | 90 | void ShiftRegisters::setUiOnOff() 91 | { 92 | if (m_latchPin > 0 && m_clkPin > 0 && m_dataPin > 0) { 93 | for (auto &&child : this->findChildren()) { 94 | child->setEnabled(true); 95 | } 96 | } else { 97 | ui->spinBox_ButtonCount->setValue(0); 98 | for (auto &&child : this->findChildren()) { 99 | child->setEnabled(false); 100 | } 101 | } 102 | } 103 | 104 | const QString &ShiftRegisters::defaultText() const 105 | { 106 | return m_notDefined; 107 | } 108 | 109 | void ShiftRegisters::readFromConfig() 110 | { 111 | ui->comboBox_ShiftRegType->setCurrentIndex(gEnv.pDeviceConfig->config.shift_registers[m_shiftRegNumber].type); 112 | ui->spinBox_ButtonCount->setValue(gEnv.pDeviceConfig->config.shift_registers[m_shiftRegNumber].button_cnt); 113 | } 114 | 115 | void ShiftRegisters::writeToConfig() 116 | { 117 | gEnv.pDeviceConfig->config.shift_registers[m_shiftRegNumber].type = ui->comboBox_ShiftRegType->currentIndex(); 118 | gEnv.pDeviceConfig->config.shift_registers[m_shiftRegNumber].button_cnt = ui->spinBox_ButtonCount->value(); 119 | } 120 | -------------------------------------------------------------------------------- /src/widgets/shift-reg/shiftregisters.h: -------------------------------------------------------------------------------- 1 | #ifndef SHIFTREGISTERS_H 2 | #define SHIFTREGISTERS_H 3 | 4 | #include 5 | 6 | #include "deviceconfig.h" 7 | #include "global.h" 8 | 9 | #define SHIFT_REG_TYPES 4 10 | 11 | namespace Ui { 12 | class ShiftRegisters; 13 | } 14 | 15 | class ShiftRegisters : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit ShiftRegisters(int shiftRegNumber, QWidget *parent = nullptr); 21 | ~ShiftRegisters(); 22 | 23 | void readFromConfig(); 24 | void writeToConfig(); 25 | 26 | void retranslateUi(); 27 | 28 | void setLatchPin(int latchPin, QString pinGuiName); 29 | void setClkPin(int clkPin, QString pinGuiName); 30 | void setDataPin(int dataPin, QString pinGuiName); 31 | 32 | const QString &defaultText() const; 33 | 34 | signals: 35 | void buttonCountChanged(int currentCount, int previousCount); 36 | 37 | private slots: 38 | void calcRegistersCount(int buttonCount); 39 | 40 | private: 41 | Ui::ShiftRegisters *ui; 42 | void setUiOnOff(); 43 | 44 | static QString m_notDefined; 45 | int m_buttonsCount; 46 | int m_shiftRegNumber; 47 | int m_latchPin; 48 | int m_clkPin; 49 | int m_dataPin; 50 | 51 | const deviceEnum_guiName_t m_shiftRegistersList[SHIFT_REG_TYPES] = // порядов обязан быть как в common_types.h!!!!!!!!!!! 52 | { 53 | {HC165_PULL_DOWN, tr("HC165 Pull Down")}, 54 | {CD4021_PULL_DOWN, tr("CD4021 Pull Down")}, 55 | {HC165_PULL_UP, tr("HC165 Pull Up")}, 56 | {CD4021_PULL_UP, tr("CD4021 Pull Up")}, 57 | }; 58 | }; 59 | 60 | #endif // SHIFTREGISTERS_H 61 | -------------------------------------------------------------------------------- /src/widgets/shift-reg/shiftregistersconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "shiftregistersconfig.h" 2 | #include "ui_shiftregistersconfig.h" 3 | #include 4 | 5 | ShiftRegistersConfig::ShiftRegistersConfig(QWidget *parent) : 6 | QWidget(parent), 7 | ui(new Ui::ShiftRegistersConfig) 8 | { 9 | ui->setupUi(this); 10 | m_shiftButtonsCount = 0; 11 | 12 | ui->layoutV_ShiftRegisters->setAlignment(Qt::AlignTop); 13 | // shift registers spawn 14 | for (int i = 0; i < MAX_SHIFT_REG_NUM; i++) 15 | { 16 | ShiftRegisters * shift_register = new ShiftRegisters(i, this); 17 | ui->layoutV_ShiftRegisters->addWidget(shift_register); 18 | m_shiftRegsPtrList.append(shift_register); 19 | connect(shift_register, &ShiftRegisters::buttonCountChanged, 20 | this, &ShiftRegistersConfig::shiftRegButtonsCalc); 21 | } 22 | } 23 | 24 | ShiftRegistersConfig::~ShiftRegistersConfig() 25 | { 26 | delete ui; 27 | } 28 | 29 | void ShiftRegistersConfig::retranslateUi() 30 | { 31 | ui->retranslateUi(this); 32 | for (int i = 0; i < m_shiftRegsPtrList.size(); ++i) { 33 | m_shiftRegsPtrList[i]->retranslateUi(); 34 | } 35 | } 36 | 37 | 38 | void ShiftRegistersConfig::shiftRegButtonsCalc(int currentCount, int previousCount) 39 | { 40 | m_shiftButtonsCount += currentCount - previousCount; 41 | emit shiftRegButtonsCountChanged(m_shiftButtonsCount); 42 | } 43 | 44 | 45 | bool ShiftRegistersConfig::sortByPinNumberAndNullLast(const ShiftRegData_t &lhs, const ShiftRegData_t &rhs) 46 | { 47 | // sort null last 48 | if (lhs.pinNumber == 0) { 49 | return false; 50 | } else if (rhs.pinNumber == 0) { 51 | return true; 52 | } else { // sort ascending 53 | return lhs.pinNumber < rhs.pinNumber; 54 | } 55 | } 56 | 57 | // bullshit 58 | void ShiftRegistersConfig::addPinAndSort(int pin, const QString &pinGuiName, std::array &arr) 59 | { 60 | // add shift reg latch/clk pin 61 | if (pin > 0) { 62 | arr.back().pinNumber = pin; 63 | arr.back().guiName = pinGuiName; 64 | } 65 | // delete shift reg latch pin 66 | else 67 | { 68 | pin = -pin; 69 | for (uint i = 0; i < arr.size(); ++i) { 70 | if (pin == arr[i].pinNumber) { 71 | arr[i].pinNumber = 0; 72 | arr[i].guiName = m_shiftRegsPtrList[0]->defaultText(); //????????????????? 73 | } 74 | } 75 | } 76 | 77 | std::sort(arr.begin(), arr.end(), sortByPinNumberAndNullLast); 78 | 79 | //all unused pins (if (m_latchPinsArray[i].pinNumber == 0)) = bigger pin 80 | for (int i = arr.size() -1; i >= 0; --i) { // bullshit // todo: refactoring 81 | if (arr[i].pinNumber > 0) { 82 | // example: we have selected ShiftLatch pins{A0(pinNumber = 1), A2(pinNumber = 3), A6(pinNumber = 7)} 83 | // in the end it should look like: m_latchPinsArray.pinNumber{1, 3, 7, 7, 7} 84 | for (uint k = 0; k < arr.size() -1; ++k) { 85 | if (arr[k].pinNumber == arr[k + 1].pinNumber && arr.back().pinNumber > 0) { 86 | for (uint p = 0; p < arr.size() -(k + 2); ++p) { 87 | arr[k + p + 1].pinNumber = arr.back().pinNumber; 88 | arr[k + p + 1].guiName = arr.back().guiName; 89 | } 90 | break; 91 | } 92 | } 93 | for (int j = arr.size() -1; j > i; --j) { 94 | arr[j].pinNumber = arr[i].pinNumber; 95 | arr[j].guiName = arr[i].guiName; 96 | } 97 | break; 98 | } 99 | } 100 | } 101 | 102 | void ShiftRegistersConfig::shiftRegSelected(int latchPin, int clkPin, int dataPin, const QString &pinGuiName) 103 | { 104 | // add shift reg latch pin 105 | if (latchPin != 0) { 106 | addPinAndSort(latchPin, pinGuiName, m_latchPinsArray); 107 | 108 | // update shiftreg ui 109 | for (uint i = 0; i < m_latchPinsArray.size() - 1; ++i) { 110 | m_shiftRegsPtrList[i]->setLatchPin(m_latchPinsArray[i].pinNumber, m_latchPinsArray[i].guiName); 111 | } 112 | } 113 | // add shift reg clk pin 114 | else if (clkPin != 0) { 115 | addPinAndSort(clkPin, pinGuiName, m_clkPinsArray); 116 | 117 | // update shiftreg ui 118 | for (uint i = 0; i < m_clkPinsArray.size() - 1; ++i) { 119 | m_shiftRegsPtrList[i]->setClkPin(m_clkPinsArray[i].pinNumber, m_clkPinsArray[i].guiName); 120 | } 121 | } 122 | // add shift reg data pin 123 | else if (dataPin != 0) { 124 | if (dataPin > 0) { 125 | m_dataPinsArray[m_dataPinsArray.size() - 1].pinNumber = dataPin; 126 | m_dataPinsArray[m_dataPinsArray.size() - 1].guiName = pinGuiName; 127 | } else { 128 | dataPin = -dataPin; 129 | for (uint i = 0; i < m_dataPinsArray.size(); ++i) { 130 | if (dataPin == m_dataPinsArray[i].pinNumber){ 131 | m_dataPinsArray[i].pinNumber = 0; 132 | m_dataPinsArray[i].guiName = m_shiftRegsPtrList[i]->defaultText(); //????????????????? 133 | } 134 | } 135 | } 136 | 137 | std::sort(m_dataPinsArray.begin(), m_dataPinsArray.end(), sortByPinNumberAndNullLast); 138 | 139 | for (uint i = 0; i < m_dataPinsArray.size() - 1; ++i) { 140 | m_shiftRegsPtrList[i]->setDataPin(m_dataPinsArray[i].pinNumber, m_dataPinsArray[i].guiName); 141 | } 142 | 143 | } 144 | } 145 | 146 | void ShiftRegistersConfig::readFromConfig() 147 | { 148 | for (int i = 0; i < m_shiftRegsPtrList.size(); ++i) { 149 | m_shiftRegsPtrList[i]->readFromConfig(); 150 | } 151 | } 152 | 153 | void ShiftRegistersConfig::writeToConfig() 154 | { 155 | for (int i = 0; i < m_shiftRegsPtrList.size(); ++i) { 156 | m_shiftRegsPtrList[i]->writeToConfig(); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/widgets/shift-reg/shiftregistersconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef SHIFTREGISTERSCONFIG_H 2 | #define SHIFTREGISTERSCONFIG_H 3 | 4 | #include "shiftregisters.h" 5 | #include // ?? 6 | #include 7 | 8 | #include "deviceconfig.h" 9 | #include "global.h" 10 | 11 | namespace Ui { 12 | class ShiftRegistersConfig; 13 | } 14 | 15 | class ShiftRegistersConfig : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit ShiftRegistersConfig(QWidget *parent = nullptr); 21 | ~ShiftRegistersConfig(); 22 | 23 | void readFromConfig(); 24 | void writeToConfig(); 25 | 26 | void retranslateUi(); 27 | 28 | signals: 29 | void shiftRegButtonsCountChanged(int buttonsCount); 30 | 31 | public slots: 32 | void shiftRegSelected(int latchPin, int clkPin, int dataPin, const QString &pinGuiName); 33 | private slots: 34 | void shiftRegButtonsCalc(int currentCount, int previousCount); 35 | 36 | private: 37 | Ui::ShiftRegistersConfig *ui; 38 | 39 | struct ShiftRegData_t // можно и глобальную deviceEnum_guiName_t взять 40 | { 41 | int pinNumber; 42 | QString guiName; 43 | }; 44 | 45 | int m_shiftButtonsCount; 46 | 47 | static bool sortByPinNumberAndNullLast(const ShiftRegData_t &lhs, const ShiftRegData_t &rhs); 48 | void addPinAndSort(int pin, const QString &pinGuiName, std::array &arr); 49 | 50 | std::array m_latchPinsArray{}; 51 | std::array m_clkPinsArray{}; 52 | std::array m_dataPinsArray{}; 53 | 54 | QList m_shiftRegsPtrList; 55 | }; 56 | 57 | #endif // SHIFTREGISTERSCONFIG_H 58 | -------------------------------------------------------------------------------- /src/widgets/shift-reg/shiftregistersconfig.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ShiftRegistersConfig 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1062 10 | 603 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 0 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | 0 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | 35 | QFrame::NoFrame 36 | 37 | 38 | true 39 | 40 | 41 | 42 | 43 | 0 44 | 0 45 | 1062 46 | 603 47 | 48 | 49 | 50 | 51 | 0 52 | 53 | 54 | 0 55 | 56 | 57 | 0 58 | 59 | 60 | 0 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/widgets/switchbutton.cpp: -------------------------------------------------------------------------------- 1 | #include "switchbutton.h" 2 | #include 3 | #include 4 | #include 5 | 6 | //QPoint poin2[50]; 7 | SwitchButton::SwitchButton(QWidget *parent) 8 | : QWidget(parent) 9 | , m_currentState(false) 10 | , m_mousePressed(false) 11 | { 12 | changeColor(m_currentState); 13 | } 14 | 15 | 16 | bool SwitchButton::isChecked() const 17 | { 18 | return m_currentState; 19 | } 20 | 21 | void SwitchButton::setChecked(bool checked) 22 | { 23 | if (m_currentState == checked) return; 24 | 25 | m_currentState = checked; 26 | changeColor(m_currentState); 27 | update(); 28 | emit stateChanged(m_currentState); 29 | } 30 | 31 | 32 | void SwitchButton::paintEvent(QPaintEvent *event) 33 | { 34 | Q_UNUSED(event) 35 | QPainter p(this); 36 | QStyleOption opt; 37 | opt.initFrom(this); 38 | style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); 39 | 40 | p.setRenderHint(QPainter::Antialiasing, true); 41 | p.setRenderHint(QPainter::SmoothPixmapTransform,true); 42 | //p.setRenderHint(QPainter::LosslessImageRendering,true); 43 | 44 | int height = this->height(); 45 | int width = this->width(); 46 | int offset = 5; 47 | 48 | QPointF point; 49 | if (m_currentState == false) { 50 | // first 51 | point = QPointF(m_halfHeight, m_halfHeight); 52 | p.setBrush(m_kSunBackground); 53 | } else { 54 | // last 55 | point = QPointF(width - m_halfHeight, m_halfHeight); 56 | p.setBrush(m_kMoonBackground); 57 | // p.setPen(QColor(248, 227, 161)); 58 | // for (int i = 0; i < 10; ++i) { 59 | // p.drawLine(poin2[i], QPoint(poin2[i].x() + 3, poin2[i].y() -3)); 60 | // p.drawLine(poin2[i].x() + 3, poin2[i].y()-1, poin2[i].x(), poin2[i].y() -3); 61 | // } 62 | } 63 | 64 | p.setPen(QColor(90, 90, 90)); 65 | QRectF rect(3, 4, width-6, height-8); 66 | p.drawRoundedRect(rect, 10.0, 60.0); 67 | 68 | p.setPen(QColor(110, 64, 201)); 69 | p.drawEllipse(point, m_halfHeight -1.0f, m_halfHeight -1.0f); 70 | 71 | 72 | QRectF target(offset, offset, 73 | height - offset *2, height - offset *2); 74 | QRectF source(0.0, 0.0, m_sunPix.size().width(), m_sunPix.size().height()); 75 | p.drawPixmap(target, m_sunPix, source); 76 | 77 | QRectF target3(width - height +offset, offset, 78 | height - offset *2, height - offset *2); 79 | QRectF source3(0.0, 0.0, m_moonPix.size().width(), m_moonPix.size().height()); 80 | p.drawPixmap(target3, m_moonPix, source3); 81 | } 82 | 83 | void SwitchButton::changeColor(bool checked) 84 | { 85 | if (checked == false) { 86 | m_sunPix = changePixmapColor(m_sunPix, m_kSunLightMode); 87 | m_moonPix = changePixmapColor(m_moonPix, m_kMoonLightMode); 88 | } else { 89 | m_sunPix = changePixmapColor(m_sunPix, m_kSunDarkMode); 90 | m_moonPix = changePixmapColor(m_moonPix, m_kMoonDarkMode); 91 | } 92 | } 93 | 94 | QPixmap SwitchButton::changePixmapColor(const QPixmap &pixmap, const QColor &color) 95 | { 96 | QPixmap pix = pixmap; 97 | QPainter painter(&pix); 98 | painter.setCompositionMode(QPainter::CompositionMode_SourceIn); 99 | // set color 100 | painter.setBrush(color); 101 | painter.setPen(color); 102 | // paint rect 103 | painter.drawRect(pix.rect()); 104 | return pix; 105 | } 106 | 107 | void SwitchButton::mousePressEvent(QMouseEvent *event) 108 | { 109 | if (event->button() == Qt::LeftButton) { 110 | m_mousePressed = true; 111 | } 112 | } 113 | 114 | void SwitchButton::mouseReleaseEvent(QMouseEvent *event) 115 | { 116 | if (event->button() == Qt::LeftButton) { 117 | if (m_mousePressed) { 118 | setChecked(!m_currentState); 119 | m_mousePressed = false; 120 | } 121 | } 122 | } 123 | 124 | void SwitchButton::resizeEvent(QResizeEvent *event) 125 | { 126 | Q_UNUSED(event) 127 | m_halfWidth = width() / 2.0f; 128 | m_halfHeight = height() / 2.0f; 129 | // for (int i = 0; i < 50; ++i) { 130 | // poin2[i].setX(rand() % (width() - 2)); 131 | // poin2[i].setY(rand() % height()); 132 | // } 133 | } 134 | -------------------------------------------------------------------------------- /src/widgets/switchbutton.h: -------------------------------------------------------------------------------- 1 | #ifndef SWITCHBUTTON_H 2 | #define SWITCHBUTTON_H 3 | 4 | #include 5 | 6 | class QPropertyAnimation; 7 | 8 | class SwitchButton : public QWidget 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit SwitchButton(QWidget *parent = nullptr); 13 | 14 | bool isChecked() const; 15 | 16 | public slots: 17 | void setChecked(bool checked); 18 | 19 | signals: 20 | void stateChanged(bool checked); 21 | 22 | protected: 23 | void paintEvent(QPaintEvent *event) override; 24 | void mousePressEvent(QMouseEvent *event) override; 25 | void mouseReleaseEvent(QMouseEvent *event) override; 26 | void resizeEvent(QResizeEvent *event) override; 27 | 28 | private: 29 | 30 | QPixmap changePixmapColor(const QPixmap &pixmap, const QColor &color); 31 | void changeColor(bool state); 32 | 33 | QPixmap m_sunPix = QPixmap(":/Images/sun.png"); 34 | const QColor m_kSunLightMode = QColor(248, 227, 161); 35 | const QColor m_kSunDarkMode = QColor(124, 113, 60); 36 | const QColor m_kSunBackground = QColor(100, 123, 210);; 37 | 38 | QPixmap m_moonPix = QPixmap(":/Images/moon.png"); 39 | const QColor m_kMoonLightMode = QColor(74, 79, 89);//QColor(49, 54, 59); 40 | const QColor m_kMoonDarkMode = QColor(248, 227, 161); 41 | const QColor m_kMoonBackground = QColor(39, 51, 69); 42 | 43 | //QColor m_backgroundColor; 44 | 45 | bool m_currentState; 46 | bool m_mousePressed; 47 | 48 | float m_halfWidth; 49 | float m_halfHeight; 50 | }; 51 | 52 | #endif // SWITCHBUTTON_H 53 | -------------------------------------------------------------------------------- /src/winapp.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeJoy-Team/FreeJoyConfiguratorQt/0651652a53d1079f55cfcb22ac8d969a07bc7a4f/src/winapp.rc --------------------------------------------------------------------------------