Compare commits

...

128 Commits

Author SHA1 Message Date
Max Paperno 85863358fb [Horus] Outputs widget: Fix bar graph overflow with extended limits (#4969)
* [Horus][Widgets] Outputs widget: Fix bar graph overflow with extended limits (closes #4968); Show standard/translatable source names (CHxx) when no custom name is defined; More const-ness, less math.

* [OutputsWidget] Yet more const-ness and less calculation repetition.
2017-05-30 18:37:38 +02:00
3djc b397af1bac Fix overflow when firmware filename is too long (#4971) 2017-05-30 18:36:36 +02:00
Max Paperno 0906bdc6d7 Adjust logical switch abbreviations. (#4965)
* [Companion] Change logical switch abbreviations to "LS##" in Source/Switch selection lists.

* [LogicalSwitchesPanel] Normalize LS name label.

* We had decided on "Lxx"

* Match firmware side

* ARM wasn't using the translations

* Update strhelpers.cpp
2017-05-30 18:36:04 +02:00
Arne Schwabe 77925f6abc Fix issue #4961 (#4963) 2017-05-29 18:16:01 +02:00
Martin Hotar 0a0893e6cc cz translations of companion (#4964) 2017-05-29 18:15:21 +02:00
3djc 3d17023bc9 Fixes numbering discrepancy for Horus inputs (#4967)
Fixes #4966
2017-05-29 13:24:29 +02:00
3djc fd16151850 Update CREDITS.txt 2017-05-28 10:21:12 +02:00
Arne Schwabe 2ae0472f76 Minor fixes to lua dua 2017-05-28 09:48:34 +02:00
Arne Schwabe cd23fedb56 Schwabe/lua set curve (#4955)
* Implement setCurve for lua

* Bug fixes after actual testing of API

* Fix documentation

* Even more error checking

* Add example code how to use this function

* Silence gcc warnings

* Drop points and start array index at 1 and note about wrong index in getCurve

* Add standard example

* Fixes

* Don’t use an invalid number in example

* fix missing 0
2017-05-28 07:30:43 +02:00
Bertrand Songis 1cb0156cd0 Update CREDITS.txt 2017-05-25 11:25:30 +02:00
Arne Schwabe 4880c029b7 Schwabe/fix curve overflow (#4951)
* Fix curve editing function not checking if there is space for the curve

* Fix compile error
2017-05-24 18:42:56 +02:00
Arne Schwabe c79994d812 Exit if the FindSDL script finds 2.x instead of 1.x (#4948) 2017-05-23 16:46:36 +02:00
Sebastien Charpentier f462af1b0e Updated French translation (#4946)
* Updated French .ts file.

* Updated French Translation.

* Missing space.
2017-05-23 16:12:04 +02:00
David Zumbrunnen 8729bbc41b Fixed syntax error in UDEV rules (#4945)
Extraneous semicolon results in an error saying: `invalid key/value pair in
file /lib/udev/rules.d/45-companion22-taranis.rules on line 1, starting
at character 83 (';')`
2017-05-23 13:46:10 +02:00
Max Paperno 0fc1681d5c [Companion] Improve first use of Companion & upgrade notice (#4940)
* [Companion] On first use of Companion show preferences dialog and new welcome message (closes #4731); Improve detection of new version upgrade & reformat message; Add download link URL to Linux update notice (closes #4774); Fix issue with leftover top-level settings categories when checking for older versions which don't exist; Introduce basic structure for warnings/messages to be suppressed by user preferences (eg. "don't show this message again" option).

* Welcome msg typo fix.
2017-05-23 09:44:47 +02:00
Max Paperno 69576cb17d [Companion] Speed up/fix findMassstoragePath(): Use Qt methods when available (v5.4+) and only check for path on FAT[32] file systems; For older Qt, skip root (/), /net, /proc, & /run devices on Linux/macOS; Fixes long delay on eg. macOS due to network access. Remove unused #include "mountlist.h" in process_flash.cpp. (#4937) 2017-05-20 21:34:26 +02:00
3djc 1a85956dcb Tentative fix (#4939) 2017-05-20 21:33:43 +02:00
Arne Schwabe 01150497bb Schwabe/log sensors by default (#4932)
* Log telemetry sensors by default

* Renome now redundant logs = True code from Frsky
2017-05-19 17:19:43 +02:00
Sebastien Charpentier 0ed7f5a5ad French translation (#4936)
* Created French .ts file.

* Fixed some French translation.
2017-05-19 17:18:59 +02:00
Bertrand Songis ce83cf00e0 Update CREDITS.txt 2017-05-19 17:16:38 +02:00
Andre Bernet 8eea072cd1 Don’t spam simulator with dummy values on telemetry reset anymore (#4933)
* Don’t spam simulator with dummy values on telemetry reset anymore, simulator can be used if needed

* Ditch more dummies
2017-05-18 07:11:48 +02:00
Andre Bernet 4d23292ad3 Empty error message box is no fun 2017-05-16 14:39:27 +04:00
Damjan Adamic 618832974e Re #4718: added missing dependency libqt5multimedia5-plugins for Debian/Ubuntu packages (missing sound when using Qt Multimedia) 2017-05-14 19:20:51 +02:00
3djc c80fbf2de7 Get lua fields info from inside docker 2017-05-14 12:35:13 +02:00
3djc 5b69ceff0d Further follow up 2017-05-14 08:40:47 +02:00
3djc 3cc3687dcb Follow up on next rename 2017-05-14 08:11:04 +02:00
Andre Bernet eb7c73668f Leftover stuff on Windows uninstall 2017-05-13 16:18:56 +02:00
Damjan Adamic d35d3b5e22 Prepare Launchpad scripts for non-nightly release 2017-05-13 14:02:59 +02:00
3djc 935518f6dd Let's build a few more 2017-05-13 13:37:02 +02:00
3djc 20dcee3a5c Release prep 2017-05-13 13:17:14 +02:00
Arne Schwabe 5825a2ec2c remove dubious GNUC and rename 9x refrences 2017-05-13 13:05:47 +02:00
Arne Schwabe 355f4b5f92 Also download and open new updates on OS X (#4926)
* Also download and open new updates on OS X

* Cosmetics
2017-05-13 13:03:39 +02:00
Andre Bernet 9437d98df9 Merge branch 'kilrah/companion_sdcard_download' into next 2017-05-13 11:55:59 +02:00
3djc 7a8ca1c675 Match release dir struct 2017-05-13 11:49:58 +02:00
3djc 79d9359e56 More release prep 2017-05-13 11:46:13 +02:00
3djc 006166a25c Release helping change 2017-05-13 11:17:48 +02:00
3djc 33cc0861a6 Release prep 2017-05-13 11:00:07 +02:00
Bertrand Songis d48ab63497 Update CREDITS.txt 2017-05-12 22:09:07 +02:00
3djc bd62281144 X12 : split S6R settings and calibration scripts (#4920)
* Quick and dirty split

* Some cleanups
2017-05-12 19:53:46 +02:00
Bertrand Songis 50397d0052 3djc added
Thanks for your help!
2017-05-12 07:56:00 +02:00
Andre Bernet 460e6aab96 Update all custom screen references after deleting one (fix #4909) (#4914) 2017-05-11 18:39:26 +02:00
3djc 95b0a21cfc Introduce S6R calibration tool to x7 (#4916)
Introduce real time position feedback
Autosense between S6R and S8R (not same sensor orientation)
2017-05-11 18:39:10 +02:00
Max Paperno f7b6d95910 [Companion] Input names formatting (#4888)
* [Companion] Re-format Inputs list to format input name consistently with rest of UI; Add leading zeros to RawSource numbers in names; Show custom channel name in MixerDialog.

* [Companion] Remove colon separator between input number and custom name.

* Fix segfault when no model pointer is passed to RawSource::toString() (problem was only on this branch).
2017-05-11 07:37:13 +02:00
Sebastien Charpentier 6e0bec9db4 Update French translation (#4908)
* Generated new French .ts file.

* Update French translation concerning the new SD sync mechanism.

* Skip must be translated as "Ignorer", not "Sauter".

* French mistake.
2017-05-11 07:36:54 +02:00
Bertrand Songis 83132ef041 Update README.md 2017-05-09 09:30:06 +02:00
Max Paperno c1586b72bb [Companion] SD Sync reworked: (#4906)
* Complete re-write of SyncProcess, now more robust, UI-independent, runs in own thread, large speed boost;
    * Use file hash comparisons instead of byte-level compare with string methods (probable fixes for #4837 and #4848);
    * New pre-sync options dialog with selectable folders and other settings (settings are remembered until app exit);
    * Option to choose sync direction(s) (up/down/bi) and the order in which bi-directional sync runs;
    * Option to choose file comparison mode (timestamp/hash/both) or force overwrite (for one-way sync);
    * Option to set a maximum file size to copy;
    * Option to do a test run w/out actually copying any files;
    * Better reporting of progress, total counts (copied/updated/skipped), and errors, with color coding;
    * Much more reliable to cancel long-running/hung copy process;
    * ProgressWidget can now display rich-text in the text browser, added some new functions for usage;
    * Misc. small layout tweaks to ProgressDialog and ProgressWidget to make them behave/look better;
2017-05-08 20:51:26 +02:00
Max Paperno ca25696d1a [Companion] Radio module setup: Fix custom failsafe no-pulse and hold options not being saved properly (closes #4904). 2017-05-08 08:29:11 -04:00
Bertrand Songis 11579d9118 Update CREDITS.txt 2017-05-08 13:48:13 +02:00
Andre Bernet 32714fb841 No more subdomain 2017-05-08 12:33:15 +02:00
Andre Bernet 2bc2030f86 Merge branch 'next' into kilrah/companion_sdcard_download
# Conflicts:
#	companion/src/fwpreferencesdialog.cpp
2017-05-08 09:48:53 +02:00
Bertrand Songis 93dbdf8680 Just some comments, the very minimum 2017-05-07 22:27:10 +02:00
3djc 301e33a271 gTTS (#4899)
* Release prep work

* Add CZ support

* Prep for release

* No more need to prefix unicode strings (we use python3)
Some fixes
Italian fixes
2017-05-07 17:39:31 +02:00
Sebastien Charpentier 53bb8bc6c3 Updated French translation. (#4902)
* Generate nex French .ts file.

* Updated French translation.
2017-05-07 17:39:06 +02:00
Max Paperno e2502772cb [Companion] Model Setup: Prevent bogus modification signals. (#4896)
* [Companion] Model editor Setup panel: Prevent bogus modification signals, eg. when populating protocols box or when removing focus from some fields w/out the value actually changing; Remove unnecessary function.

* [SetupPanel] Fix comparison warning and also a translation issue with Multiprotocols subtype and option names.

* [ModelPrinter] Add a missing include.
2017-05-06 18:09:20 +02:00
Max Paperno 24de312a30 [Companion] Some radio settings Hardware tab fixes. (#4895)
* [Companion] Radio -> General Settings -> Hardware: Hide external serial port option for Horus; Fix battery voltage and current calibration changes not registering (wrong signal handler name); Prevent modified() event if edited value wasn't actually changed (this is a problem in all panels with onEditingFinished() signals); Fix some cosmetic layout issues when no hardware names are editable.

* [HardwarePanel] Minor layout fix for BT option.

* [HardwarePanel] Fix comparison issue.
2017-05-06 18:08:55 +02:00
3djc efe53eb034 Fix translation for audio files (#4889)
Switch the time mechanic to english one (may not be perfect, but current italian is not working at all)
2017-05-06 18:08:28 +02:00
Max Paperno 96ccb4cb3f [Companion] Fix a few translations. (#4890)
* [Simulator] Fix keymap translations.

* [Companion] Fix translations in file type selector dialogs.

* [Simulator] Fix inadvertent help text delimiter change.
2017-05-06 18:04:51 +02:00
Bertrand Songis 3f06037e1b [Companion] Credits dialog refactoring 2017-05-06 17:55:03 +02:00
Bertrand Songis 38d8f6a326 Update DONATIONS.txt 2017-05-06 00:13:12 +02:00
Bertrand Songis 2bec60517a Update DONATIONS.txt 2017-05-05 07:28:32 +02:00
Bertrand Songis d3b8133ee2 Add LapinFou to CREDITS.txt 2017-05-02 07:33:10 +02:00
Sebastien Charpentier 4b2b5a9d37 Logical switch L% or LSw% are now translated in IL% (Interrupteur Logique). (#4886) 2017-05-01 17:44:08 +02:00
Bertrand Songis 6edc3b61ff Update DONATIONS.txt 2017-05-01 08:29:22 +02:00
Arne Schwabe f525b1762b Fix #4881 (#4884)
Thanks Mike for noticing: In pxx_arm.cpp, the pulse duration is set to either 48 or 32. This value gets put into the ARR register of the timer (via DMA). Counters count from 0 to the ARR value, then go back to 0. This will result in either 49 or 33 counts for the pulse width, thus making the pulses 0.5uS too long.

Tested only with external PXX
2017-05-01 00:33:45 +02:00
3djc 4f5f241669 Fix opentx-9x-autoswitch-autosource-dblkeys-battgraph-telemetrez-sp22-stickrev-pgbar-en.hex (#4883) 2017-04-30 23:19:43 +02:00
Bertrand Songis 0b25332171 Add @schwabe to CREDITS.txt 2017-04-30 12:58:49 +02:00
3djc 054c87c91e Fix adjust GVAR and Volume (#4880) 2017-04-30 12:53:25 +02:00
Bertrand Songis e053abfc3e Max added to the CREDITS.txt 2017-04-30 08:57:36 +02:00
Max Paperno 6abd36d628 [Simulator] Revert logic switch names in Radio Outputs view to numbers-only (since @72b1ad0, closes #4877). 2017-04-29 20:49:04 -04:00
Damjan Adamic 582546f8ed Fixes #4839: path buffer overflow if LUA widget or theme directory name was too long (max length of directory name is 13 characters) (#4876) 2017-04-29 22:18:11 +02:00
Damjan Adamic c1e7235375 Launchpad changelogs for 2.2.0 RC18 2017-04-29 19:26:49 +02:00
Bertrand Songis 975023bdc7 Update DONATIONS.txt 2017-04-29 16:02:37 +02:00
Max Paperno 4df32f8247 [Companion] Prevent crash when importing (converting) more models than current radio can handle. 2017-04-29 07:30:44 -04:00
Sebastien Charpentier 630dec62f5 Fixed French translations (#4875)
* Updated French .ts file.

* Updated French translations.
2017-04-29 10:34:50 +02:00
3djc a58a541bb6 Only display RAS for XJT modules (#4869) 2017-04-29 09:10:15 +02:00
3djc 0cff67e032 Fix some too long translation (#4873)
* Fix FR, DE, PL

* Such a better fix thanks to @mhotar !

* Create conditional linebreak for 128pixels and Horus, but not X9

* CosmeticsCo
2017-04-29 09:04:23 +02:00
Max Paperno 72b1ad085f [Companion] Show custom channel, G-Var, and Curve names throughout UI. (#4874)
* [Companion] Move RadioData constructor.

* [Companion] Move getCapability(SwitchPositions) to Boards class.

* [Companion] Show custom channel, g-var, & curve names throughout UI; Remove redundant name formatting and other unused functions in ModelPrinter and Helpers; Add CustomFunctionData::isEmpty().

* [Companion] Add LogicalSwitchData::isEmpty().

* [Companion] Fix small bug in HardwarePanel.

* [Companion] Rename logical switches to "LSw##" in selections lists to avoid confusion with "L#" and "LS" hardware controls; remove unused RotaryEncoderString().
2017-04-29 09:03:53 +02:00
3djc 04bcc70422 X7 output main view : dynamic PREC also for PPM_US (#4871)
* Differentiate PREC threshold for PPM_US and PPM_PERCENT

* Cosmetics
2017-04-28 16:14:48 +02:00
Sebastien Charpentier d5eec9b8dc Fixed typo. (#4870) 2017-04-28 16:13:19 +02:00
Bertrand Songis 36afe4127c Update DONATIONS.txt 2017-04-28 16:12:41 +02:00
Bertrand Songis 572463bb0d Update DONATIONS.txt 2017-04-27 21:13:09 +02:00
3djc 6f066253f0 Proper (?) fix (#4868) 2017-04-27 21:08:46 +02:00
Sebastien Charpentier f3cbc37067 Fix French translation (#4862)
* Fixed too long French translation for the Horus.

* Fixed some French translations.
2017-04-27 21:06:40 +02:00
Arne Schwabe 37b0dab9da Add RAS to X7 analogs screen (#4865)
* Add RAS to X7 analogs screen

* Also fix SWR->RAS in simulator UI

* Only display RAS for external XJT module

The „this is almost useless but I have done the work, now it stays commit“
2017-04-27 20:31:00 +02:00
Damjan Adamic c6d15c6f37 Launchpad changelogs for 2.2.0 RC17 2017-04-27 11:19:57 +02:00
Damjan Adamic 73f4b8f172 Projectkk2glider/issue 4827 (#4855)
* Reverting a part of f94b4c743d that deals with the size of table hash. Fixes 4827, but uses more memory and CPU.

* New internal Lua traces
2017-04-26 21:45:46 +02:00
Bertrand Songis 3aceed62c9 [Companion] Fixes #4777 (#4860) 2017-04-26 21:43:35 +02:00
Bertrand Songis f10bad7abe Proposal to fix #4831 (CZ TTS problem with PREC1 and units) (#4856)
* Proposal to fix #4831

* Next fix for #4831

* Initiate some CZ docs

* Some more structure, still a workframe

* My attempt to help with #4831

* Update tts_doc_cz.md

* copy/paste error

* Update tts_doc_cz.md

* missed one number/qr.quot

* Cosmetics

* Consistency in parameters order

* Nearly complete doc

* Cosmetics to facilitate coding for non CZ devs

* Fix integer+unit, cosmetics

* Update tts_doc Radians and Mililiters are Male gender

* Radian and Millimeter are Male (so i've been told)

* Cosmetics

* Invers pushUnitPrompt parameters as per bsongis request
2017-04-26 21:42:01 +02:00
Bertrand Songis c15922a942 Update DONATIONS.txt 2017-04-26 17:30:34 +02:00
Bertrand Songis c2a6a20fc1 [TTS] Fixes 2017-04-26 13:13:55 +02:00
Bertrand Songis 37155363ff [TTS] gTTS method added 2017-04-26 12:33:12 +02:00
Bertrand Songis b0183efaf1 Fixes #4841 2017-04-25 21:25:46 +02:00
3djc 6dd8524ea5 Differentiate message despite so little space :s (#4850) 2017-04-25 12:08:20 +02:00
Arne Schwabe 50cb102a34 [MULTI] Fix fallback to Flysky and Spektrum telemetry without MULTI_TELEMETRY (#4851) 2017-04-25 12:07:34 +02:00
3djc be20e90630 3djc/gps display fixes (#4852)
* Remove top GPS coord display on X7 sensor edit (not enough space for it)

* Improve GPS coord display on X9
2017-04-25 12:06:40 +02:00
Martin Hotar c15a86dc19 cz rtanslation fixes and mode sources aligned a bit -it fixes EN version as well (#4854) 2017-04-24 20:53:09 +02:00
Bertrand Songis b790a844f1 Fixes #4806 2017-04-24 19:33:06 +02:00
Bertrand Songis faacf7f9c5 Update DONATIONS.txt 2017-04-24 18:00:45 +02:00
Max Paperno f9b7f567c3 [Companion] Fix Special/Global Functions action selector being reset for all lines when one line is deleted/cut/pasted (closes #4825). 2017-04-23 21:10:17 -04:00
3djc 591522c25a fix drawSource (#4843) 2017-04-23 18:00:11 +02:00
3djc 9193604aff X7 : fix calibration interuption (#4835)
* Fix 4833

* Less worse fix ?

* Trying something else
2017-04-23 12:38:50 +02:00
Bertrand Songis 1ad8769fff [Horus] Vector table updated (#4842) 2017-04-23 10:11:01 +02:00
3djc fbc3bac6d3 Review handling of combine INTERNAL_PPM and MULTIMODULE (#4826)
* First attempt

* Fix

* Review IS_INTERNAL_MODULE_ENABLED() macro
2017-04-23 10:10:43 +02:00
Bertrand Songis ea5401084c Update DONATIONS.txt 2017-04-22 20:50:50 +02:00
Bertrand Songis 902473fe6f Update 2017-04-20 09:39:44 +02:00
Sebastien Charpentier bc6ed93b0f Updated Frencht ranslation for "SimulatorMain". (#4817) 2017-04-19 10:57:31 +02:00
reichi b5f5e64d95 Fix DS3231 RTC read/write on AR9X (#4819) 2017-04-19 10:55:48 +02:00
3djc fa951acf40 Review line ending handling (#4820)
* New line end handling rules

* Normalize all the line endings
2017-04-19 10:54:43 +02:00
Bertrand Songis 189b65b724 Update DONATIONS.txt 2017-04-18 22:11:39 +02:00
3djc 6e427bca74 Do not allow past SWSRC_TELEMETRY_STREAMING for global functions (#4814) 2017-04-18 12:56:03 +02:00
3djc 0c260ce12d Invert outputs limits when output is reversed (#4813)
* Invert outputs limits when output is reversed

* Cosmetics
2017-04-18 12:55:43 +02:00
Bertrand Songis 9a93d85ef6 Update DONATIONS.txt 2017-04-18 08:33:23 +02:00
3djc 46f0384828 No reason for that just yet 2017-04-17 12:02:33 +02:00
Arne Schwabe 54c1f22312 Multimodule has a pulldown resistor and does not work with open drain, use push pull instead (#4808) 2017-04-17 10:25:56 +02:00
Bertrand Songis 2b41ba94ff Update opentxsimulator.cpp 2017-04-17 10:23:09 +02:00
Arne Schwabe 471c38628f Fix key variable not initialised (#4790) 2017-04-17 10:22:21 +02:00
Andre Bernet b0b270963c Cosmetics 2017-04-17 10:16:20 +02:00
Bertrand Songis a719c391a1 Fixes #4768 (#4807) 2017-04-17 10:04:09 +02:00
3djc 13e6ae1d08 Move tm_year to unsigned (#4811)
Fixes 4627
2017-04-17 10:03:45 +02:00
Bertrand Songis c6148c109c Update DONATIONS.txt 2017-04-17 09:59:12 +02:00
3djc 95bc595f50 Better manage additional switches declared as toggle or 2pos (#4793) 2017-04-16 21:13:51 +02:00
Max Paperno 1d6f2acbc2 [Simulator] Refactor CLI option parsing, add "--sd-path" and "--start-with" options (#4798)
* [Simulator] Refactor CLI option parsing to use QCommandLineParser, remove QxtCommandOptions external lib; Add "--sd-path" and "--start-with" options; Qualify all translatable text (SimulatorMain context).

* Add date string to version.
2017-04-16 21:03:31 +02:00
Andre Bernet 5d5c915ea9 [Horus] Language specific char handling was missing in text view 2017-04-16 21:02:10 +02:00
Sebastien Charpentier f795528d21 Translate last missing field + correct some translation (confirmation box) when deleting models/categories. (#4797) 2017-04-16 20:58:14 +02:00
3djc 1d4ec6f73e 3djc/fix #4795 (#4802)
* Prevent popup in undue places

* Working fix ?
2017-04-16 10:18:52 +02:00
Damjan Adamic 723b5df4f1 Launchpad changelogs for 2.2.0 RC16 2017-04-15 11:54:12 +02:00
Andre Bernet b8e0f26a22 Cosmetics 2017-03-20 10:31:39 +01:00
Andre Bernet 22217e8e22 [companion] Replace voice download by SD download, new URL for 2.2 (sd-22.open-tx.org, needs to be created) 2017-03-20 10:24:43 +01:00
579 changed files with 262458 additions and 262445 deletions
+111
View File
@@ -1 +1,112 @@
# Handle line endings automatically for files detected as text
# and leave all files detected as binary untouched.
* text=auto
#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
# Source files
*.c text
*.cc text
*.cxx text
*.cpp text
*.c++ text
*.hpp text
*.h text
*.h++ text
*.hh text
*.lua text
*.pxd text
*.py text
*.py3 text
*.pyw text
*.pyx text
*.pl text
*.pm text
*.sln text eol=crlf
*.csproj text eol=crlf
*.vbproj text eol=crlf
*.vcxproj text eol=crlf
*.vcproj text eol=crlf
*.dbproj text eol=crlf
*.fsproj text eol=crlf
*.lsproj text eol=crlf
*.wixproj text eol=crlf
*.modelproj text eol=crlf
*.sqlproj text eol=crlf
*.wmaproj text eol=crlf
*.xproj text eol=crlf
*.props text eol=crlf
*.filters text eol=crlf
*.vcxitems text eol=crlf
*.sh eol=lf
# Compiled Object files
*.slo binary
*.lo binary
*.o binary
*.obj binary
# Precompiled Headers
*.gch binary
*.pch binary
# Compiled Dynamic libraries
*.so binary
*.dylib binary
*.dll binary
# Compiled Static libraries
*.lai binary
*.la binary
*.a binary
*.lib binary
# Executables
*.exe binary
*.out binary
*.app binary
# Binary files
*.db binary
*.p binary
*.pkl binary
*.pyc binary
*.pyd binary
*.pyo binary
# Documents
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.md text
*.adoc text
*.textile text
*.mustache text
*.csv text
*.tab text
*.tsv text
*.sql text
# Graphics
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.tif binary
*.tiff binary
*.ico binary
# SVG treated as an asset (binary) by default. If you want to treat it as text,
# comment-out the following line and uncomment the line after.
*.svg binary
#*.svg text
*.eps binary
+4 -1
View File
@@ -6,7 +6,7 @@ set(VERSION_REVISION "0")
set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX})
set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR})
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX})
set(SDCARD_REVISION "0009")
set(SDCARD_REVISION "0010")
set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION})
cmake_minimum_required(VERSION 2.8)
@@ -133,6 +133,9 @@ if(Qt5Core_FOUND OR FOX_FOUND)
find_package("SDL")
if(SDL_FOUND)
message(STATUS "SDL Lib: ${SDL_LIBRARY}; Headers: ${SDL_INCLUDE_DIR}; Version: ${SDL_VERSION_STRING}")
if (NOT ${SDL_VERSION_STRING} VERSION_LESS "2.0")
message(FATAL_ERROR "OpenTX requires SDL 1.x, not 2.x")
endif()
else()
message(STATUS "SDL not found! Simulator audio, and joystick inputs, will not work.")
endif()
+1203
View File
File diff suppressed because it is too large Load Diff
-1158
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -10,7 +10,6 @@ The ongoing development on 2.2.x is done in this branch.
Refer to the [OpenTX wiki](https://github.com/opentx/opentx/wiki) for information about setting up the tool chains for building OpenTX and OpenTX Companion as well as other development related issues.
Useful links:
* OpenTX Blog http://blog.open-tx.org/
* OpenTX Main Site http://www.open-tx.org/
* OpenTx University http://open-txu.org/
* OpenTX User Manual https://www.gitbook.com/book/opentx/opentx-taranis-manual/details
+67 -67
View File
@@ -1,68 +1,68 @@
# Find Xerces-C
# The following setings are defined
# XERCESC_ROOT_DIR, the root of the include and lib directory
# XERCESC_INCLUDE_DIR, the full path of the include dir (ADVANCED)
# XERCESC_LIBRARIES, the name of the xerces-c library (ADVANCED)
# Look for a root installation
IF( MSVC )
SET( XERCES_WINDIR C:/Programs/xerces-vc )
ELSE( )
SET( XERCES_WINDIR C:/Programs/xerces )
ENDIF( )
FIND_PATH(XERCESC_ROOT_DIR include/xercesc/parsers/SAXParser.hpp
${XERCES_WINDIR}
"C:/mingw/msys/1.0/local"
"C:/Program Files/CodeSynthesis XSD 3.2"
/usr
/usr/local
"C:/MinGW"
$ENV{CODESYNTH}
DOC "The root of an installed xerces-c installation"
)
# try to find the header
FIND_PATH(XERCESC_INCLUDE_DIR xercesc/parsers/SAXParser.hpp
${XERCESC_ROOT_DIR}/include
/usr/include
/usr/local/include
)
# Find the library
FIND_LIBRARY(XERCESC_LIBRARY
NAMES xerces-c xerces-c_3
PATHS
${XERCESC_ROOT_DIR}/lib
${XERCESC_ROOT_DIR}/lib/vc-9.0
${XERCESC_ROOT_DIR}/lib64/vc-9.0
/usr/lib
/usr/local/lib
DOC "The name of the xerces-c library"
)
IF (XERCESC_ROOT_DIR)
IF (XERCESC_INCLUDE_DIR AND XERCESC_LIBRARY)
SET (XERCESC_FOUND TRUE)
SET (XERCESC_LIBRARIES "${XERCESC_LIBRARY}")
# FIXME: There should be a better way of handling this?
# FIXME: How can we test to see if the lib dir isn't
# FIXME: one of the default dirs?
LINK_DIRECTORIES(${XERCESC_ROOT_DIR}/lib)
ENDIF (XERCESC_INCLUDE_DIR AND XERCESC_LIBRARY)
ENDIF (XERCESC_ROOT_DIR)
IF (XERCESC_FOUND)
IF (NOT XERCESC_FIND_QUIETLY)
MESSAGE (STATUS " found xerces-c: ${XERCESC_LIBRARY}")
ENDIF (NOT XERCESC_FIND_QUIETLY)
ELSE (XERCESC_FOUND)
IF (XERCESC_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Xerces-C")
ENDIF (XERCESC_FIND_REQUIRED)
ENDIF (XERCESC_FOUND)
MARK_AS_ADVANCED(
XERCESC_INCLUDE_DIR
XERCESC_LIBRARY
# Find Xerces-C
# The following setings are defined
# XERCESC_ROOT_DIR, the root of the include and lib directory
# XERCESC_INCLUDE_DIR, the full path of the include dir (ADVANCED)
# XERCESC_LIBRARIES, the name of the xerces-c library (ADVANCED)
# Look for a root installation
IF( MSVC )
SET( XERCES_WINDIR C:/Programs/xerces-vc )
ELSE( )
SET( XERCES_WINDIR C:/Programs/xerces )
ENDIF( )
FIND_PATH(XERCESC_ROOT_DIR include/xercesc/parsers/SAXParser.hpp
${XERCES_WINDIR}
"C:/mingw/msys/1.0/local"
"C:/Program Files/CodeSynthesis XSD 3.2"
/usr
/usr/local
"C:/MinGW"
$ENV{CODESYNTH}
DOC "The root of an installed xerces-c installation"
)
# try to find the header
FIND_PATH(XERCESC_INCLUDE_DIR xercesc/parsers/SAXParser.hpp
${XERCESC_ROOT_DIR}/include
/usr/include
/usr/local/include
)
# Find the library
FIND_LIBRARY(XERCESC_LIBRARY
NAMES xerces-c xerces-c_3
PATHS
${XERCESC_ROOT_DIR}/lib
${XERCESC_ROOT_DIR}/lib/vc-9.0
${XERCESC_ROOT_DIR}/lib64/vc-9.0
/usr/lib
/usr/local/lib
DOC "The name of the xerces-c library"
)
IF (XERCESC_ROOT_DIR)
IF (XERCESC_INCLUDE_DIR AND XERCESC_LIBRARY)
SET (XERCESC_FOUND TRUE)
SET (XERCESC_LIBRARIES "${XERCESC_LIBRARY}")
# FIXME: There should be a better way of handling this?
# FIXME: How can we test to see if the lib dir isn't
# FIXME: one of the default dirs?
LINK_DIRECTORIES(${XERCESC_ROOT_DIR}/lib)
ENDIF (XERCESC_INCLUDE_DIR AND XERCESC_LIBRARY)
ENDIF (XERCESC_ROOT_DIR)
IF (XERCESC_FOUND)
IF (NOT XERCESC_FIND_QUIETLY)
MESSAGE (STATUS " found xerces-c: ${XERCESC_LIBRARY}")
ENDIF (NOT XERCESC_FIND_QUIETLY)
ELSE (XERCESC_FOUND)
IF (XERCESC_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Xerces-C")
ENDIF (XERCESC_FIND_REQUIRED)
ENDIF (XERCESC_FOUND)
MARK_AS_ADVANCED(
XERCESC_INCLUDE_DIR
XERCESC_LIBRARY
)
+3 -5
View File
@@ -104,7 +104,6 @@ include_directories(
${COMPANION_SRC_DIRECTORY}
${COMPANION_SRC_DIRECTORY}/shared
${SIMU_SRC_DIRECTORY}
${COMPANION_SRC_DIRECTORY}/thirdparty/qxtcommandoptions
${COMPANION_SRC_DIRECTORY}/thirdparty/qcustomplot
${COMPANION_SRC_DIRECTORY}/thirdparty/miniz
${COMPANION_SRC_DIRECTORY}/storage
@@ -207,7 +206,6 @@ add_subdirectory(generaledit)
add_subdirectory(simulation)
add_subdirectory(storage)
add_subdirectory(thirdparty/qcustomplot)
add_subdirectory(thirdparty/qxtcommandoptions)
############# Companion ###############
@@ -220,7 +218,7 @@ set(companion_SRCS
burnconfigdialog.cpp
multimodelprinter.cpp
comparedialog.cpp
contributorsdialog.cpp
creditsdialog.cpp
releasenotesdialog.cpp
releasenotesfirmwaredialog.cpp
customizesplashdialog.cpp
@@ -254,7 +252,7 @@ set(companion_MOC_HDRS
printdialog.h
fusesdialog.h
logsdialog.h
contributorsdialog.h
creditsdialog.h
releasenotesdialog.h
releasenotesfirmwaredialog.h
customizesplashdialog.h
@@ -315,7 +313,7 @@ PrintTargetReport("${COMPANION_NAME}")
set(simu_SRCS simulator.cpp )
add_executable(${SIMULATOR_NAME} MACOSX_BUNDLE ${WIN_EXECUTABLE_TYPE} ${simu_SRCS} ${icon_RC})
target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation ${CPN_COMMON_LIB} storage qxtcommandoptions ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES})
target_link_libraries(${SIMULATOR_NAME} PRIVATE simulation ${CPN_COMMON_LIB} storage ${PTHREAD_LIBRARY} ${SDL_LIBRARY} ${WIN_LINK_LIBRARIES})
############# Install ####################
+5
View File
@@ -211,6 +211,11 @@ const int Boards::getCapability(Board::Type board, Board::Capability capability)
return 8;
else
return 7;
case SwitchPositions:
if (IS_HORUS_OR_TARANIS(board))
return getCapability(board, Switches) * 3;
else
return 9;
case NumTrims:
if (IS_HORUS(board))
return 6;
+1
View File
@@ -111,6 +111,7 @@ namespace Board {
Sliders,
MouseAnalogs,
Switches,
SwitchPositions,
FactoryInstalledSwitches,
NumTrims,
NumTrimSwitches
-1
View File
@@ -3,7 +3,6 @@
<file>images/customize.png</file>
<file>icon.png</file>
<file>../../CREDITS.txt</file>
<file>../../DONATIONS.txt</file>
<file>../releasenotes.txt</file>
<file>images/screenshot.png</file>
<file>images/splash.png</file>
+16 -14
View File
@@ -21,6 +21,8 @@
#ifndef _CONSTANTS_H_
#define _CONSTANTS_H_
#include <QCoreApplication>
#define CPN_MAX_MODELS 60
#define CPN_MAX_TIMERS 3
#define CPN_MAX_FLIGHT_MODES 9
@@ -47,23 +49,23 @@
#define CPN_MAX_MOUSE_ANALOGS 2
#define CPN_MAX_ANALOGS (CPN_MAX_STICKS + CPN_MAX_POTS + CPN_MAX_MOUSE_ANALOGS)
#define CPN_STR_FILES QT_TRANSLATE_NOOP("CompanionMacros", "files")
#define CPN_STR_RAD_MOD_SETTINGS QT_TRANSLATE_NOOP("CompanionMacros", "Radio and Models settings")
#define HEX_FILES_FILTER "HEX " CPN_STR_FILES " (*.hex);;"
#define BIN_FILES_FILTER "BIN " CPN_STR_FILES " (*.bin);;"
#define DFU_FILES_FILTER "DFU " CPN_STR_FILES " (*.dfu);;"
#define EEPE_FILES_FILTER "EEPE " CPN_STR_FILES " (*.eepe);;"
#define OTX_FILES_FILTER "OpenTX " CPN_STR_FILES " (*.otx);;"
#define EEPROM_FILES_FILTER CPN_STR_RAD_MOD_SETTINGS " " CPN_STR_FILES " (*.otx *.eepe *.bin *.hex);;" OTX_FILES_FILTER EEPE_FILES_FILTER BIN_FILES_FILTER HEX_FILES_FILTER
#define FLASH_FILES_FILTER "FLASH " CPN_STR_FILES " (*.bin *.hex *.dfu);;" BIN_FILES_FILTER HEX_FILES_FILTER DFU_FILES_FILTER
#define EXTERNAL_EEPROM_FILES_FILTER "EEPROM " CPN_STR_FILES " (*.bin *.hex);;" BIN_FILES_FILTER HEX_FILES_FILTER
#define CPN_STR_FILES QCoreApplication::translate("Companion", "files")
#define CPN_STR_RAD_MOD_SETTINGS QCoreApplication::translate("Companion", "Radio and Models settings")
#define HEX_FILES_FILTER "HEX " % CPN_STR_FILES % " (*.hex);;"
#define BIN_FILES_FILTER "BIN " % CPN_STR_FILES % " (*.bin);;"
#define DFU_FILES_FILTER "DFU " % CPN_STR_FILES % " (*.dfu);;"
#define EEPE_FILES_FILTER "EEPE " % CPN_STR_FILES % " (*.eepe);;"
#define OTX_FILES_FILTER "OpenTX " % CPN_STR_FILES % " (*.otx);;"
#define EEPROM_FILES_FILTER CPN_STR_RAD_MOD_SETTINGS % " " % CPN_STR_FILES % " (*.otx *.eepe *.bin *.hex);;" % OTX_FILES_FILTER % EEPE_FILES_FILTER % BIN_FILES_FILTER % HEX_FILES_FILTER
#define FLASH_FILES_FILTER "FLASH " % CPN_STR_FILES % " (*.bin *.hex *.dfu);;" % BIN_FILES_FILTER % HEX_FILES_FILTER % DFU_FILES_FILTER
#define EXTERNAL_EEPROM_FILES_FILTER "EEPROM " % CPN_STR_FILES % " (*.bin *.hex);;" % BIN_FILES_FILTER % HEX_FILES_FILTER
#define ER9X_EEPROM_FILE_TYPE "ER9X_EEPROM_FILE"
#define EEPE_EEPROM_FILE_HEADER "EEPE EEPROM FILE"
#define EEPE_MODEL_FILE_HEADER "EEPE MODEL FILE"
#define CPN_STR_SW_INDICATOR_UP QT_TRANSLATE_NOOP("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
#define CPN_STR_SW_INDICATOR_DN QT_TRANSLATE_NOOP("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.
#define CPN_STR_SW_INDICATOR_NEUT QT_TRANSLATE_NOOP("RawSwitch", "-") // Switch neutral (middle) position indicator.
#define CPN_STR_SW_INDICATOR_REV QT_TRANSLATE_NOOP("RawSwitch", "!") // Switch reversed logic (NOT) indicator.
#define CPN_STR_SW_INDICATOR_UP QCoreApplication::translate("RawSwitch", "\xE2\x86\x91") // Switch up position indicator: Up arrow, or similar.
#define CPN_STR_SW_INDICATOR_DN QCoreApplication::translate("RawSwitch", "\xE2\x86\x93") // Switch down position indicator: Down arrow, or similar.
#define CPN_STR_SW_INDICATOR_NEUT QCoreApplication::translate("RawSwitch", "-") // Switch neutral (middle) position indicator.
#define CPN_STR_SW_INDICATOR_REV QCoreApplication::translate("RawSwitch", "!") // Switch reversed logic (NOT) indicator.
#endif // _CONSTANTS_H_
@@ -18,12 +18,12 @@
* GNU General Public License for more details.
*/
#include "contributorsdialog.h"
#include "creditsdialog.h"
#include "ui_htmldialog.h"
#include "helpers.h"
#include <QFile>
ContributorsDialog::ContributorsDialog(QWidget * parent):
CreditsDialog::CreditsDialog(QWidget * parent):
QDialog(parent),
ui(new Ui::HtmlDialog)
{
@@ -42,42 +42,8 @@ ContributorsDialog::ContributorsDialog(QWidget * parent):
"</head>"
"<body class=\"normal\">";
QFile credits(":/CREDITS.txt");
if (credits.open(QIODevice::ReadOnly | QIODevice::Text)) {
QStringList names;
while (!credits.atEnd()) {
QByteArray line = credits.readLine();
if (line.trimmed() == "")
break;
names.append(line.trimmed());
}
str.append(formatTable(tr("Main Developers"), names, 3));
names.clear();
while (!credits.atEnd()) {
QByteArray line = credits.readLine();
names.append(line.trimmed());
}
str.append(formatTable(tr("Other contributors"), names, 3));
}
QFile donations(":/DONATIONS.txt");
if (donations.open(QIODevice::ReadOnly | QIODevice::Text)) {
QStringList names;
while (!donations.atEnd()) {
QByteArray line = donations.readLine();
if (line.trimmed() == "")
break;
names.append(line.trimmed());
}
str.append(formatTable(tr("Companies and projects who have donated to OpenTX"), names, 3));
names.clear();
while (!donations.atEnd()) {
QByteArray line = donations.readLine();
names.append(line);
}
str.append(formatTable(tr("People who have donated to OpenTX"), names, 6));
foreach(CreditsSection section, readCredits()) {
str.append(formatTable(sectionTitle(section.title), section.names, 3));
}
str.append("<table><tr><td class=\"normal\">&nbsp;</td></tr>" \
@@ -87,9 +53,9 @@ ContributorsDialog::ContributorsDialog(QWidget * parent):
#if 0
QFile blacklist(":/BLACKLIST.txt");
if (blacklist.open(QIODevice::ReadOnly | QIODevice::Text)) {
QStringList names;
names << blacklist.readAll();
str.append(formatTable(tr("OpenTX Blacklist"), names, 1));
QStringList names;
names << blacklist.readAll();
str.append(formatTable(tr("OpenTX Blacklist"), names, 1));
}
#endif
@@ -99,12 +65,45 @@ ContributorsDialog::ContributorsDialog(QWidget * parent):
ui->textEditor->setOpenExternalLinks(true);
}
ContributorsDialog::~ContributorsDialog()
CreditsDialog::~CreditsDialog()
{
delete ui;
}
QString ContributorsDialog::formatTable(const QString & title, const QStringList & names, int columns)
QList<CreditsDialog::CreditsSection> CreditsDialog::readCredits()
{
QFile credits(":/CREDITS.txt");
QList<CreditsSection> result;
if (credits.open(QIODevice::ReadOnly | QIODevice::Text)) {
while (!credits.atEnd()) {
QByteArray line = credits.readLine().trimmed();
if (line.size() >= 2) {
if (line.startsWith("[") && line.endsWith("]")) {
result.push_back(CreditsSection(line.mid(1, line.size() - 2)));
} else {
result.back().addName(line);
}
}
}
}
return result;
}
QString CreditsDialog::sectionTitle(const QString & title)
{
if (title == "Main developers")
return tr("Main developers");
else if (title == "Translators")
return tr("Translators");
else if (title == "Companies and projects who have donated to OpenTX")
return tr("Companies and projects who have donated to OpenTX");
else if (title == "People who have donated to OpenTX")
return tr("People who have donated to OpenTX");
else
return tr("Other contributors");
}
QString CreditsDialog::formatTable(const QString & title, const QStringList & names, int columns)
{
const float cwidth = 100.0 / columns;
QString str = "<table width=\"100%\" border=0 cellspacing=0 cellpadding=2>" \
@@ -18,8 +18,8 @@
* GNU General Public License for more details.
*/
#ifndef _CONTRIBUTORSDIALOG_H_
#define _CONTRIBUTORSDIALOG_H_
#ifndef _CREDITSDIALOG_H_
#define _CREDITSDIALOG_H_
#include <QDialog>
@@ -27,17 +27,36 @@ namespace Ui {
class HtmlDialog;
}
class ContributorsDialog : public QDialog
class CreditsDialog : public QDialog
{
Q_OBJECT
class CreditsSection
{
public:
CreditsSection(const QString & title):
title(title)
{
}
void addName(const QString & name)
{
names.push_back(name);
}
QString title;
QStringList names;
};
public:
explicit ContributorsDialog(QWidget * parent = 0);
~ContributorsDialog();
explicit CreditsDialog(QWidget * parent = 0);
~CreditsDialog();
private:
Ui::HtmlDialog * ui;
QList<CreditsSection> readCredits();
QString sectionTitle(const QString & title);
QString formatTable(const QString & title, const QStringList & names, int colums);
};
#endif // _CONTRIBUTORSDIALOG_H_
#endif // _CREDITSDIALOG_H_
+23 -25
View File
@@ -150,11 +150,9 @@ bool Side::saveImage()
return true;
}
//*** customizeSplashDialog Class ***
customizeSplashDialog::customizeSplashDialog(QWidget *parent) :
CustomizeSplashDialog::CustomizeSplashDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::customizeSplashDialog)
ui(new Ui::CustomizeSplashDialog)
{
ui->setupUi(this);
setWindowIcon(CompanionIcon("paintbrush.png"));
@@ -185,22 +183,22 @@ customizeSplashDialog::customizeSplashDialog(QWidget *parent) :
resize(0,0);
}
customizeSplashDialog::~customizeSplashDialog()
CustomizeSplashDialog::~CustomizeSplashDialog()
{
delete ui;
}
void customizeSplashDialog::on_copyRightToLeftButton_clicked() {
void CustomizeSplashDialog::on_copyRightToLeftButton_clicked() {
left.copyImage(right);
}
void customizeSplashDialog::on_copyLeftToRightButton_clicked() {
void CustomizeSplashDialog::on_copyLeftToRightButton_clicked() {
right.copyImage(left);
}
void customizeSplashDialog::on_leftLoadFwButton_clicked() {loadFirmware(left);}
void customizeSplashDialog::on_rightLoadFwButton_clicked() {loadFirmware(right);}
void customizeSplashDialog::loadFirmware(Side side)
void CustomizeSplashDialog::on_leftLoadFwButton_clicked() {loadFirmware(left);}
void CustomizeSplashDialog::on_rightLoadFwButton_clicked() {loadFirmware(right);}
void CustomizeSplashDialog::loadFirmware(Side side)
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Firmware File"), g.flashDir(), FLASH_FILES_FILTER);
if (!fileName.isEmpty()) {
@@ -212,9 +210,9 @@ void customizeSplashDialog::loadFirmware(Side side)
side.markSourceButton();
}
void customizeSplashDialog::on_leftLoadPictButton_clicked() {loadPicture(left);}
void customizeSplashDialog::on_rightLoadPictButton_clicked() {loadPicture(right);}
void customizeSplashDialog::loadPicture(Side side)
void CustomizeSplashDialog::on_leftLoadPictButton_clicked() {loadPicture(left);}
void CustomizeSplashDialog::on_rightLoadPictButton_clicked() {loadPicture(right);}
void CustomizeSplashDialog::loadPicture(Side side)
{
QString supportedImageFormats;
for (int formatIndex = 0; formatIndex < QImageReader::supportedImageFormats().count(); formatIndex++) {
@@ -232,9 +230,9 @@ void customizeSplashDialog::loadPicture(Side side)
side.markSourceButton();
}
void customizeSplashDialog::on_leftLoadProfileButton_clicked() {loadProfile(left);}
void customizeSplashDialog::on_rightLoadProfileButton_clicked() {loadProfile(right);}
void customizeSplashDialog::loadProfile(Side side)
void CustomizeSplashDialog::on_leftLoadProfileButton_clicked() {loadProfile(left);}
void CustomizeSplashDialog::on_rightLoadProfileButton_clicked() {loadProfile(right);}
void CustomizeSplashDialog::loadProfile(Side side)
{
QString fileName=g.profile[g.id()].splashFile();
@@ -245,9 +243,9 @@ void customizeSplashDialog::loadProfile(Side side)
side.markSourceButton();
}
void customizeSplashDialog::on_leftLibraryButton_clicked(){libraryButton_clicked(left);}
void customizeSplashDialog::on_rightLibraryButton_clicked(){libraryButton_clicked(right);}
void customizeSplashDialog::libraryButton_clicked( Side side )
void CustomizeSplashDialog::on_leftLibraryButton_clicked(){libraryButton_clicked(left);}
void CustomizeSplashDialog::on_rightLibraryButton_clicked(){libraryButton_clicked(right);}
void CustomizeSplashDialog::libraryButton_clicked( Side side )
{
QString fileName;
SplashLibraryDialog *ld = new SplashLibraryDialog(this,&fileName);
@@ -258,9 +256,9 @@ void customizeSplashDialog::libraryButton_clicked( Side side )
}
}
void customizeSplashDialog::on_leftSaveButton_clicked(){saveButton_clicked(left);}
void customizeSplashDialog::on_rightSaveButton_clicked(){saveButton_clicked(right);}
void customizeSplashDialog::saveButton_clicked( Side side )
void CustomizeSplashDialog::on_leftSaveButton_clicked(){saveButton_clicked(left);}
void CustomizeSplashDialog::on_rightSaveButton_clicked(){saveButton_clicked(right);}
void CustomizeSplashDialog::saveButton_clicked( Side side )
{
if (side.saveImage()){
QMessageBox::information(this, tr("File Saved"), tr("The image was saved to the file %1").arg(*side.saveToFileName));
@@ -272,9 +270,9 @@ void customizeSplashDialog::saveButton_clicked( Side side )
QMessageBox::critical(this, tr("File Save Error"), tr("Failed to write image to %1").arg(*side.saveToFileName));
}
void customizeSplashDialog::on_leftInvertButton_clicked(){invertButton_clicked(left);}
void customizeSplashDialog::on_rightInvertButton_clicked(){invertButton_clicked(right);}
void customizeSplashDialog::invertButton_clicked(Side side)
void CustomizeSplashDialog::on_leftInvertButton_clicked(){invertButton_clicked(left);}
void CustomizeSplashDialog::on_rightInvertButton_clicked(){invertButton_clicked(right);}
void CustomizeSplashDialog::invertButton_clicked(Side side)
{
QImage image = side.imageLabel->pixmap()->toImage();
image.invertPixels();
+5 -5
View File
@@ -26,7 +26,7 @@
namespace Ui
{
class customizeSplashDialog;
class CustomizeSplashDialog;
}
const int WIDTH_TARANIS = 212;
@@ -63,15 +63,15 @@ private:
LCDFormat *format;
};
class customizeSplashDialog : public QDialog
class CustomizeSplashDialog : public QDialog
{
Q_OBJECT
Side left;
Side right;
public:
explicit customizeSplashDialog(QWidget *parent = 0);
~customizeSplashDialog();
explicit CustomizeSplashDialog(QWidget *parent = 0);
~CustomizeSplashDialog();
private slots:
void on_leftLoadFwButton_clicked();
@@ -99,7 +99,7 @@ private:
void saveButton_clicked( Side );
void invertButton_clicked( Side );
Ui::customizeSplashDialog *ui;
Ui::CustomizeSplashDialog *ui;
enum sideEnum { LEFT, RIGHT };
};
+2 -2
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>customizeSplashDialog</class>
<widget class="QDialog" name="customizeSplashDialog">
<class>CustomizeSplashDialog</class>
<widget class="QDialog" name="CustomizeSplashDialog">
<property name="enabled">
<bool>true</bool>
</property>
+83 -64
View File
@@ -134,27 +134,6 @@ int TimToVal(float value)
return (temp-129);
}
QString getSignedStr(int value)
{
return value > 0 ? QString("+%1").arg(value) : QString("%1").arg(value);
}
QString getGVarString(int16_t val, bool sign)
{
if (val >= -10000 && val <= 10000) {
if (sign)
return QString("%1%").arg(getSignedStr(val));
else
return QString("%1%").arg(val);
}
else {
if (val<0)
return QObject::tr("-GV%1").arg(-val-10000);
else
return QObject::tr("GV%1").arg(val-10000);
}
}
void SensorData::updateUnit()
{
if (type == TELEM_TYPE_CALCULATED) {
@@ -494,17 +473,6 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting
return result;
}
QString RotaryEncoderString(int index)
{
static const QString rotary[] = { QObject::tr("REa"), QObject::tr("REb") };
return CHECK_IN_ARRAY(rotary, index);
}
/*
* RawSource
*/
QString RawSource::toString(const ModelData * model, const GeneralSettings * const generalSettings) const
{
static const QString trims[] = {
@@ -530,6 +498,8 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
QObject::tr("ACC"), QObject::tr("GPS Time"),
};
static const QString rotary[] = { QObject::tr("REa"), QObject::tr("REb") };
if (index<0) {
return QObject::tr("----");
}
@@ -538,9 +508,9 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
int genAryIdx = 0;
switch (type) {
case SOURCE_TYPE_VIRTUAL_INPUT:
result = QObject::tr("[I%1]").arg(index+1);
if (model)
result += QString(model->inputNames[index]);
result = QObject::tr("[I%1]").arg(index+1, 2, 10, QChar('0'));
if (model && model->inputNames[index][0])
result.append(/*":" + */QString(model->inputNames[index]).trimmed());
return result;
case SOURCE_TYPE_LUA_OUTPUT:
@@ -552,8 +522,8 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
result = QString(generalSettings->potName[genAryIdx]);
else if (isSlider(&genAryIdx))
result = QString(generalSettings->sliderName[genAryIdx]);
else
result = QString(generalSettings->stickName[index]);
else if (isStick(&genAryIdx))
result = QString(generalSettings->stickName[genAryIdx]);
}
if (result.isEmpty())
result = getCurrentFirmware()->getAnalogInputName(index);;
@@ -562,7 +532,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
case SOURCE_TYPE_TRIM:
return CHECK_IN_ARRAY(trims, index);
case SOURCE_TYPE_ROTARY_ENCODER:
return RotaryEncoderString(index);
return CHECK_IN_ARRAY(rotary, index);
case SOURCE_TYPE_MAX:
return QObject::tr("MAX");
@@ -574,16 +544,19 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
return result;
case SOURCE_TYPE_CUSTOM_SWITCH:
return QObject::tr("L%1").arg(index+1);
return RawSwitch(SWITCH_TYPE_VIRTUAL, index+1).toString();
case SOURCE_TYPE_CYC:
return QObject::tr("CYC%1").arg(index+1);
case SOURCE_TYPE_PPM:
return QObject::tr("TR%1").arg(index+1);
return QObject::tr("TR%1").arg(index+1, 2, 10, QChar('0'));
case SOURCE_TYPE_CH:
return QObject::tr("CH%1").arg(index+1);
result = QObject::tr("CH%1").arg(index+1, 2, 10, QChar('0'));
if (getCurrentFirmware()->getCapability(ChannelsName) && model && model->limitData[index].name[0])
result.append(":" + QString(model->limitData[index].name).trimmed());
return result;
case SOURCE_TYPE_SPECIAL:
return CHECK_IN_ARRAY(special, index);
@@ -591,7 +564,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
case SOURCE_TYPE_TELEMETRY:
if (IS_ARM(getCurrentBoard())) {
div_t qr = div(index, 3);
result = model ? QString(model->sensorData[qr.quot].label) : QString("[T%1]").arg(qr.quot+1);
result = model ? QString(model->sensorData[qr.quot].label) : QString("[T%1]").arg(qr.quot+1, 2, 10, QChar('0'));
if (qr.rem)
result += (qr.rem == 1 ? "-" : "+");
return result;
@@ -601,13 +574,26 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con
}
case SOURCE_TYPE_GVAR:
return QObject::tr("GV%1").arg(index+1);
result = QObject::tr("GV%1").arg(index+1, 2, 10, QChar('0'));
if (getCurrentFirmware()->getCapability(GvarsName) && model && model->gvars_names[index][0])
result.append(":" + QString(model->gvars_names[index]).trimmed());
return result;
default:
return QObject::tr("----");
}
}
bool RawSource::isStick(int * stickIndex) const
{
if (type == SOURCE_TYPE_STICK && index < getBoardCapability(getCurrentBoard(), Board::Sticks)) {
if (stickIndex)
*stickIndex = index;
return true;
}
return false;
}
bool RawSource::isPot(int * potsIndex) const
{
if (type == SOURCE_TYPE_STICK &&
@@ -696,7 +682,7 @@ QString RawSwitch::toString(Board::Type board, const GeneralSettings * const gen
}
case SWITCH_TYPE_VIRTUAL:
return QObject::tr("L%1").arg(index);
return QObject::tr("L%1").arg(index, 2, 10, QChar('0'));
case SWITCH_TYPE_MULTIPOS_POT:
if (!getCurrentFirmware()->getCapability(MultiposPotsPositions))
@@ -743,23 +729,48 @@ QString RawSwitch::toString(Board::Type board, const GeneralSettings * const gen
* CurveReference
*/
QString CurveReference::toString() const
QString CurveReference::toString(const ModelData * model, bool verbose) const
{
if (value == 0) {
return "----";
}
else {
switch(type) {
case CURVE_REF_DIFF:
return QObject::tr("Diff(%1)").arg(getGVarString(value));
case CURVE_REF_EXPO:
return QObject::tr("Expo(%1)").arg(getGVarString(value));
case CURVE_REF_FUNC:
return QObject::tr("Function(%1)").arg(QString("x>0" "x<0" "|x|" "f>0" "f<0" "|f|").mid(3*(value-1), 3));
default:
return QString(value > 0 ? QObject::tr("Curve(%1)") : QObject::tr("!Curve(%1)")).arg(abs(value));
}
QString ret;
unsigned idx = abs(value) - 1;
switch(type) {
case CURVE_REF_DIFF:
ret = QObject::tr("Diff(%1)").arg(Helpers::getAdjustmentString(value, model));
break;
case CURVE_REF_EXPO:
ret = QObject::tr("Expo(%1)").arg(Helpers::getAdjustmentString(value, model));
break;
case CURVE_REF_FUNC:
ret = QString("x>0" "x<0" "|x|" "f>0" "f<0" "|f|").mid(3*(value-1), 3);
if (verbose)
ret = QObject::tr("Function(%1)").arg(ret);
break;
default:
if (model)
ret = model->curves[idx].nameToString(idx);
else
ret = CurveData().nameToString(idx);
if (verbose)
ret = QObject::tr("Curve(%1)").arg(ret);
if (value < 0)
ret.prepend(CPN_STR_SW_INDICATOR_REV);
break;
}
return ret;
}
bool LogicalSwitchData::isEmpty() const
{
return (func == 0);
}
CSFunctionFamily LogicalSwitchData::getFunctionFamily() const
@@ -846,10 +857,15 @@ void CustomFunctionData::clear()
}
}
QString CustomFunctionData::funcToString() const
bool CustomFunctionData::isEmpty() const
{
return (swtch.type == SWITCH_TYPE_NONE);
}
QString CustomFunctionData::funcToString(const ModelData * model) const
{
if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32)
return QObject::tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString());
return QObject::tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model));
else if (func == FuncTrainer)
return QObject::tr("Trainer");
else if (func == FuncTrainerRUD)
@@ -893,7 +909,7 @@ QString CustomFunctionData::funcToString() const
else if (func == FuncBackgroundMusicPause)
return QObject::tr("Background Music Pause");
else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast)
return QObject::tr("Adjust GV%1").arg(func-FuncAdjustGV1+1);
return QObject::tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model));
else if (func == FuncSetFailsafeInternalModule)
return QObject::tr("SetFailsafe Int. Module");
else if (func == FuncSetFailsafeExternalModule)
@@ -1068,6 +1084,14 @@ bool CurveData::isEmpty() const
return true;
}
QString CurveData::nameToString(const int idx) const
{
QString ret = QCoreApplication::translate("CurveData", "CV%1").arg(idx+1, 2, 10, QChar('0'));
if (name[0])
ret.append(":" + QString(name).trimmed());
return ret;
}
QString LimitData::minToString() const
{
return QString::number((qreal)min/10);
@@ -1494,11 +1518,6 @@ void ModelData::clearMixes()
mixData[i].clear();
}
RadioData::RadioData()
{
models.resize(getCurrentFirmware()->getCapability(Models));
}
void ModelData::clear()
{
memset(this, 0, sizeof(ModelData));
-6
View File
@@ -30,8 +30,6 @@
#include <iostream>
#include <QDebug>
QString RotaryEncoderString(int index);
const uint8_t modn12x3[4][4]= {
{1, 2, 3, 4},
{1, 3, 2, 4},
@@ -52,7 +50,6 @@ enum Capability {
VoicesMaxLength,
MultiLangVoice,
ModelImage,
SwitchesPositions,
CustomFunctions,
SafetyChannelCustomFunction,
LogicalSwitches,
@@ -187,9 +184,6 @@ void getEEPROMString(char *dst, const char *src, int size);
float ValToTim(int value);
int TimToVal(float value);
QString getSignedStr(int value);
QString getGVarString(int16_t val, bool sign=false);
inline int applyStickMode(int stick, unsigned int mode)
{
if (mode == 0 || mode > 4) {
@@ -243,9 +243,12 @@ class SourcesConversionTable: public ConversionTable {
for (int i=0; i<32; i++) {
addConversion(RawSource(SOURCE_TYPE_VIRTUAL_INPUT, i), val++);
}
for (int i=0; i<MAX_SCRIPTS(board); i++) {
for (int j=0; j<6; j++) {
addConversion(RawSource(SOURCE_TYPE_LUA_OUTPUT, i*16+j), val++);
}
if (IS_STM32(board) && version >= 216) {
for (int i = 0; i < MAX_SCRIPTS(board); i++) {
for (int j = 0; j < 6; j++) {
addConversion(RawSource(SOURCE_TYPE_LUA_OUTPUT, i * 16 + j), val++);
}
}
}
@@ -881,7 +884,7 @@ class FlightModeField: public TransformedField {
virtual void beforeExport()
{
for (int i=0; i<CPN_MAX_STICKS+MAX_AUX_TRIMS(board); i++) {
if (IS_HORUS_OR_TARANIS(board) && version >= 216) {
if ((IS_HORUS_OR_TARANIS(board) && version >= 216) || (IS_ARM(board) && version >= 218)) {
if (phase.trimMode[i] < 0)
trimMode[i] = TRIM_MODE_NONE;
else
@@ -909,7 +912,7 @@ class FlightModeField: public TransformedField {
virtual void afterImport()
{
for (int i=0; i<CPN_MAX_STICKS+MAX_AUX_TRIMS(board); i++) {
if (IS_HORUS_OR_TARANIS(board) && version >= 216) {
if ((IS_HORUS_OR_TARANIS(board) && version >= 216) || (IS_ARM(board) && version >= 218)) {
if (trimMode[i] == TRIM_MODE_NONE) {
phase.trimMode[i] = -1;
}
@@ -1204,7 +1207,7 @@ class MixField: public TransformedField {
if (mix.srcRaw.type != SOURCE_TYPE_NONE) {
mix.destCh = _destCh + 1;
if (!IS_STM32(board) || version < 216) {
if (!IS_ARM(board) || (!IS_STM32(board) && version < 218) || version < 216) {
if (!_curveMode)
mix.curve = CurveReference(CurveReference::CURVE_REF_DIFF, smallGvarToC9x(_curveParam));
else if (_curveParam > 6)
@@ -1407,7 +1410,7 @@ class InputField: public TransformedField {
expo.offset = smallGvarToC9x(_offset);
}
if (!IS_STM32(board) || version < 216) {
if (!IS_ARM(board) || (!IS_STM32(board) && version < 218) || version < 216) {
if (!_curveMode)
expo.curve = CurveReference(CurveReference::CURVE_REF_EXPO, smallGvarToC9x(_curveParam));
else if (_curveParam > 6)
@@ -1592,7 +1595,7 @@ class CurvesField: public TransformedField {
for (int i=0; i<maxCurves; i++) {
CurveData * curve = &curves[i];
if (!IS_STM32(board) || version < 216) {
if (!IS_ARM(board) || (!IS_STM32(board) && version < 218) || version < 216) {
int * next = &_points[5*(i+1) + _curves[i]];
int size = next - cur;
if (size % 2 == 0) {
@@ -26,6 +26,7 @@
#include <QMessageBox>
#include <QTime>
#include <QUrl>
#include <companion/src/storage/storage.h>
using namespace Board;
@@ -95,30 +96,6 @@ const char * OpenTxEepromInterface::getName()
}
}
uint32_t OpenTxEepromInterface::getFourCC()
{
switch (board) {
case BOARD_X12S:
case BOARD_X10:
return 0x3478746F;
case BOARD_TARANIS_X7:
return 0x3678746F;
case BOARD_TARANIS_X9E:
return 0x3578746F;
case BOARD_TARANIS_X9D:
case BOARD_TARANIS_X9DP:
return 0x3378746F;
case BOARD_SKY9X:
case BOARD_AR9X:
return 0x3278746F;
case BOARD_MEGA2560:
case BOARD_GRUVIN9X:
return 0x3178746F;
default:
return 0;
}
}
bool OpenTxEepromInterface::loadRadioSettingsFromRLE(GeneralSettings & settings, RleFile * rleFile, uint8_t version)
{
QByteArray data(sizeof(settings), 0); // GeneralSettings should be always bigger than the EEPROM struct
@@ -163,7 +140,7 @@ bool OpenTxEepromInterface::saveToByteArray(const T & src, QByteArray & data, ui
// manager.Dump();
manager.Export(raw);
data.resize(8);
*((uint32_t*)&data.data()[0]) = getFourCC();
*((uint32_t*)&data.data()[0]) = StorageFormat::getFourCC(board);
data[4] = version;
data[5] = 'M';
*((uint16_t*)&data.data()[6]) = raw.size();
@@ -186,12 +163,12 @@ template <class T, class M>
bool OpenTxEepromInterface::loadFromByteArray(T & dest, const QByteArray & data)
{
uint32_t fourcc = *((uint32_t*)&data.data()[0]);
if (getFourCC() != fourcc) {
if (StorageFormat::getFourCC(board) != fourcc) {
if (IS_HORUS(board) && fourcc == 0x3178396F) {
qDebug() << QString().sprintf("%s: Deprecated fourcc used %x vs %x", getName(), fourcc, getFourCC());
qDebug() << QString().sprintf("%s: Deprecated fourcc used %x vs %x", getName(), fourcc, StorageFormat::getFourCC(board));
}
else {
qDebug() << QString().sprintf("%s: Wrong fourcc %x vs %x", getName(), fourcc, getFourCC());
qDebug() << QString().sprintf("%s: Wrong fourcc %x vs %x", getName(), fourcc, StorageFormat::getFourCC(board));
return false;
}
}
@@ -273,7 +250,7 @@ unsigned long OpenTxEepromInterface::load(RadioData &radioData, const uint8_t *
radioData.models.resize(firmware->getCapability(Models));
}
for (int i = 0; i < firmware->getCapability(Models); i++) {
if (!loadModelFromRLE(radioData.models[i], efile, i, version, radioData.generalSettings.variant)) {
if (i < (int)radioData.models.size() && !loadModelFromRLE(radioData.models[i], efile, i, version, radioData.generalSettings.variant)) {
std::cout << " ko\n";
errors.set(UNKNOWN_ERROR);
if (getCurrentFirmware()->getCapability(Models) == 0) {
@@ -512,11 +489,6 @@ int OpenTxFirmware::getCapability(::Capability capability)
return 0;
case PermTimers:
return (IS_2560(board) || IS_ARM(board));
case SwitchesPositions:
if (IS_HORUS_OR_TARANIS(board))
return getBoardCapability(board, Board::Switches) * 3;
else
return 9;
case CustomFunctions:
if (IS_ARM(board))
return 64;
@@ -72,8 +72,6 @@ class OpenTxEepromInterface : public EEPROMInterface
uint8_t getLastDataVersion(Board::Type board);
uint32_t getFourCC();
RleFile * efile;
OpenTxFirmware * firmware;
+1 -1
View File
@@ -102,7 +102,7 @@ void FlashEEpromDialog::updateUI()
void FlashEEpromDialog::on_eepromLoad_clicked()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Choose Radio Backup file"), g.eepromDir(), tr(EXTERNAL_EEPROM_FILES_FILTER));
QString filename = QFileDialog::getOpenFileName(this, tr("Choose Radio Backup file"), g.eepromDir(), EXTERNAL_EEPROM_FILES_FILTER);
if (!filename.isEmpty()) {
eepromFilename = filename;
updateUI();
+3 -9
View File
@@ -34,12 +34,6 @@ FirmwarePreferencesDialog::FirmwarePreferencesDialog(QWidget *parent) :
ui->setupUi(this);
setWindowIcon(CompanionIcon("fwpreferences.png"));
initSettings();
foreach(const char *lang, getCurrentFirmware()->getFirmwareBase()->ttslanguages) {
ui->voiceCombo->addItem(lang);
if (Firmware::getCurrentVariant()->getId().contains(QString("-tts%1").arg(lang)))
ui->voiceCombo->setCurrentIndex(ui->voiceCombo->count() - 1);
}
}
FirmwarePreferencesDialog::~FirmwarePreferencesDialog()
@@ -70,13 +64,13 @@ void FirmwarePreferencesDialog::on_fw_dnld_clicked()
initSettings();
}
void FirmwarePreferencesDialog::on_voice_dnld_clicked()
void FirmwarePreferencesDialog::on_sd_dnld_clicked()
{
QString url = "http://voices-21.open-tx.org/";
QString url = "http://downloads.open-tx.org/2.2/sdcard/";
QString fwType = g.profile[g.id()].fwType();
QStringList list = fwType.split("-");
QString firmware = QString("%1-%2").arg(list[0]).arg(list[1]);
url.append(QString("%1/%2/").arg(firmware).arg(ui->voiceCombo->currentText().toLower()));
url.append(QString("%1/").arg(firmware));
QDesktopServices::openUrl(url);
}
+1 -1
View File
@@ -45,7 +45,7 @@ class FirmwarePreferencesDialog : public QDialog
private slots:
void on_fw_dnld_clicked();
void on_voice_dnld_clicked();
void on_sd_dnld_clicked();
void on_checkFWUpdates_clicked();
};
+59 -86
View File
@@ -26,13 +26,22 @@
<string>Downloads</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>6</number>
</property>
<item row="24" column="5">
<item row="23" column="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -42,7 +51,7 @@
</property>
</widget>
</item>
<item row="3" column="5">
<item row="3" column="3">
<widget class="QPushButton" name="checkFWUpdates">
<property name="minimumSize">
<size>
@@ -55,75 +64,6 @@
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="voiceLabel">
<property name="font">
<font>
<family>Sans Serif</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Voice</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QComboBox" name="voiceCombo">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Set voice language.
May be different from firmware language</string>
</property>
</widget>
</item>
<item row="7" column="5">
<widget class="QPushButton" name="voice_dnld">
<property name="text">
<string>Download Voice</string>
</property>
</widget>
</item>
<item row="5" column="5">
<widget class="QPushButton" name="fw_dnld">
<property name="text">
<string>Download FW</string>
</property>
</widget>
</item>
<item row="7" column="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="0" colspan="6">
<widget class="Line" name="voiceLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="23" column="0" colspan="6">
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
@@ -147,20 +87,28 @@ May be different from firmware language</string>
</property>
</widget>
</item>
<item row="0" column="2" colspan="4">
<widget class="QLabel" name="fwTypeLbl">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="5" column="3">
<widget class="QPushButton" name="fw_dnld">
<property name="text">
<string notr="true">FwType</string>
<string>Download firmware</string>
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<item row="22" column="0" colspan="4">
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QPushButton" name="sd_dnld">
<property name="text">
<string>Download SD contents</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLabel" name="lastRevisionLbl">
<property name="text">
<string notr="true">-</string>
@@ -174,13 +122,38 @@ May be different from firmware language</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLabel" name="fwTypeLbl">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">FwType</string>
</property>
</widget>
</item>
<item row="6" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<tabstops>
<tabstop>checkFWUpdates</tabstop>
<tabstop>fw_dnld</tabstop>
<tabstop>voiceCombo</tabstop>
<tabstop>voice_dnld</tabstop>
<tabstop>sd_dnld</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
+39 -22
View File
@@ -21,7 +21,7 @@
#include "hardware.h"
#include "ui_hardware.h"
void HardwarePanel::setupSwitchType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type, bool threePos = true)
void HardwarePanel::setupSwitchType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type, bool threePos)
{
Board::Type board = getCurrentBoard();
if (IS_STM32(board) && index < getBoardCapability(board, Board::Switches)) {
@@ -92,7 +92,7 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
ui(new Ui::Hardware)
{
ui->setupUi(this);
Board::Type board = firmware->getBoard();
if (IS_STM32(board)) {
@@ -110,6 +110,8 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
ui->thrName->hide();
ui->ailLabel->hide();
ui->ailName->hide();
ui->potsTypeSeparator_1->hide();
ui->potsTypeSeparator_2->hide();
}
setupPotType(0, ui->pot1Label, ui->pot1Name, ui->pot1Type);
@@ -141,10 +143,11 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
setupSwitchType(16, ui->sqLabel, ui->sqName, ui->sqType);
setupSwitchType(17, ui->srLabel, ui->srName, ui->srType);
if (IS_HORUS_OR_TARANIS(board) && !IS_TARANIS_X7(board)) {
if (IS_TARANIS(board) && !IS_TARANIS_X7(board)) {
ui->serialPortMode->setCurrentIndex(generalSettings.hw_uartMode);
}
else {
ui->serialPortMode->setCurrentIndex(0);
ui->serialPortMode->hide();
ui->serialPortLabel->hide();
}
@@ -160,10 +163,9 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings
}
else {
ui->bluetoothLabel->hide();
ui->bluetoothEnable->hide();
ui->bluetoothName->hide();
ui->bluetoothWidget->hide();
}
if (IS_HORUS_OR_TARANIS(board)) {
ui->filterEnable->setChecked(!generalSettings.jitterFilter);
}
@@ -188,39 +190,52 @@ void HardwarePanel::on_filterEnable_stateChanged()
void HardwarePanel::on_PPM_MultiplierDSB_editingFinished()
{
generalSettings.PPM_Multiplier = (int)(ui->PPM_MultiplierDSB->value()*10)-10;
emit modified();
int val = (int)(ui->PPM_MultiplierDSB->value()*10)-10;
if (generalSettings.PPM_Multiplier != val) {
generalSettings.PPM_Multiplier = val;
emit modified();
}
}
void HardwarePanel::on_PPM1_editingFinished()
{
generalSettings.trainer.calib[0] = ui->PPM1->value();
emit modified();
if (generalSettings.trainer.calib[0] != ui->PPM1->value()) {
generalSettings.trainer.calib[0] = ui->PPM1->value();
emit modified();
}
}
void HardwarePanel::on_PPM2_editingFinished()
{
generalSettings.trainer.calib[1] = ui->PPM2->value();
emit modified();
if (generalSettings.trainer.calib[1] != ui->PPM2->value()) {
generalSettings.trainer.calib[1] = ui->PPM2->value();
emit modified();
}
}
void HardwarePanel::on_PPM3_editingFinished()
{
generalSettings.trainer.calib[2] = ui->PPM3->value();
emit modified();
if (generalSettings.trainer.calib[2] != ui->PPM3->value()) {
generalSettings.trainer.calib[2] = ui->PPM3->value();
emit modified();
}
}
void HardwarePanel::on_PPM4_editingFinished()
{
generalSettings.trainer.calib[3] = ui->PPM4->value();
emit modified();
if (generalSettings.trainer.calib[3] != ui->PPM4->value()) {
generalSettings.trainer.calib[3] = ui->PPM4->value();
emit modified();
}
}
void HardwarePanel::on_txCurrentHardware_editingFinished()
void HardwarePanel::on_txCurrentCalibration_editingFinished()
{
generalSettings.txCurrentCalibration = ui->txCurrentCalibration->value();
emit modified();
if (generalSettings.txCurrentCalibration != ui->txCurrentCalibration->value()) {
generalSettings.txCurrentCalibration = ui->txCurrentCalibration->value();
emit modified();
}
}
void HardwarePanel::on_bluetoothEnable_stateChanged(int)
@@ -241,10 +256,12 @@ void HardwarePanel::setValues()
ui->PPM_MultiplierDSB->setValue((qreal)(generalSettings.PPM_Multiplier+10)/10);
}
void HardwarePanel::on_txVoltageHardware_editingFinished()
void HardwarePanel::on_txVoltageCalibration_editingFinished()
{
generalSettings.txVoltageCalibration = ui->txVoltageCalibration->value()*10;
emit modified();
if (generalSettings.txVoltageCalibration != ui->txVoltageCalibration->value()*10) {
generalSettings.txVoltageCalibration = ui->txVoltageCalibration->value()*10;
emit modified();
}
}
void HardwarePanel::on_serialPortMode_currentIndexChanged(int index)
+3 -3
View File
@@ -40,14 +40,14 @@ class HardwarePanel : public GeneralPanel
virtual ~HardwarePanel();
private slots:
void on_txVoltageHardware_editingFinished();
void on_PPM1_editingFinished();
void on_PPM2_editingFinished();
void on_PPM3_editingFinished();
void on_PPM4_editingFinished();
void on_PPM_MultiplierDSB_editingFinished();
void on_txCurrentHardware_editingFinished();
void on_txCurrentCalibration_editingFinished();
void on_txVoltageCalibration_editingFinished();
void on_bluetoothEnable_stateChanged(int);
void on_filterEnable_stateChanged();
@@ -56,7 +56,7 @@ class HardwarePanel : public GeneralPanel
protected:
void setupPotType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type);
void setupSliderType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type);
void setupSwitchType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type, bool threePos);
void setupSwitchType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type, bool threePos = true);
private:
Ui::Hardware *ui;
+120 -65
View File
@@ -6,14 +6,23 @@
<rect>
<x>0</x>
<y>0</y>
<width>359</width>
<height>1594</height>
<width>470</width>
<height>1095</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" columnstretch="0,0,0,0,0">
<layout class="QGridLayout" name="gridLayout_2">
<property name="spacing">
<number>6</number>
</property>
<item row="29" column="0">
<widget class="QLabel" name="sqLabel">
<property name="text">
@@ -125,19 +134,6 @@
</property>
</widget>
</item>
<item row="12" column="0" colspan="5">
<widget class="Line" name="potsTypeSeparator_2">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="AutoLineEdit" name="pot2Name">
<property name="maxLength">
@@ -730,32 +726,6 @@
</property>
</widget>
</item>
<item row="31" column="0" colspan="4">
<widget class="Line" name="potsTypeSeparator_3">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="38" column="0" colspan="4">
<widget class="Line" name="potsTypeSeparator_4">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="25" column="0">
<widget class="QLabel" name="smLabel">
<property name="text">
@@ -1075,6 +1045,12 @@
</item>
<item row="32" column="0">
<widget class="QLabel" name="bluetoothLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Bluetooth</string>
</property>
@@ -1090,24 +1066,6 @@
</property>
</widget>
</item>
<item row="32" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="bluetoothEnable">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="AutoLineEdit" name="bluetoothName">
<property name="maxLength">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="33" column="1">
<widget class="QCheckBox" name="filterEnable">
<property name="text">
@@ -1122,19 +1080,116 @@
</property>
</widget>
</item>
<item row="32" column="1">
<widget class="QWidget" name="bluetoothWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="bluetoothEnable">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="btNameLabel">
<property name="text">
<string>Device Name:</string>
</property>
</widget>
</item>
<item>
<widget class="AutoLineEdit" name="bluetoothName">
<property name="maxLength">
<number>10</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="31" column="0" colspan="3">
<widget class="Line" name="potsTypeSeparator_2">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="38" column="0" colspan="3">
<widget class="Line" name="ppmSeparator">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="12" column="0" colspan="3">
<widget class="Line" name="potsTypeSeparator_1">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AutoLineEdit</class>
<extends>QLineEdit</extends>
<header>autolineedit.h</header>
</customwidget>
<customwidget>
<class>AutoComboBox</class>
<extends>QComboBox</extends>
<header>autocombobox.h</header>
</customwidget>
<customwidget>
<class>AutoLineEdit</class>
<extends>QLineEdit</extends>
<header>autolineedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
+40 -57
View File
@@ -225,7 +225,7 @@ void CurveGroup::update()
lastType = curve.type;
curveValueCB->clear();
for (int i=0; i<=6/*TODO constant*/; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_FUNC, i).toString());
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_FUNC, i).toString(&model, false));
}
}
curveValueCB->setCurrentIndex(curve.value);
@@ -237,7 +237,7 @@ void CurveGroup::update()
lastType = curve.type;
curveValueCB->clear();
for (int i= ((flags & HIDE_NEGATIVE_CURVES) ? 0 : -numcurves); i<=numcurves; i++) {
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, i).toString(), i);
curveValueCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, i).toString(&model, false), i);
if (i == curve.value) {
curveValueCB->setCurrentIndex(curveValueCB->count() - 1);
}
@@ -324,38 +324,43 @@ void CurveGroup::valuesChanged()
void Helpers::populateGVCB(QComboBox & b, int value, const ModelData & model)
{
bool selected = false;
int count = getCurrentFirmware()->getCapability(Gvars);
b.clear();
int count = getCurrentFirmware()->getCapability(Gvars);
for (int i=-count; i<=-1; i++) {
int16_t gval = (int16_t)(-10000+i);
if (strlen(model.gvars_names[-i-1]) > 0)
b.addItem(QObject::tr("-GV%1 (%2)").arg(-i).arg(model.gvars_names[-i-1]), gval);
else
b.addItem(QObject::tr("-GV%1").arg(-i), gval);
if (value == gval) {
b.setCurrentIndex(b.count()-1);
selected = true;
}
b.addItem("-" + RawSource(SOURCE_TYPE_GVAR, abs(i)-1).toString(&model), gval);
}
for (int i=1; i<=count; i++) {
int16_t gval = (int16_t)(10000+i);
if (strlen(model.gvars_names[i-1]) > 0)
b.addItem(QObject::tr("GV%1 (%2)").arg(i).arg(model.gvars_names[i-1]), gval);
else
b.addItem(QObject::tr("GV%1").arg(i), gval);
if (value == gval) {
b.setCurrentIndex(b.count()-1);
selected = true;
}
b.addItem(RawSource(SOURCE_TYPE_GVAR, i-1).toString(&model), gval);
}
if (!selected) {
b.setCurrentIndex(b.findData(value));
if (b.currentIndex() == -1)
b.setCurrentIndex(count);
}
// Returns Diff/Expo/Weight/Offset adjustment value as either a percentage or a global variable name.
QString Helpers::getAdjustmentString(int16_t val, const ModelData * model, bool sign)
{
QString ret;
if (val >= -10000 && val <= 10000) {
ret = "%1%";
if (sign && val > 0)
ret.prepend("+");
ret = ret.arg(val);
}
else {
ret = RawSource(SOURCE_TYPE_GVAR, abs(val) - 10001).toString(model);
if (val < 0)
ret.prepend("-");
else if (sign)
ret.prepend("+");
}
return ret;
}
void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
@@ -368,29 +373,6 @@ void Helpers::populateGvarUseCB(QComboBox * b, unsigned int phase)
}
}
void Helpers::populateGvSourceCB(QComboBox * b, int value)
{
QString strings[] = { QObject::tr("---"), QObject::tr("Rud Trim"), QObject::tr("Ele Trim"), QObject::tr("Thr Trim"), QObject::tr("Ail Trim"), QObject::tr("Rot Enc"), QObject::tr("Rud"), QObject::tr("Ele"), QObject::tr("Thr"), QObject::tr("Ail"), QObject::tr("P1"), QObject::tr("P2"), QObject::tr("P3")};
b->clear();
for (int i=0; i<= 12; i++) {
b->addItem(strings[i]);
}
b->setCurrentIndex(value);
}
void Helpers::populatePhasesCB(QComboBox * b, int value)
{
for (int i=-getCurrentFirmware()->getCapability(FlightModes); i<=getCurrentFirmware()->getCapability(FlightModes); i++) {
if (i < 0)
b->addItem(QObject::tr("!Flight mode %1").arg(-i-1), i);
else if (i > 0)
b->addItem(QObject::tr("Flight mode %1").arg(i-1), i);
else
b->addItem(QObject::tr("----"), 0);
}
b->setCurrentIndex(value + getCurrentFirmware()->getCapability(FlightModes));
}
void Helpers::populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current)
{
b->clear();
@@ -456,21 +438,22 @@ void Helpers::addRawSwitchItems(QStandardItemModel * itemModel, const RawSwitchT
QStandardItemModel * Helpers::getRawSwitchItemModel(const GeneralSettings * const generalSettings, SwitchContext context)
{
QStandardItemModel * itemModel = new QStandardItemModel();
Board::Type board = getCurrentBoard();
Boards board = Boards(getCurrentBoard());
Board::Type btype = board.getBoardType();
Firmware * fw = getCurrentFirmware();
// Descending switch direction: NOT (!) switches
if (context != MixesContext && context != GlobalFunctionsContext && IS_ARM(board)) {
if (context != MixesContext && context != GlobalFunctionsContext && IS_ARM(btype)) {
addRawSwitchItems(itemModel, SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes), generalSettings);
}
if (context != GlobalFunctionsContext) {
addRawSwitchItems(itemModel, SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches), generalSettings);
}
addRawSwitchItems(itemModel, SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_TRIM, -getBoardCapability(board, Board::NumTrimSwitches), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_TRIM, -board.getCapability(Board::NumTrimSwitches), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_MULTIPOS_POT, -(fw->getCapability(MultiposPots) * fw->getCapability(MultiposPotsPositions)), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_SWITCH, -fw->getCapability(SwitchesPositions), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_SWITCH, -board.getCapability(Board::SwitchPositions), generalSettings);
// Ascending switch direction (including zero)
@@ -481,14 +464,14 @@ QStandardItemModel * Helpers::getRawSwitchItemModel(const GeneralSettings * cons
addRawSwitchItems(itemModel, SWITCH_TYPE_NONE, 1);
}
addRawSwitchItems(itemModel, SWITCH_TYPE_SWITCH, fw->getCapability(SwitchesPositions), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_SWITCH, board.getCapability(Board::SwitchPositions), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_MULTIPOS_POT, fw->getCapability(MultiposPots) * fw->getCapability(MultiposPotsPositions), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_TRIM, getBoardCapability(board, Board::NumTrimSwitches), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_TRIM, board.getCapability(Board::NumTrimSwitches), generalSettings);
addRawSwitchItems(itemModel, SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders), generalSettings);
if (context != GlobalFunctionsContext) {
addRawSwitchItems(itemModel, SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches), generalSettings);
}
if (context != MixesContext && context != GlobalFunctionsContext && IS_ARM(board)) {
if (context != MixesContext && context != GlobalFunctionsContext && IS_ARM(btype)) {
addRawSwitchItems(itemModel, SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes), generalSettings);
}
if (context == SpecialFunctionsContext || context == GlobalFunctionsContext) {
@@ -530,7 +513,7 @@ void Helpers::addRawSourceItems(QStandardItemModel * itemModel, const RawSourceT
QStandardItemModel * Helpers::getRawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const model, unsigned int flags)
{
QStandardItemModel * itemModel = new QStandardItemModel();
Board::Type board = getCurrentBoard();
Boards board = Boards(getCurrentBoard());
Firmware * fw = getCurrentFirmware();
if (flags & POPULATE_NONE) {
@@ -548,13 +531,13 @@ QStandardItemModel * Helpers::getRawSourceItemModel(const GeneralSettings * cons
}
if (flags & POPULATE_SOURCES) {
int totalSources = CPN_MAX_STICKS + getBoardCapability(board, Board::Pots) + getBoardCapability(board, Board::Sliders) + getBoardCapability(board, Board::MouseAnalogs);
int totalSources = CPN_MAX_STICKS + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + board.getCapability(Board::MouseAnalogs);
addRawSourceItems(itemModel, SOURCE_TYPE_STICK, totalSources, generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders), generalSettings, model);
}
if (flags & POPULATE_TRIMS) {
addRawSourceItems(itemModel, SOURCE_TYPE_TRIM, getBoardCapability(board, Board::NumTrims), generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_TRIM, board.getCapability(Board::NumTrims), generalSettings, model);
}
if (flags & POPULATE_SOURCES) {
@@ -562,7 +545,7 @@ QStandardItemModel * Helpers::getRawSourceItemModel(const GeneralSettings * cons
}
if (flags & POPULATE_SWITCHES) {
addRawSourceItems(itemModel, SOURCE_TYPE_SWITCH, getBoardCapability(board, Board::Switches), generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_SWITCH, board.getCapability(Board::Switches), generalSettings, model);
addRawSourceItems(itemModel, SOURCE_TYPE_CUSTOM_SWITCH, fw->getCapability(LogicalSwitches), generalSettings, model);
}
@@ -573,7 +556,7 @@ QStandardItemModel * Helpers::getRawSourceItemModel(const GeneralSettings * cons
}
if (flags & POPULATE_TELEMETRY) {
if (IS_ARM(board)) {
if (IS_ARM(board.getBoardType())) {
addRawSourceItems(itemModel, SOURCE_TYPE_SPECIAL, 5, generalSettings, model);
if (model) {
@@ -593,7 +576,7 @@ QStandardItemModel * Helpers::getRawSourceItemModel(const GeneralSettings * cons
exclude << TELEMETRY_SOURCE_TX_TIME;
if (!fw->getCapability(SportTelemetry))
exclude << TELEMETRY_SOURCE_SWR;
if (!IS_ARM(board))
if (!IS_ARM(board.getBoardType()))
exclude << TELEMETRY_SOURCE_TIMER3;
int count = ((flags & POPULATE_TELEMETRYEXT) ? TELEMETRY_SOURCES_STATUS_COUNT : TELEMETRY_SOURCES_COUNT);
addRawSourceItems(itemModel, SOURCE_TYPE_TELEMETRY, count, generalSettings, model, 0, exclude);
+1 -2
View File
@@ -146,9 +146,8 @@ namespace Helpers
QStandardItemModel * getRawSourceItemModel(const GeneralSettings * const generalSettings = NULL, const ModelData * const model = NULL, unsigned int flags = 0);
void populateGvarUseCB(QComboBox *b, unsigned int phase);
void populateGvSourceCB(QComboBox *b, int value);
void populatePhasesCB(QComboBox *b, int value);
void populateGVCB(QComboBox & b, int value, const ModelData & model);
QString getAdjustmentString(int16_t val, const ModelData * model = NULL, bool sign = false);
void populateFileComboBox(QComboBox * b, const QSet<QString> & set, const QString & current);
void getFileComboBoxValue(QComboBox * b, char * dest, int length);
+1 -1
View File
@@ -1 +1 @@
IDI_ICON1 ICON DISCARDABLE "icon.ico"
IDI_ICON1 ICON DISCARDABLE "icon.ico"
+315 -53
View File
@@ -30,7 +30,7 @@
#include "downloaddialog.h"
#include "printdialog.h"
#include "version.h"
#include "contributorsdialog.h"
#include "creditsdialog.h"
#include "releasenotesdialog.h"
#include "releasenotesfirmwaredialog.h"
#include "customizesplashdialog.h"
@@ -44,6 +44,7 @@
#include "process_sync.h"
#include "radiointerface.h"
#include "progressdialog.h"
#include "progresswidget.h"
#include "storage.h"
#include "translations.h"
@@ -52,22 +53,28 @@
#include <QFileInfo>
#include <QDesktopServices>
#define OPENTX_DOWNLOADS_PAGE_URL "http://www.open-tx.org/downloads"
#define OPENTX_COMPANION_DOWNLOADS "http://downloads-22.open-tx.org/companion"
#define DONATE_STR "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QUZ48K4SEXDP2"
#ifdef __APPLE__
#define COMPANION_STAMP "companion-macosx.stamp"
#define COMPANION_INSTALLER "companion-macosx-%1.dmg"
#else
#define COMPANION_INSTALLER "macosx/opentx-companion-%1.dmg"
#define COMPANION_FILEMASK tr("Diskimage (*.dmg)")
#define COMPANION_INSTALL_QUESTION tr("Would you like to open the disk image to install the new version?")
#elif WIN32
#define COMPANION_STAMP "companion-windows.stamp"
#define COMPANION_INSTALLER "companion-windows-%1.exe"
#define COMPANION_INSTALLER "windows/companion-windows-%1.exe"
#define COMPANION_FILEMASK tr("Executable (*.exe)")
#define COMPANION_INSTALL_QUESTION tr("Would you like to launch the installer?")
#else
#define COMPANION_STAMP "companion-linux.stamp"
#define COMPANION_INSTALLER "" // no automatated updates for linux
#define COMPANION_FILEMASK "*.*"
#define COMPANION_INSTALL_QUESTION tr("Would you like to launch the installer?")
#endif
#ifdef WIN32
#define OPENTX_NIGHT_COMPANION_DOWNLOADS "http://downloads-22.open-tx.org/nightly/companion/windows"
#else
#define OPENTX_NIGHT_COMPANION_DOWNLOADS "http://downloads-22.open-tx.org/nightly/companion/linux"
#endif
#define OPENTX_NIGHT_COMPANION_DOWNLOADS "http://downloads-22.open-tx.org/nightlies/companion"
MainWindow::MainWindow():
downloadDialog_forWait(NULL),
@@ -108,7 +115,16 @@ MainWindow::MainWindow():
if (showSplash) {
updateDelay += (SPLASH_TIME*1000);
}
QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
if (g.isFirstUse()) {
g.warningId(g.warningId() | AppMessages::MSG_WELCOME);
QTimer::singleShot(updateDelay-500, this, SLOT(appPrefs())); // must be shown before warnings dialog but after splash
}
else {
if (!g.previousVersion().isEmpty())
g.warningId(g.warningId() | AppMessages::MSG_UPGRADED);
QTimer::singleShot(updateDelay, this, SLOT(doAutoUpdates()));
}
QTimer::singleShot(updateDelay, this, SLOT(displayWarnings()));
QStringList strl = QApplication::arguments();
@@ -161,21 +177,39 @@ MainWindow::~MainWindow()
void MainWindow::displayWarnings()
{
int warnId = g.warningId();
if (warnId<WARNING_ID && warnId!=0) {
int res=0;
if (WARNING_LEVEL>0)
QMessageBox::warning(this, "Companion", WARNING);
else
QMessageBox::about(this, "Companion", WARNING);
res = QMessageBox::question(this, "Companion", tr("Display previous warning again at startup ?"), QMessageBox::Yes | QMessageBox::No);
if (res == QMessageBox::No) {
g.warningId(WARNING_ID);
}
using namespace AppMessages;
static uint shownMsgs = 0;
int showMsgs = g.warningId();
int msgId;
QString infoTxt;
if ((showMsgs & MSG_WELCOME) && !(shownMsgs & MSG_WELCOME)) {
infoTxt = CPN_STR_MSG_WELCOME.arg(VERSION);
msgId = MSG_WELCOME;
}
else if (warnId==0) {
g.warningId(WARNING_ID);
else if ((showMsgs & MSG_UPGRADED) && !(shownMsgs & MSG_UPGRADED)) {
infoTxt = CPN_STR_MSG_UPGRADED.arg(VERSION);
msgId = MSG_UPGRADED;
}
else {
return;
}
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Companion"));
msgBox.setIcon(QMessageBox::Information);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setInformativeText(infoTxt);
QCheckBox * cb = new QCheckBox(tr("Show this message again at next startup?"), &msgBox);
msgBox.setCheckBox(cb);
msgBox.exec();
shownMsgs |= msgId;
if (!cb->isChecked())
g.warningId(showMsgs & ~msgId);
displayWarnings(); // in case more warnings need showing
}
void MainWindow::doAutoUpdates()
@@ -288,20 +322,20 @@ void MainWindow::checkForCompanionUpdateFinished(QNetworkReply * reply)
if (version.isNull())
return onUpdatesError();
int vnum = version2index(version);
int webVersion = version2index(version);
QString c9xversion = QString(VERSION);
int c9xver = version2index(c9xversion);
int ownVersion = version2index(VERSION);
if (c9xver < vnum) {
#if defined WIN32 || !defined __GNUC__ // || defined __APPLE__ // OSX should only notify of updates since no update packages are available.
if (ownVersion < webVersion) {
#if defined WIN32 || defined __APPLE__
int ret = QMessageBox::question(this, "Companion", tr("A new version of Companion is available (version %1)<br>"
"Would you like to download it?").arg(version) ,
QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) {
QDir dir(g.updatesDir());
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), dir.absoluteFilePath(QString(COMPANION_INSTALLER).arg(version)), tr("Executable (*.exe)"));
QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), dir.absoluteFilePath(QString(COMPANION_INSTALLER).arg(version)), COMPANION_FILEMASK);
if (!fileName.isEmpty()) {
g.updatesDir(QFileInfo(fileName).dir().absolutePath());
downloadDialog * dd = new downloadDialog(this, QString("%1/%2").arg(getCompanionUpdateBaseUrl()).arg(QString(COMPANION_INSTALLER).arg(version)), fileName);
@@ -311,7 +345,7 @@ void MainWindow::checkForCompanionUpdateFinished(QNetworkReply * reply)
}
}
#else
QMessageBox::warning(this, tr("New release available"), tr("A new release of Companion is available, please check the OpenTX website!"));
QMessageBox::warning(this, tr("New release available"), tr("A new release of Companion is available, please check the <a href='%1'>OpenTX website!</a>").arg(OPENTX_DOWNLOADS_PAGE_URL));
#endif
}
else {
@@ -325,8 +359,7 @@ void MainWindow::checkForCompanionUpdateFinished(QNetworkReply * reply)
void MainWindow::updateDownloaded()
{
int ret = QMessageBox::question(this, "Companion", tr("Would you like to launch the installer?") ,
QMessageBox::Yes | QMessageBox::No);
int ret = QMessageBox::question(this, "Companion", COMPANION_INSTALL_QUESTION, QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) {
if (QDesktopServices::openUrl(QUrl::fromLocalFile(installer_fileName)))
QApplication::exit();
@@ -657,9 +690,7 @@ void MainWindow::openFile(const QString & fileName, bool updateLastUsedDir)
void MainWindow::openFile()
{
QString fileFilter;
fileFilter = tr(EEPROM_FILES_FILTER);
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Models and Settings file"), g.eepromDir(), fileFilter);
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Models and Settings file"), g.eepromDir(), EEPROM_FILES_FILTER);
openFile(fileName);
}
@@ -732,29 +763,259 @@ void MainWindow::fwPrefs()
void MainWindow::contributors()
{
ContributorsDialog * dialog = new ContributorsDialog(this);
CreditsDialog * dialog = new CreditsDialog(this);
dialog->exec();
dialog->deleteLater();
}
// Create a widget with a line edit and folder select button and handles all interactions. Features autosuggest
// path hints while typing, invalid paths shown in red. The label string is only for dialog title, not a QLabel.
// This should probably be moved some place more reusable, esp. the QFileSystemModel.
QWidget * folderSelectorWidget(QString * path, const QString & label, QWidget * parent)
{
static QFileSystemModel fileModel;
static bool init = false;
if (!init) {
init = true;
fileModel.setFilter(QDir::Dirs);
fileModel.setRootPath("/");
}
QWidget * fsw = new QWidget(parent);
QLineEdit * le = new QLineEdit(parent);
QCompleter * fsc = new QCompleter(fsw);
fsc->setModel(&fileModel);
//fsc->setCompletionMode(QCompleter::InlineCompletion);
le->setCompleter(fsc);
QToolButton * btn = new QToolButton(fsw);
btn->setIcon(CompanionIcon("open.png"));
QHBoxLayout * l = new QHBoxLayout(fsw);
l->setContentsMargins(0,0,0,0);
l->setSpacing(3);
l->addWidget(le);
l->addWidget(btn);
QObject::connect(btn, &QToolButton::clicked, [=]() {
QString dir = QFileDialog::getExistingDirectory(parent, label, le->text(), 0);
if (!dir.isEmpty()) {
le->setText(QDir::toNativeSeparators(dir));
le->setFocus();
}
});
QObject::connect(le, &QLineEdit::textChanged, [=](const QString & text) {
*path = text;
if (QFile::exists(text))
le->setStyleSheet("");
else
le->setStyleSheet("QLineEdit {color: red;}");
});
le->setText(QDir::toNativeSeparators(*path));
return fsw;
}
void MainWindow::sdsync()
{
QString sdPath = g.profile[g.id()].sdPath();
if (sdPath.isEmpty()) {
QMessageBox::warning(this, QObject::tr("Synchronization error"), QObject::tr("No SD directory configured!"));
const QString dlgTtl = tr("Synchronize SD");
const QIcon dlgIcn = CompanionIcon("sdsync.png");
const QString srcArw = CPN_STR_SW_INDICATOR_UP % " ";
const QString dstArw = CPN_STR_SW_INDICATOR_DN % " ";
QStringList errorMsgs;
// remember user-selectable options for duration of session
static QString sourcePath;
static QString destPath;
static int syncDirection = SyncProcess::SYNC_A2B_B2A;
static int compareType = SyncProcess::OVERWR_NEWER_IF_DIFF;
static int maxFileSize = 2 * 1024 * 1024; // Bytes
static bool dryRun = false;
if (sourcePath.isEmpty())
sourcePath = g.profile[g.id()].sdPath();
if (destPath.isEmpty())
destPath = findMassstoragePath("SOUNDS").replace(QRegExp("[/\\\\]?SOUNDS"), "");
if (sourcePath.isEmpty())
errorMsgs << tr("No local SD structure path configured!");
if (destPath.isEmpty())
errorMsgs << tr("No Radio or SD card detected!");
QDialog dlg(this);
dlg.setWindowTitle(dlgTtl % tr(" :: Options"));
dlg.setWindowIcon(dlgIcn);
dlg.setSizeGripEnabled(true);
dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);
QLabel * lblSrc = new QLabel(tr("Local Folder:"), &dlg);
QWidget * wdgSrc = folderSelectorWidget(&sourcePath, lblSrc->text(), &dlg);
QLabel * lblDst = new QLabel(tr("Radio Folder:"), &dlg);
QWidget * wdgDst = folderSelectorWidget(&destPath, lblDst->text(), &dlg);
QLabel * lbDir = new QLabel(tr("Sync. Direction:"), &dlg);
QComboBox * syncDir = new QComboBox(&dlg);
syncDir->addItem(tr("%1%2 Both directions, to radio folder first").arg(dstArw, srcArw), SyncProcess::SYNC_A2B_B2A);
syncDir->addItem(tr("%1%2 Both directions, to local folder first").arg(srcArw, dstArw), SyncProcess::SYNC_B2A_A2B);
syncDir->addItem(tr(" %1 Only from local folder to radio folder").arg(dstArw), SyncProcess::SYNC_A2B);
syncDir->addItem(tr(" %1 Only from radio folder to local folder").arg(srcArw), SyncProcess::SYNC_B2A);
syncDir->setCurrentIndex(-1); // we set the default option later
QLabel * lbMode = new QLabel(tr("Existing Files:"), &dlg);
QComboBox * copyMode = new QComboBox(&dlg);
copyMode->setToolTip(tr("How to handle overwriting files which already exist in the destination folder."));
copyMode->addItem(tr("Copy only if newer and different (compare contents)"), SyncProcess::OVERWR_NEWER_IF_DIFF);
copyMode->addItem(tr("Copy only if newer (do not compare contents)"), SyncProcess::OVERWR_NEWER_ALWAYS);
copyMode->addItem(tr("Copy only if different (ignore file time stamps)"), SyncProcess::OVERWR_IF_DIFF);
copyMode->addItem(tr("Always copy (force overwite existing files)"), SyncProcess::OVERWR_ALWAYS);
QLabel * lbSize = new QLabel(tr("Max. File Size:"), &dlg);
QSpinBox * maxSize = new QSpinBox(&dlg);
maxSize->setRange(0, 100 * 1024);
maxSize->setAccelerated(true);
maxSize->setSpecialValueText(tr("Any size"));
maxSize->setToolTip(tr("Skip files larger than this size. Enter zero for unlimited."));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 3, 0))
maxSize->setGroupSeparatorShown(true);
#endif
QCheckBox * testRun = new QCheckBox(tr("Test-run only"), &dlg);
testRun->setToolTip(tr("Run as normal but do not actually copy anything. Useful for verifying results before real sync."));
connect(testRun, &QCheckBox::toggled, [=](bool on) { dryRun = on; });
// layout to hold size spinbox and checkbox option(s)
QHBoxLayout * hlay1 = new QHBoxLayout();
hlay1->addWidget(maxSize, 1);
hlay1->addWidget(testRun);
// dialog OK/Cancel buttons
QDialogButtonBox * bb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dlg);
// Create main layout and add everything
QGridLayout * dlgL = new QGridLayout(&dlg);
dlgL->setSizeConstraint(QLayout::SetFixedSize);
int row = 0;
if (errorMsgs.size()) {
QLabel * lblWarn = new QLabel(QString(errorMsgs.join('\n')), &dlg);
lblWarn->setStyleSheet("QLabel { color: red; }");
dlgL->addWidget(lblWarn, row++, 0, 1, 2);
}
dlgL->addWidget(lblSrc, row, 0);
dlgL->addWidget(wdgSrc, row++, 1);
dlgL->addWidget(lblDst, row, 0);
dlgL->addWidget(wdgDst, row++, 1);
dlgL->addWidget(lbDir, row, 0);
dlgL->addWidget(syncDir, row++, 1);
dlgL->addWidget(lbMode, row, 0);
dlgL->addWidget(copyMode, row++, 1);
dlgL->addWidget(lbSize, row, 0);
dlgL->addLayout(hlay1, row++, 1);
dlgL->addWidget(bb, row++, 0, 1, 2);
dlgL->setRowStretch(row, 1);
connect(copyMode, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int) {
compareType = copyMode->currentData().toInt();
});
// function to dis/enable the OVERWR_ALWAYS option depending on sync direction
connect(syncDir, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int) {
int dir = syncDir->currentData().toInt();
int idx = copyMode->findData(SyncProcess::OVERWR_ALWAYS);
int flg = (dir == SyncProcess::SYNC_A2B || dir == SyncProcess::SYNC_B2A) ? 33 : 0;
if (!flg && idx == copyMode->currentIndex())
copyMode->setCurrentIndex(copyMode->findData(SyncProcess::OVERWR_NEWER_IF_DIFF));
copyMode->setItemData(idx, flg, Qt::UserRole - 1);
syncDirection = dir;
});
// function to set magnitude of file size spinbox, KB or MB
connect(maxSize, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int value) {
int multi = maxSize->property("multi").isValid() ? maxSize->property("multi").toInt() : 0;
maxSize->blockSignals(true);
if (value >= 10 * 1024 && multi != 1024 * 1024) {
// KB -> MB
multi = 1024 * 1024;
maxSize->setValue(value / 1024);
maxSize->setMaximum(100);
maxSize->setSingleStep(1);
maxSize->setSuffix(tr(" MB"));
}
else if ((value < 10 && multi != 1024) || !multi) {
// MB -> KB
if (multi)
value *= 1024;
multi = 1024;
if (value == 9 * 1024)
value += 1024 - 32; // avoid large jump when stepping from 10MB to 10,208KB
maxSize->setMaximum(100 * 1024);
maxSize->setValue(value);
maxSize->setSingleStep(32);
maxSize->setSuffix(tr(" KB"));
}
maxSize->setProperty("multi", multi);
maxSize->blockSignals(false);
maxFileSize = value * multi;
});
copyMode->setCurrentIndex(copyMode->findData(compareType));
syncDir->setCurrentIndex(syncDir->findData(syncDirection));
maxSize->setValue(maxFileSize / 1024);
testRun->setChecked(dryRun);
connect(bb, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
connect(bb, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
// to restart dialog on error/etc
openDialog:
// show the modal options dialog
if (dlg.exec() == QDialog::Rejected)
return;
// validate
errorMsgs.clear();
if (sourcePath == destPath)
errorMsgs << tr("Source and destination folders are the same!");
if (sourcePath.isEmpty() || !QFile::exists(sourcePath))
errorMsgs << tr("Source folder not found: %1").arg(sourcePath);
if (destPath.isEmpty() || !QFile::exists(destPath))
errorMsgs << tr("Destination folder not found: %1").arg(destPath);
if (!errorMsgs.isEmpty()) {
QMessageBox::warning(this, dlgTtl % tr(" :: Error"), errorMsgs.join('\n'));
goto openDialog;
}
QString massstoragePath = findMassstoragePath("SOUNDS");
if (massstoragePath.isEmpty()) {
QMessageBox::warning(this, QObject::tr("Synchronization error"), QObject::tr("No Radio connected!"));
return;
}
massstoragePath = massstoragePath.left(massstoragePath.length() - 7);
ProgressDialog progressDialog(this, tr("Synchronize SD"), CompanionIcon("sdsync.png"));
SyncProcess syncProcess(massstoragePath, g.profile[g.id()].sdPath(), progressDialog.progress());
if (!syncProcess.run()) {
progressDialog.exec();
}
// set up the progress dialog and the sync process worker
ProgressDialog * progressDlg = new ProgressDialog(this, dlgTtl % tr(" :: Progress"), dlgIcn);
progressDlg->setAttribute(Qt::WA_DeleteOnClose, true);
ProgressWidget * progWidget = progressDlg->progress();
SyncProcess * syncProcess = new SyncProcess(sourcePath, destPath, syncDirection, compareType, maxFileSize, dryRun);
// move sync process to separate thread, we only use signals/slots from here on...
QThread * syncThread = new QThread(this);
syncProcess->moveToThread(syncThread);
// ...and quite a few of them!
connect(this, &MainWindow::startSync, syncProcess, &SyncProcess::run);
connect(syncThread, &QThread::finished, syncProcess, &SyncProcess::deleteLater);
connect(syncProcess, &SyncProcess::finished, syncThread, &QThread::quit);
connect(syncProcess, &SyncProcess::destroyed, syncThread, &QThread::quit);
connect(syncProcess, &SyncProcess::destroyed, syncThread, &QThread::deleteLater);
connect(syncProcess, &SyncProcess::fileCountChanged, progWidget, &ProgressWidget::setMaximum);
connect(syncProcess, &SyncProcess::progressStep, progWidget, &ProgressWidget::setValue);
connect(syncProcess, &SyncProcess::progressMessage, progWidget, &ProgressWidget::addMessage);
connect(syncProcess, &SyncProcess::statusMessage, progWidget, &ProgressWidget::setInfo);
connect(syncProcess, &SyncProcess::started, progressDlg, &ProgressDialog::setProcessStarted);
connect(syncProcess, &SyncProcess::finished, progressDlg, &ProgressDialog::setProcessStopped);
connect(syncProcess, &SyncProcess::finished, [=]() { QApplication::alert(this); });
connect(progressDlg, &ProgressDialog::rejected, syncProcess, &SyncProcess::stop);
connect(progressDlg, &ProgressDialog::rejected, syncProcess, &SyncProcess::deleteLater);
// go (finally)
syncThread->start();
emit startSync();
}
void MainWindow::changelog()
@@ -780,7 +1041,7 @@ void MainWindow::fwchangelog()
void MainWindow::customizeSplash()
{
customizeSplashDialog * dialog = new customizeSplashDialog(this);
CustomizeSplashDialog * dialog = new CustomizeSplashDialog(this);
dialog->exec();
dialog->deleteLater();
}
@@ -861,7 +1122,7 @@ void MainWindow::readBackup()
return;
// TODO implementation
}
QString fileName = QFileDialog::getSaveFileName(this, tr("Save Radio Backup to File"), g.eepromDir(), tr(EXTERNAL_EEPROM_FILES_FILTER));
QString fileName = QFileDialog::getSaveFileName(this, tr("Save Radio Backup to File"), g.eepromDir(), EXTERNAL_EEPROM_FILES_FILTER);
if (!fileName.isEmpty()) {
if (!readEepromFromRadio(fileName))
return;
@@ -870,7 +1131,7 @@ void MainWindow::readBackup()
void MainWindow::readFlash()
{
QString fileName = QFileDialog::getSaveFileName(this,tr("Read Radio Firmware to File"), g.flashDir(),tr(FLASH_FILES_FILTER));
QString fileName = QFileDialog::getSaveFileName(this,tr("Read Radio Firmware to File"), g.flashDir(), FLASH_FILES_FILTER);
if (!fileName.isEmpty()) {
readFirmwareFromRadio(fileName);
}
@@ -944,6 +1205,7 @@ void MainWindow::updateMenus()
readEepromAct->setEnabled(true);
writeBUToRadioAct->setEnabled(true);
readBUToFileAct->setEnabled(true);
editSplashAct->setDisabled(IS_HORUS(getCurrentBoard()));
foreach (QAction * act, fileWindowActions) {
if (!act)
+1
View File
@@ -54,6 +54,7 @@ class MainWindow : public QMainWindow
signals:
void firmwareChanged();
void startSync();
protected:
QString getCompanionUpdateBaseUrl();
+2 -2
View File
@@ -702,7 +702,7 @@ void MdiChild::onFirmwareChanged()
Firmware * previous = firmware;
firmware = getCurrentFirmware();
//qDebug() << "onFirmwareChanged" << previous->getName() << "=>" << firmware->getName();
if (previous->getBoard() != firmware->getBoard()) {
if (StorageFormat::getFourCC(previous->getBoard()) != StorageFormat::getFourCC(firmware->getBoard())) {
convertStorage(previous->getBoard(), firmware->getBoard());
setModified();
}
@@ -1480,7 +1480,7 @@ void MdiChild::writeEeprom() // write to Tx
bool MdiChild::loadBackup()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open backup Models and Settings file"), g.eepromDir(), tr(EEPROM_FILES_FILTER));
QString fileName = QFileDialog::getOpenFileName(this, tr("Open backup Models and Settings file"), g.eepromDir(), EEPROM_FILES_FILTER);
if (fileName.isEmpty())
return false;
QFile file(fileName);
+1 -1
View File
@@ -156,7 +156,7 @@ Channels::Channels(QWidget * parent, ModelData & model, GeneralSettings & genera
curveCB->setProperty("index", i);
int numcurves = firmware->getCapability(NumCurves);
for (int j=-numcurves; j<=numcurves; j++) {
curveCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(), j);
curveCB->addItem(CurveReference(CurveReference::CURVE_REF_CUSTOM, j).toString(&model, false), j);
}
curveCB->setCurrentIndex(model.limitData[i].curve.value+numcurves);
connect(curveCB, SIGNAL(currentIndexChanged(int)), this, SLOT(curveEdited()));
+13 -13
View File
@@ -337,6 +337,7 @@ void CustomFunctionsPanel::playMusic()
#define CUSTOM_FUNCTION_REPEAT (1<<7)
#define CUSTOM_FUNCTION_PLAY (1<<8)
#define CUSTOM_FUNCTION_BL_COLOR (1<<9)
#define CUSTOM_FUNCTION_SHOW_FUNC (1<<10)
void CustomFunctionsPanel::customFunctionEdited()
{
@@ -357,7 +358,7 @@ void CustomFunctionsPanel::functionEdited()
RawSwitch swtch = functions[index].swtch;
functions[index].clear();
functions[index].swtch = swtch;
functions[index].func = (AssignFunc)fswtchFunc[index]->itemData(fswtchFunc[index]->currentIndex()).toInt();
functions[index].func = (AssignFunc)fswtchFunc[index]->currentData().toInt();
refreshCustomFunction(index);
emit modified();
lock = false;
@@ -382,7 +383,8 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
cfn.adjustMode = (AssignFunc)fswtchGVmode[i]->currentIndex();
}
if (cfn.swtch.toValue()) {
if (!cfn.isEmpty()) {
widgetsMask |= CUSTOM_FUNCTION_SHOW_FUNC;
if (func>=FuncOverrideCH1 && func<=FuncOverrideCH32) {
if (model) {
@@ -395,7 +397,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
cfn.param = fswtchParam[i]->value();
}
fswtchParam[i]->setValue(cfn.param);
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM + CUSTOM_FUNCTION_ENABLE;
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_ENABLE;
}
}
else if (func==FuncLogs) {
@@ -456,7 +458,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
if (modified)
cfn.param = fswtchParamT[i]->currentData().toInt();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM + CUSTOM_FUNCTION_ENABLE;
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_ENABLE;
}
else if (func==FuncPlaySound || func==FuncPlayHaptic || func==FuncPlayValue || func==FuncPlayPrompt || func==FuncPlayBoth || func==FuncBackgroundMusic) {
if (func != FuncBackgroundMusic) {
@@ -467,7 +469,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
if (modified)
cfn.param = fswtchParamT[i]->currentData().toInt();
populateFuncParamCB(fswtchParamT[i], func, cfn.param);
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM + CUSTOM_FUNCTION_REPEAT;
widgetsMask |= CUSTOM_FUNCTION_SOURCE_PARAM | CUSTOM_FUNCTION_REPEAT;
}
else if (func==FuncPlayPrompt || func==FuncPlayBoth) {
if (firmware->getCapability(VoicesAsNumbers)) {
@@ -475,10 +477,10 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
fswtchParam[i]->setSingleStep(1);
fswtchParam[i]->setMinimum(0);
if (func==FuncPlayPrompt) {
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM + CUSTOM_FUNCTION_REPEAT + CUSTOM_FUNCTION_GV_TOOGLE;
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT | CUSTOM_FUNCTION_GV_TOOGLE;
}
else {
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM + CUSTOM_FUNCTION_REPEAT;
widgetsMask |= CUSTOM_FUNCTION_NUMERIC_PARAM | CUSTOM_FUNCTION_REPEAT;
fswtchParamGV[i]->setChecked(false);
}
fswtchParam[i]->setMaximum(func==FuncPlayBoth ? 254 : 255);
@@ -563,7 +565,7 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified)
}
fswtchFunc[i]->setVisible(cfn.swtch.toValue());
fswtchFunc[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_SHOW_FUNC);
fswtchParam[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_NUMERIC_PARAM);
fswtchParamTime[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_TIME_PARAM);
fswtchParamGV[i]->setVisible(widgetsMask & CUSTOM_FUNCTION_GV_TOOGLE);
@@ -599,9 +601,8 @@ void CustomFunctionsPanel::fswPaste()
CustomFunctionData *fsw = &functions[selectedFunction];
memcpy(fsw, fswData.constData(), sizeof(CustomFunctionData));
lock = true;
fswtchSwtch[selectedFunction]->setModel(rawSwitchItemModel);
fswtchSwtch[selectedFunction]->setCurrentIndex(fswtchSwtch[selectedFunction]->findData(functions[selectedFunction].swtch.toValue()));
populateFuncCB(fswtchFunc[selectedFunction], functions[selectedFunction].func);
fswtchFunc[selectedFunction]->setCurrentIndex(fswtchFunc[selectedFunction]->findData(functions[selectedFunction].func));
populateGVmodeCB(fswtchGVmode[selectedFunction], functions[selectedFunction].adjustMode);
populateFuncParamCB(fswtchParamT[selectedFunction], functions[selectedFunction].func, functions[selectedFunction].param, functions[selectedFunction].adjustMode);
refreshCustomFunction(selectedFunction);
@@ -615,9 +616,8 @@ void CustomFunctionsPanel::fswDelete()
functions[selectedFunction].clear();
// TODO update switch and func
lock = true;
fswtchSwtch[selectedFunction]->setModel(rawSwitchItemModel);
fswtchSwtch[selectedFunction]->setCurrentIndex(fswtchSwtch[selectedFunction]->findData(functions[selectedFunction].swtch.toValue()));
populateFuncCB(fswtchFunc[selectedFunction], functions[selectedFunction].func);
fswtchFunc[selectedFunction]->setCurrentIndex(fswtchFunc[selectedFunction]->findData(functions[selectedFunction].func));
refreshCustomFunction(selectedFunction);
lock = false;
emit modified();
@@ -680,7 +680,7 @@ void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value)
// b->model()->setData(index, v, Qt::UserRole - 1);
}
else {
b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(), i);
b->addItem(CustomFunctionData(AssignFunc(i)).funcToString(model), i);
if (i == value) {
b->setCurrentIndex(b->count()-1);
}
+2 -1
View File
@@ -41,7 +41,8 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G
cb_fp[i] = tmp[i];
}
setWindowTitle(tr("Edit %1").arg(modelPrinter.printInputName(ed->chn)));
RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_STICK);
setWindowTitle(tr("Edit %1").arg(RawSource(srcType, ed->chn).toString(&model, &generalSettings)));
QRegExp rx(CHAR_FOR_NAMES_REGEX);
if (IS_HORUS_OR_TARANIS(getCurrentBoard())) {
+11 -11
View File
@@ -153,26 +153,26 @@ bool InputsPanel::AddInputLine(int dest)
QString InputsPanel::getInputText(int dest, bool * new_ch)
{
QString str;
if (new_ch) *new_ch = 0;
if (new_ch)
*new_ch = false;
if (dest < 0) {
str = modelPrinter.printInputName(-dest-1);
if (new_ch) *new_ch = 1;
if (new_ch)
*new_ch = true;
}
else {
ExpoData & input = model->expoData[dest];
int nameChars = (firmware->getCapability(VirtualInputs) ? 10 : 4);
if ((dest == 0) || (model->expoData[dest-1].chn != input.chn)) {
if (new_ch) *new_ch = 1;
if (firmware->getCapability(VirtualInputs))
str += QString("%1").arg(modelPrinter.printInputName(input.chn), -10, ' ');
else
str = modelPrinter.printInputName(input.chn);
if (new_ch)
*new_ch = true;
str = QString("%1").arg(modelPrinter.printInputName(input.chn), -nameChars, QChar(' '));
}
else {
if (firmware->getCapability(VirtualInputs))
str = " ";
else
str = " ";
str = QString(nameChars, QChar(' '));
}
str.replace(" ", "&nbsp;");
str += modelPrinter.printInputLine(input);
+2 -2
View File
@@ -48,7 +48,7 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model,
// The label
QLabel * label = new QLabel(this);
label->setProperty("index", i);
label->setText(tr("L%1").arg(i+1));
label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, i+1).toString());
label->setContextMenuPolicy(Qt::CustomContextMenu);
label->setMouseTracking(true);
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
@@ -468,7 +468,7 @@ void LogicalSwitchesPanel::populateAndSwitchCB(QComboBox *b, const RawSwitch & v
b->addItem(item.toString(), item.toValue());
if (item == value) b->setCurrentIndex(b->count()-1);
for (int i=1; i<=firmware->getCapability(SwitchesPositions); i++) {
for (int i=1; i <= Boards::getCapability(firmware->getBoard(), Board::SwitchPositions); i++) {
item = RawSwitch(SWITCH_TYPE_SWITCH, i);
b->addItem(item.toString(), item.toValue());
if (item == value) b->setCurrentIndex(b->count()-1);
+1 -1
View File
@@ -40,7 +40,7 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, G
cb_fp[i] = tmp[i];
}
this->setWindowTitle(tr("DEST -> CH%1").arg(md->destCh));
this->setWindowTitle(tr("DEST -> %1").arg(RawSource(SOURCE_TYPE_CH, md->destCh-1).toString(&model, &generalSettings)));
ui->sourceCB->setModel(Helpers::getRawSourceItemModel(&generalSettings, &model, POPULATE_NONE | POPULATE_SOURCES | POPULATE_SCRIPT_OUTPUTS | POPULATE_VIRTUAL_INPUTS | POPULATE_SWITCHES | POPULATE_TRIMS));
ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue()));
+2 -2
View File
@@ -140,7 +140,7 @@ QString MixesPanel::getMixerText(int dest, bool * new_ch)
QString str;
bool newChannel = false;
if (dest < 0) {
str = modelPrinter.printMixerName(-dest);
str = modelPrinter.printChannelName(abs(dest)-1);
//highlight channel if needed
if (-dest == (int)highlightedSource) {
str = "<b>" + str + "</b>";
@@ -150,7 +150,7 @@ QString MixesPanel::getMixerText(int dest, bool * new_ch)
else {
MixData & mix = model->mixData[dest];
//mix->destCh from 1 to 32
str = modelPrinter.printMixerName(mix.destCh);
str = modelPrinter.printChannelName(mix.destCh-1);
if ((dest == 0) || (model->mixData[dest-1].destCh != mix.destCh)) {
newChannel = true;
+46 -38
View File
@@ -51,7 +51,6 @@ TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, Ge
// Mode
ui->mode->setModel(Helpers::getRawSwitchItemModel(&generalSettings, Helpers::TimersContext));
ui->mode->setCurrentIndex(ui->mode->findData(timer.mode.toValue()));
//Helpers::populateSwitchCB(ui->mode, timer.mode, generalSettings, Helpers::TimersContext);
if (!firmware->getCapability(PermTimers)) {
ui->persistent->hide();
@@ -121,8 +120,11 @@ QWidget * TimerPanel::getLastFocus()
void TimerPanel::on_value_editingFinished()
{
timer.val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
emit modified();
unsigned val = ui->value->time().hour()*3600 + ui->value->time().minute()*60 + ui->value->time().second();
if (timer.val != val) {
timer.val = val;
emit modified();
}
}
void TimerPanel::on_mode_currentIndexChanged(int index)
@@ -141,9 +143,11 @@ void TimerPanel::on_minuteBeep_toggled(bool checked)
void TimerPanel::on_name_editingFinished()
{
int length = ui->name->maxLength();
strncpy(timer.name, ui->name->text().toLatin1(), length);
emit modified();
if (QString(timer.name) != ui->name->text()) {
int length = ui->name->maxLength();
strncpy(timer.name, ui->name->text().toLatin1(), length);
emit modified();
}
}
/******************************************************************************/
@@ -234,15 +238,15 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul
disableMouseScrolling();
update();
connect(ui->protocol, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ModulePanel::onProtocolChanged);
connect(ui->multiProtocol, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ModulePanel::onMultiProtocolChanged);
connect(this, &ModulePanel::channelsRangeChanged, this, &ModulePanel::setupFailsafes);
connect(ui->btnGrpValueType, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &ModulePanel::onFailsafesDisplayValueTypeChanged);
lock = false;
// a change will not register if only one item was added
if (ui->protocol->count() == 1) {
on_protocol_currentIndexChanged(ui->protocol->currentIndex());
}
}
ModulePanel::~ModulePanel()
@@ -476,7 +480,7 @@ void ModulePanel::update()
ui->optionValue->setMinimum(pdef.getOptionMin());
ui->optionValue->setMaximum(pdef.getOptionMax());
ui->optionValue->setValue(module.multi.optionValue);
ui->label_option->setText(pdef.optionsstr);
ui->label_option->setText(qApp->translate("Multiprotocols", qPrintable(pdef.optionsstr)));
}
ui->multiSubType->setCurrentIndex(module.subType);
@@ -533,7 +537,7 @@ void ModulePanel::on_trainerMode_currentIndexChanged(int index)
}
}
void ModulePanel::on_protocol_currentIndexChanged(int index)
void ModulePanel::onProtocolChanged(int index)
{
if (!lock) {
module.protocol = ui->protocol->itemData(index).toInt();
@@ -562,7 +566,7 @@ void ModulePanel::on_ppmOutputType_currentIndexChanged(int index)
void ModulePanel::on_channelsCount_editingFinished()
{
if (!lock) {
if (!lock && module.channelsCount != ui->channelsCount->value()) {
module.channelsCount = ui->channelsCount->value();
update();
emit channelsRangeChanged();
@@ -572,8 +576,8 @@ void ModulePanel::on_channelsCount_editingFinished()
void ModulePanel::on_channelsStart_editingFinished()
{
if (!lock) {
module.channelsStart = ui->channelsStart->value() - 1;
if (!lock && module.channelsStart != (unsigned)ui->channelsStart->value() - 1) {
module.channelsStart = (unsigned)ui->channelsStart->value() - 1;
update();
emit channelsRangeChanged();
emit modified();
@@ -582,7 +586,7 @@ void ModulePanel::on_channelsStart_editingFinished()
void ModulePanel::on_ppmDelay_editingFinished()
{
if (!lock) {
if (!lock && module.ppm.delay != ui->ppmDelay->value()) {
// TODO only accept valid values
module.ppm.delay = ui->ppmDelay->value();
emit modified();
@@ -591,14 +595,19 @@ void ModulePanel::on_ppmDelay_editingFinished()
void ModulePanel::on_rxNumber_editingFinished()
{
module.modelId = ui->rxNumber->value();
emit modified();
if (module.modelId != (unsigned)ui->rxNumber->value()) {
module.modelId = (unsigned)ui->rxNumber->value();
emit modified();
}
}
void ModulePanel::on_ppmFrameLength_editingFinished()
{
module.ppm.frameLength = (ui->ppmFrameLength->value()-22.5) / 0.5;
emit modified();
int val = (ui->ppmFrameLength->value()-22.5) / 0.5;
if (module.ppm.frameLength != val) {
module.ppm.frameLength = val;
emit modified();
}
}
void ModulePanel::on_failsafeMode_currentIndexChanged(int value)
@@ -610,7 +619,7 @@ void ModulePanel::on_failsafeMode_currentIndexChanged(int value)
}
}
void ModulePanel::on_multiProtocol_currentIndexChanged(int index)
void ModulePanel::onMultiProtocolChanged(int index)
{
if (!lock) {
lock=true;
@@ -627,8 +636,10 @@ void ModulePanel::on_multiProtocol_currentIndexChanged(int index)
void ModulePanel::on_optionValue_editingFinished()
{
module.multi.optionValue = ui->optionValue->value();
emit modified();
if (module.multi.optionValue != ui->optionValue->value()) {
module.multi.optionValue = ui->optionValue->value();
emit modified();
}
}
void ModulePanel::on_multiSubType_currentIndexChanged(int index)
@@ -753,16 +764,16 @@ void ModulePanel::updateFailsafe(int channel)
const int failsafeValue = module.failsafeChannels[channel];
const ChannelFailsafeWidgetsGroup & grp = failsafeGroupsMap.value(channel);
const bool valDisable = (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE);
const int cbIdx = (failsafeValue == FAILSAFE_CHANNEL_HOLD ? 1 : failsafeValue == FAILSAFE_CHANNEL_NOPULSE ? 2 : 0);
if (grp.combo)
grp.combo->setCurrentIndex(cbIdx);
grp.combo->setCurrentIndex(grp.combo->findData(valDisable ? failsafeValue : 0));
if (grp.sbPercent)
grp.sbPercent->setDisabled(valDisable);
if (grp.sbUsec)
grp.sbUsec->setDisabled(valDisable);
setChannelFailsafeValue(channel, (valDisable ? 0 : failsafeValue), (FAILSAFE_DISPLAY_PERCENT | FAILSAFE_DISPLAY_USEC));
if (!valDisable)
setChannelFailsafeValue(channel, failsafeValue, (FAILSAFE_DISPLAY_PERCENT | FAILSAFE_DISPLAY_USEC));
}
/******************************************************************************/
@@ -855,7 +866,7 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
if (i<firmware->getCapability(Timers)) {
timers[i] = new TimerPanel(this, model, model.timers[i], generalSettings, firmware, prevFocus);
ui->gridLayout->addWidget(timers[i], 1+i, 1);
connect(timers[i], SIGNAL(modified()), this, SLOT(onChildModified()));
connect(timers[i], &TimerPanel::modified, this, &SetupPanel::modified);
prevFocus = timers[i]->getLastFocus();
}
else {
@@ -987,14 +998,14 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
for (int i=0; i<firmware->getCapability(NumModules); i++) {
modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i);
ui->modulesLayout->addWidget(modules[i]);
connect(modules[i], SIGNAL(modified()), this, SLOT(onChildModified()));
connect(modules[i], &ModulePanel::modified, this, &SetupPanel::modified);
connect(this, &SetupPanel::extendedLimitsToggled, modules[i], &ModulePanel::onExtendedLimitsToggled);
}
if (firmware->getCapability(ModelTrainerEnable)) {
modules[CPN_MAX_MODULES] = new ModulePanel(this, model, model.moduleData[CPN_MAX_MODULES], generalSettings, firmware, -1);
ui->modulesLayout->addWidget(modules[CPN_MAX_MODULES]);
connect(modules[CPN_MAX_MODULES], SIGNAL(modified()), this, SLOT(onChildModified()));
connect(modules[CPN_MAX_MODULES], &ModulePanel::modified, this, &SetupPanel::modified);
}
disableMouseScrolling();
@@ -1048,9 +1059,11 @@ void SetupPanel::on_throttleSource_currentIndexChanged(int index)
void SetupPanel::on_name_editingFinished()
{
int length = ui->name->maxLength();
strncpy(model->name, ui->name->text().toLatin1(), length);
emit modified();
if (QString(model->name) != ui->name->text()) {
int length = ui->name->maxLength();
strncpy(model->name, ui->name->text().toLatin1(), length);
emit modified();
}
}
void SetupPanel::on_image_currentIndexChanged(int index)
@@ -1104,7 +1117,7 @@ void SetupPanel::populateThrottleSourceCB()
ui->throttleSource->addItem(firmware->getAnalogInputName(4+i), i);
}
for (int i=0; i<firmware->getCapability(Outputs); i++) {
ui->throttleSource->addItem(ModelPrinter::printChannelName(i));
ui->throttleSource->addItem(RawSource(SOURCE_TYPE_CH, i).toString(model, &generalSettings));
}
ui->throttleSource->setCurrentIndex(model->thrTraceSrc);
lock = false;
@@ -1293,8 +1306,3 @@ void SetupPanel::onBeepCenterToggled(bool checked)
emit modified();
}
}
void SetupPanel::onChildModified()
{
emit modified();
}
+2 -3
View File
@@ -71,7 +71,7 @@ class ModulePanel : public ModelPanel
private slots:
void setupFailsafes();
void on_trainerMode_currentIndexChanged(int index);
void on_protocol_currentIndexChanged(int index);
void onProtocolChanged(int index);
void on_ppmDelay_editingFinished();
void on_channelsCount_editingFinished();
void on_channelsStart_editingFinished();
@@ -81,7 +81,7 @@ class ModulePanel : public ModelPanel
void on_antennaMode_currentIndexChanged(int index);
void on_rxNumber_editingFinished();
void on_failsafeMode_currentIndexChanged(int value);
void on_multiProtocol_currentIndexChanged(int index);
void onMultiProtocolChanged(int index);
void on_multiSubType_currentIndexChanged(int index);
void on_autoBind_stateChanged(int state);
void on_lowPower_stateChanged(int state);
@@ -140,7 +140,6 @@ class SetupPanel : public ModelPanel
void startupSwitchToggled(bool checked);
void potWarningToggled(bool checked);
void on_potWarningMode_currentIndexChanged(int index);
void onChildModified();
private:
Ui::Setup *ui;
+22 -53
View File
@@ -22,6 +22,7 @@
#include "modelprinter.h"
#include "multiprotocols.h"
#include <QApplication>
#include <QPainter>
#include <QFile>
#include <QUrl>
@@ -76,18 +77,12 @@ QString ModelPrinter::printEEpromSize()
QString ModelPrinter::printChannelName(int idx)
{
return tr("CH%1").arg(idx+1, 2, 10, QChar('0'));
}
QString ModelPrinter::printOutputName(int idx)
{
QString name = QString(model.limitData[idx].name).trimmed();
if (firmware->getCapability(ChannelsName) > 0 && !name.isEmpty()) {
return name;
}
else {
return "";
QString str = RawSource(SOURCE_TYPE_CH, idx).toString(&model, &generalSettings);
if (firmware->getCapability(ChannelsName)) {
str = str.leftJustified(firmware->getCapability(ChannelsName) + 5, ' ', false);
}
str.append(' ');
return str.toHtmlEscaped();
}
QString ModelPrinter::printTrimIncrementMode()
@@ -152,7 +147,7 @@ QString ModelPrinter::printMultiSubType(int rfProtocol, bool custom, unsigned in
Multiprotocols::MultiProtocolDefinition pdef = multiProtocols.getProtocol(rfProtocol);
if (subType < (unsigned int) pdef.subTypeStrings.size())
return pdef.subTypeStrings[subType];
return qApp->translate("Multiprotocols", qPrintable(pdef.subTypeStrings[subType]));
else
return "???";
}
@@ -333,20 +328,8 @@ QString ModelPrinter::printRotaryEncoder(int flightModeIndex, int reIndex)
QString ModelPrinter::printInputName(int idx)
{
QString result;
if (firmware->getCapability(VirtualInputs)) {
if (strlen(model.inputNames[idx]) > 0) {
result = tr("[I%1]").arg(idx+1);
result += QString(model.inputNames[idx]);
}
else {
result = tr("Input%1").arg(idx+1, 2, 10, QChar('0'));
}
}
else {
result = RawSource(SOURCE_TYPE_STICK, idx).toString(&model, &generalSettings);
}
return result.toHtmlEscaped();
RawSourceType srcType = (firmware->getCapability(VirtualInputs) ? SOURCE_TYPE_VIRTUAL_INPUT : SOURCE_TYPE_STICK);
return RawSource(srcType, idx).toString(&model, &generalSettings).toHtmlEscaped();
}
QString ModelPrinter::printInputLine(int idx)
@@ -368,9 +351,9 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
str += input.srcRaw.toString(&model, &generalSettings).toHtmlEscaped();
}
str += " " + tr("Weight").toHtmlEscaped() + QString("(%1)").arg(getGVarString(input.weight,true).toHtmlEscaped());
str += " " + tr("Weight").toHtmlEscaped() + QString("(%1)").arg(Helpers::getAdjustmentString(input.weight, &model, true).toHtmlEscaped());
if (input.curve.value)
str += " " + input.curve.toString().toHtmlEscaped();
str += " " + input.curve.toString(&model).toHtmlEscaped();
QString flightModesStr = printFlightModes(input.flightModes);
if (!flightModesStr.isEmpty())
@@ -388,7 +371,7 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
}
if (input.offset)
str += " " + tr("Offset(%1)").arg(getGVarString(input.offset)).toHtmlEscaped();
str += " " + tr("Offset(%1)").arg(Helpers::getAdjustmentString(input.offset, &model)).toHtmlEscaped();
if (firmware->getCapability(HasExpoNames) && input.name[0])
str += QString(" [%1]").arg(input.name).toHtmlEscaped();
@@ -396,25 +379,6 @@ QString ModelPrinter::printInputLine(const ExpoData & input)
return str;
}
QString ModelPrinter::printMixerName(int curDest)
{
QString str = printChannelName(curDest-1) + " ";
if (firmware->getCapability(ChannelsName) > 0) {
QString name = model.limitData[curDest-1].name;
if (!name.isEmpty()) {
name = QString("(") + name + QString(")");
}
name.append(" ");
str += name.left(8);
}
return str.toHtmlEscaped();
}
QString ModelPrinter::printMixerLine(int idx, bool showMultiplex, int highlightedSource)
{
return printMixerLine(model.mixData[idx], highlightedSource, showMultiplex);
}
QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, int highlightedSource)
{
QString str = "&nbsp;";
@@ -439,7 +403,7 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in
if (mix.mltpx == MLTPX_MUL && !showMultiplex)
str += " " + QString("MULT!").toHtmlEscaped();
else
str += " " + tr("Weight(%1)").arg(getGVarString(mix.weight, true)).toHtmlEscaped();
str += " " + tr("Weight(%1)").arg(Helpers::getAdjustmentString(mix.weight, &model, true)).toHtmlEscaped();
QString flightModesStr = printFlightModes(mix.flightModes);
if (!flightModesStr.isEmpty())
@@ -456,9 +420,9 @@ QString ModelPrinter::printMixerLine(const MixData & mix, bool showMultiplex, in
if (firmware->getCapability(HasNoExpo) && mix.noExpo)
str += " " + tr("No DR/Expo").toHtmlEscaped();
if (mix.sOffset)
str += " " + tr("Offset(%1)").arg(getGVarString(mix.sOffset)).toHtmlEscaped();
str += " " + tr("Offset(%1)").arg(Helpers::getAdjustmentString(mix.sOffset, &model)).toHtmlEscaped();
if (mix.curve.value)
str += " " + mix.curve.toString().toHtmlEscaped();
str += " " + mix.curve.toString(&model).toHtmlEscaped();
int scale = firmware->getCapability(SlowScale);
if (scale == 0)
scale = 1;
@@ -519,7 +483,7 @@ QString ModelPrinter::printLogicalSwitchLine(int idx)
const QString sw1Name = RawSwitch(ls.val1).toString(getCurrentBoard(), &generalSettings);
const QString sw2Name = RawSwitch(ls.val2).toString(getCurrentBoard(), &generalSettings);
if (!ls.func)
if (ls.isEmpty())
return result;
if (ls.andsw!=0) {
@@ -642,7 +606,7 @@ QString ModelPrinter::printCustomFunctionLine(int idx)
return result;
result += cf.swtch.toString(getCurrentBoard(), &generalSettings) + " - ";
result += cf.funcToString() + "(";
result += cf.funcToString(&model) + " (";
result += cf.paramToString(&model) + ")";
if (!cf.repeatToString().isEmpty())
result += " " + cf.repeatToString();
@@ -651,6 +615,11 @@ QString ModelPrinter::printCustomFunctionLine(int idx)
return result;
}
QString ModelPrinter::printCurveName(int idx)
{
return model.curves[idx].nameToString(idx).toHtmlEscaped();
}
QString ModelPrinter::printCurve(int idx)
{
QString result;
+2 -4
View File
@@ -75,13 +75,11 @@ class ModelPrinter: public QObject
QString printInputName(int idx);
QString printInputLine(int idx);
QString printInputLine(const ExpoData & ed);
QString printMixerName(int curDest);
QString printMixerLine(int idx, bool showMultiplex, int highlightedSource = 0);
QString printMixerLine(const MixData & md, bool showMultiplex, int highlightedSource = 0);
QString printLogicalSwitchLine(int idx);
QString printCustomFunctionLine(int idx);
static QString printChannelName(int idx);
QString printOutputName(int idx);
QString printChannelName(int idx);
QString printCurveName(int idx);
QString printCurve(int idx);
QString createCurveImage(int idx, QTextDocument * document);
+6 -7
View File
@@ -351,7 +351,6 @@ QString MultiModelPrinter::printLimits()
columns.append("<table border='0' cellspacing='0' cellpadding='1' width='100%'>" \
"<tr>" \
" <td><b>" + tr("Channel") + "</b></td>" \
" <td><b>" + (firmware->getCapability(ChannelsName) > 0 ? tr("Name") : "") + "</b></td>" \
" <td><b>" + tr("Offset") + "</b></td>" \
" <td><b>" + tr("Min") + "</b></td>" \
" <td><b>" + tr("Max") + "</b></td>" \
@@ -365,8 +364,6 @@ QString MultiModelPrinter::printLimits()
continue;
columns.append("<tr><td><b>");
COMPARE(modelPrinter->printChannelName(i));
columns.append("</b></td><td>");
COMPARE(modelPrinter->printOutputName(i));
columns.append("</td><td>");
COMPARE(model->limitData[i].offsetToString());
columns.append("</td><td>");
@@ -441,7 +438,7 @@ QString MultiModelPrinter::printMixers()
}
if (count > 0) {
columns.append("<tr><td width='20%'><b>");
COMPARE(modelPrinter->printMixerName(i+1));
COMPARE(modelPrinter->printChannelName(i));
columns.append("</b></td><td>");
for (int j=0; j<count; j++) {
if (j > 0)
@@ -471,7 +468,9 @@ QString MultiModelPrinter::printCurves(QTextDocument * document)
}
if (!curveEmpty) {
count++;
columns.append("<tr><td width='20%'><b>" + tr("CV%1").arg(i+1) + "</b></td><td>");
columns.append("<tr><td width='20%'><b>");
COMPARE(modelPrinter->printCurveName(i));
columns.append("</b></td><td>");
COMPARE(modelPrinter->printCurve(i));
for (int k=0; k < modelPrinterMap.size(); k++)
columns.append(k, QString("<br/><img src='%1' border='0' />").arg(modelPrinterMap.value(k).second->createCurveImage(i, document)));
@@ -495,7 +494,7 @@ QString MultiModelPrinter::printLogicalSwitches()
for (int i=0; i<firmware->getCapability(LogicalSwitches); i++) {
bool lsEmpty = true;
for (int k=0; k < modelPrinterMap.size(); k++) {
if (!modelPrinterMap.value(k).second->printLogicalSwitchLine(i).isEmpty()) {
if (!modelPrinterMap.value(k).first->logicalSw[i].isEmpty()) {
lsEmpty = false;
break;
}
@@ -524,7 +523,7 @@ QString MultiModelPrinter::printCustomFunctions()
for (int i=0; i < firmware->getCapability(CustomFunctions); i++) {
bool sfEmpty = true;
for (int k=0; k < modelPrinterMap.size(); k++) {
if (modelPrinterMap.value(k).first->customFn[i].swtch.type != SWITCH_TYPE_NONE) {
if (!modelPrinterMap.value(k).first->customFn[i].isEmpty()) {
sfEmpty = false;
break;
}
+1 -2
View File
@@ -34,7 +34,6 @@
#define sleep(x) Sleep(x*1000)
#else
#include <unistd.h>
#include "mountlist.h"
#endif
FlashProcess::FlashProcess(const QString &cmd, const QStringList &args, ProgressWidget *progress):
@@ -240,7 +239,7 @@ void FlashProcess::onReadyReadStandardError()
void FlashProcess::errorWizard()
{
QString output = progress->getText();
if (output.contains("avrdude: Expected signature for")) { // wrong signature
int pos = output.indexOf("avrdude: Device signature = ");
bool fwexist = false;
+212 -89
View File
@@ -19,133 +19,256 @@
*/
#include "process_sync.h"
#include "progresswidget.h"
#include <QDirIterator>
#include <QApplication>
#include <QCryptographicHash>
#include <QDateTime>
#include <QMessageBox>
#include <QTextStream>
#include <QMutexLocker>
#include <QDirIterator>
#include <QDebug>
#include <QEventLoop>
#include <QTimer>
SyncProcess::SyncProcess(const QString & folder1, const QString & folder2, ProgressWidget * progress):
folder1(folder1),
folder2(folder2),
progress(progress),
index(0),
count(0),
closed(false)
#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))
#define QtInfoMsg QtMsgType(4)
#endif
#define PRINT_INFO(str) emit progressMessage((str), QtInfoMsg)
#define PRINT_CREATE(str) emit progressMessage((str), QtInfoMsg)
#define PRINT_REPLACE(str) emit progressMessage((str), QtWarningMsg)
#define PRINT_DELETE(str) emit progressMessage((str), QtCriticalMsg)
#define PRINT_ERROR(str) emit progressMessage((str), QtFatalMsg)
//#define PRINT_SKIP(str) emit progressMessage((str), QtDebugMsg) // mostly useless noise (maybe make an option later)
#define PRINT_SKIP(str)
#define PRINT_SEP() PRINT_INFO(QString(80, '='))
#define SYNC_MAX_ERRORS 50 // give up after this many errors per destination
SyncProcess::SyncProcess(const QString & folderA, const QString & folderB, const int & syncDirection, const int & compareType, const qint64 & maxFileSize, const bool dryRun):
folder1(folderA),
folder2(folderB),
direction((SyncDirection)syncDirection),
ctype((SyncCompareType)compareType),
maxFileSize(qMax<qint64>(0, maxFileSize)),
dryRun(dryRun),
stopping(false)
{
connect(progress, SIGNAL(stopped()),this, SLOT(onClosed()));
if (direction == SYNC_B2A_A2B) {
folder1 = folderB;
folder2 = folderA;
direction = SYNC_A2B_B2A;
}
if (ctype == OVERWR_ALWAYS && direction == SYNC_A2B_B2A)
ctype = OVERWR_IF_DIFF;
dirFilters = QDir::Filters(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
reportTemplate = tr("New: <b>%1</b>; Updated: <b>%2</b>; Skipped: <b>%3</b>; Errors: <font color=%5><b>%4</b></font>;");
if (dryRun)
testRunStr = tr("[TEST RUN] ");
}
void SyncProcess::onClosed()
void SyncProcess::stop()
{
closed = true;
QMutexLocker locker(&stopReqMutex);
stopping = true;
}
bool SyncProcess::run()
bool SyncProcess::isStopRequsted()
{
if (!QFile::exists(folder1)) {
QMessageBox::warning(NULL, QObject::tr("Synchronization error"), QObject::tr("The directory '%1' doesn't exist!").arg(folder1));
return true;
QMutexLocker locker(&stopReqMutex);
return stopping;
}
void SyncProcess::run()
{
count = index = created = updated = skipped = errored = 0;
emit started();
emit progressStep(index);
emit statusMessage(tr("Gathering file information..."));
if (direction == SYNC_A2B_B2A || direction == SYNC_A2B)
count += getFilesCount(folder1);
if (isStopRequsted()) {
finish();
return;
}
if (!QFile::exists(folder2)) {
QMessageBox::warning(NULL, QObject::tr("Synchronization error"), QObject::tr("The directory '%1' doesn't exist!").arg(folder2));
return true;
if (direction == SYNC_A2B_B2A || direction == SYNC_B2A)
count += getFilesCount(folder2);
if (isStopRequsted()) {
finish();
return;
}
count = getFilesCount(folder1) + getFilesCount(folder2);
progress->setMaximum(count);
emit fileCountChanged(count);
QStringList errors = updateDir(folder1, folder2) + updateDir(folder2, folder1);
if (errors.count() > 0) {
QMessageBox::warning(NULL, QObject::tr("Synchronization error"), errors.join("\n"));
if (!count) {
QString nf = tr("Synchronization failed, nothing found to copy.");
emit statusMessage(nf);
PRINT_ERROR(nf);
emit finished();
return;
}
// don't close the window unless the user wanted
return closed;
if (direction == SYNC_A2B_B2A || direction == SYNC_A2B)
updateDir(folder1, folder2);
if (isStopRequsted()) {
finish();
return;
}
if (direction == SYNC_A2B_B2A || direction == SYNC_B2A)
updateDir(folder2, folder1);
finish();
}
void SyncProcess::finish()
{
QString endStr = testRunStr % tr("Synchronization finished. ") % reportTemplate;
emit statusMessage(endStr.arg(created).arg(updated).arg(skipped).arg(errored).arg(errored ? "red" : "black"));
emit finished();
}
int SyncProcess::getFilesCount(const QString & directory)
{
if (!QFile::exists(directory))
return 0;
int result = 0;
QDirIterator it(directory, QDirIterator::Subdirectories);
while (it.hasNext()) {
QDirIterator it(directory, dirFilters, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
while (it.hasNext() && !isStopRequsted()) {
it.next();
result++;
QApplication::processEvents();
}
return result;
}
QStringList SyncProcess::updateDir(const QString & source, const QString & destination)
void SyncProcess::updateDir(const QString & source, const QString & destination)
{
QDirIterator it(source, QDirIterator::Subdirectories);
while (!closed && it.hasNext()) {
QEventLoop loop;
QTimer::singleShot(10, &loop, SLOT(quit()));
loop.exec();
index++;
progress->setInfo(tr("%1/%2 files").arg(index).arg(count));
progress->setValue(index);
QString result = updateEntry(it.next(), source, destination);
if (!result.isEmpty()) {
errors << result;
int counts[4] = { created, updated, skipped, errored };
QString statusStr = testRunStr % tr("Synchronizing %1 -&gt; %2: %3").arg(source, destination, "<b>%1</b>|<b>%2</b> (%3)");
PRINT_INFO(testRunStr % tr("Starting synchronization: %1 -&gt; %2<br>").arg(source, destination));
QDirIterator it(source, dirFilters, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
while (it.hasNext() && !isStopRequsted()) {
it.next();
++index;
emit statusMessage(statusStr.arg(index).arg(count).arg(reportTemplate.arg(created).arg(updated).arg(skipped).arg(errored).arg(errored ? "red" : "black")));
emit progressStep(index);
if (maxFileSize && it.fileInfo().isFile() && it.fileInfo().size() > maxFileSize) {
PRINT_SKIP(tr("Skipping large file: %1 (%2KB)").arg(it.fileName()).arg(int(it.fileInfo().size() / 1024)));
++skipped;
}
else {
updateEntry(it.filePath(), source, destination);
if (errored - counts[3] > SYNC_MAX_ERRORS) {
PRINT_ERROR(tr("<br><b>Too many errors, giving up.<b>"));
break;
}
}
QApplication::processEvents();
}
return errors;
QString endStr = "<br>" % testRunStr % tr("Finished synchronizing %1 -&gt; %2 :<br>&nbsp;&nbsp;&nbsp;&nbsp; %3").arg(source, destination, reportTemplate);
PRINT_INFO(endStr.arg(created-counts[0]).arg(updated-counts[1]).arg(skipped-counts[2]).arg(errored-counts[3]).arg(errored-counts[3] ? "red" : "black"));
PRINT_SEP();
}
QString SyncProcess::updateEntry(const QString & path, const QDir & source, const QDir & destination)
bool SyncProcess::updateEntry(const QString & entry, const QDir & source, const QDir & destination)
{
QFileInfo sourceInfo(path);
QString relativePath = source.relativeFilePath(path);
QString destinationPath = destination.absoluteFilePath(relativePath);
QFileInfo destinationInfo(destinationPath);
QString srcPath = source.toNativeSeparators(source.absoluteFilePath(entry));
QString relPath = source.relativeFilePath(entry);
QString destPath = destination.toNativeSeparators(destination.absoluteFilePath(relPath));
QFileInfo sourceInfo(srcPath);
QFileInfo destInfo(destPath);
if (sourceInfo.isDir()) {
if (!destinationInfo.exists()) {
progress->addText(tr("Create directory %1\n").arg(destinationPath));
if (!destination.mkdir(relativePath)) {
return QObject::tr("Create '%1' failed").arg(destinationPath);
if (!destInfo.exists()) {
PRINT_CREATE(tr("Creating directory: %1").arg(destPath));
if (!dryRun && !destination.mkpath(destPath)) {
PRINT_ERROR(tr("Could not create directory: %1").arg(destPath));
++errored;
return false;
}
++created;
}
else {
PRINT_SKIP(tr("Destination directory exists: %1").arg(destPath));
++skipped;
}
return true;
}
else {
if (!destinationInfo.exists()) {
// qDebug() << "Copy" << path << "to" << destinationPath;
progress->addText(tr("Copy %1 to %2").arg(path).arg(destinationPath) + "\n");
if (!QFile::copy(path, destinationPath)) {
return QObject::tr("Copy '%1' to '%2' failed").arg(path).arg(destinationPath);
}
}
else if (sourceInfo.lastModified() > destinationInfo.lastModified()) {
// retrieve source contents
QFile sourceFile(path);
if (!sourceFile.open(QFile::ReadOnly)) {
return QObject::tr("Open '%1' failed").arg(path);
}
QString sourceContents = sourceFile.readAll();
sourceFile.close();
// try to retrieve destination contents
QFile destinationFile(destinationPath);
if (destinationFile.open(QFile::ReadOnly)) {
QString destinationContents = destinationFile.readAll();
destinationFile.close();
if (sourceContents == destinationContents) {
// qDebug() << "Skip" << path;
return QString();
}
}
if (!destinationFile.open(QFile::WriteOnly)) {
return QObject::tr("Write '%1' failed").arg(destinationPath);
}
progress->addText(tr("Write %1").arg(destinationPath) + "\n");
// qDebug() << "Write" << destinationPath;
QTextStream destinationStream(&destinationFile);
destinationStream << sourceContents;
destinationFile.close();
QFile sourceFile(srcPath);
QFile destinationFile(destPath);
bool destExists = destInfo.exists();
bool checkDate = (ctype == OVERWR_NEWER_IF_DIFF || ctype == OVERWR_NEWER_ALWAYS);
bool checkContent = (ctype == OVERWR_NEWER_IF_DIFF || ctype == OVERWR_IF_DIFF);
bool existed = false;
if (destExists && checkDate) {
if (sourceInfo.lastModified() <= destInfo.lastModified()) {
PRINT_SKIP(tr("Skipping older file: %1").arg(srcPath));
++skipped;
return true;
}
checkDate = false;
}
return QString();
if (destExists && checkContent) {
if (!sourceFile.open(QFile::ReadOnly)) {
PRINT_ERROR(tr("Could not open source file '%1': %2").arg(srcPath, sourceFile.errorString()));
++errored;
return false;
}
if (!destinationFile.open(QFile::ReadOnly)) {
PRINT_ERROR(tr("Could not open destination file '%1': %2").arg(destPath, destinationFile.errorString()));
++errored;
return false;
}
bool skip = QCryptographicHash::hash(sourceFile.readAll(), QCryptographicHash::Md5) == QCryptographicHash::hash(destinationFile.readAll(), QCryptographicHash::Md5);
sourceFile.close();
destinationFile.close();
if (skip) {
PRINT_SKIP(tr("Skipping identical file: %1").arg(srcPath));
++skipped;
return true;
}
checkContent = false;
}
if (!destExists || (!checkDate && !checkContent)) {
if (destInfo.exists()) {
existed = true;
PRINT_REPLACE(tr("Replacing destination file: %1").arg(destPath));
if (!dryRun && !destinationFile.remove()) {
PRINT_ERROR(tr("Could not delete destination file '%1': %2").arg(destPath, destinationFile.errorString()));
++errored;
return false;
}
}
else {
PRINT_CREATE(tr("Creating destination file: %1").arg(destPath));
}
if (!dryRun && !sourceFile.copy(destPath)) {
PRINT_ERROR(tr("Copy failed: '%1' to '%2': %3").arg(srcPath, destPath, sourceFile.errorString()));
++errored;
return false;
}
if (existed)
++updated;
else
++created;
}
return true;
}
+51 -13
View File
@@ -22,34 +22,72 @@
#define _PROCESS_SYNC_H_
#include <QObject>
#include <QDir>
#include <QMutex>
#include <QString>
#include <QStringList>
class QDir;
class ProgressWidget;
class SyncProcess : public QObject
{
Q_OBJECT
public:
SyncProcess(const QString & folder1, const QString & folder2, ProgressWidget * progress);
bool run();
enum SyncDirection {
SYNC_A2B_B2A,
SYNC_B2A_A2B,
SYNC_A2B,
SYNC_B2A
};
protected slots:
void onClosed();
enum SyncCompareType {
OVERWR_NEWER_IF_DIFF,
OVERWR_NEWER_ALWAYS,
OVERWR_IF_DIFF,
OVERWR_ALWAYS
};
SyncProcess(const QString & folderA,
const QString & folderB,
const int & syncDirection = SYNC_A2B_B2A,
const int & compareType = OVERWR_NEWER_IF_DIFF,
const qint64 & maxFileSize = 5*1024*1024,
const bool dryRun = false);
public slots:
void run();
void stop();
signals:
void started();
void finished();
void fileCountChanged(int count);
void progressStep(int step);
void progressMessage(const QString & text, const int & type);
void statusMessage(const QString & text);
protected:
bool isStopRequsted();
void finish();
int getFilesCount(const QString & directory);
QStringList updateDir(const QString & source, const QString & destination);
QString updateEntry(const QString & path, const QDir & source, const QDir & destination);
void updateDir(const QString & source, const QString & destination);
bool updateEntry(const QString & entry, const QDir & source, const QDir & destination);
QString folder1;
QString folder2;
ProgressWidget * progress;
QStringList errors;
SyncDirection direction;
SyncCompareType ctype;
qint64 maxFileSize; // Bytes
QDir::Filters dirFilters;
QMutex stopReqMutex;
QString reportTemplate;
QString testRunStr;
int index;
int count;
bool closed;
int created;
int updated;
int skipped;
int errored;
bool dryRun;
bool stopping;
};
#endif // _PROCESS_SYNC_H_
+12
View File
@@ -32,6 +32,7 @@ locked(false)
ui->setupUi(this);
setWindowTitle(title);
setWindowIcon(icon);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
if (forceOpen) {
ui->outputProgress->forceOpen();
}
@@ -53,6 +54,7 @@ void ProgressDialog::on_closeButton_clicked()
{
if (!locked) {
ui->outputProgress->stop();
emit rejected();
close();
}
}
@@ -77,3 +79,13 @@ bool ProgressDialog::isEmpty() const
{
return ui->outputProgress->isEmpty();
}
void ProgressDialog::setProcessStarted()
{
ui->closeButton->setText(tr("Cancel"));
}
void ProgressDialog::setProcessStopped()
{
ui->closeButton->setText(tr("Close"));
}
+4
View File
@@ -41,6 +41,10 @@ public:
ProgressWidget * progress();
bool isEmpty() const;
public slots:
void setProcessStarted();
void setProcessStopped();
private slots:
void on_closeButton_clicked();
void on_outputProgress_detailsToggled();
+30 -27
View File
@@ -6,22 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>431</width>
<height>115</height>
<width>646</width>
<height>211</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Flash Firmware</string>
</property>
@@ -29,28 +23,37 @@
<iconset resource="companion.qrc">
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,0">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>7</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="ProgressWidget" name="outputProgress" native="true"/>
</item>
<item>
<spacer name="spacer2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<widget class="ProgressWidget" name="outputProgress" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<spacer name="spacer1">
<property name="orientation">
@@ -59,7 +62,7 @@
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
<height>1</height>
</size>
</property>
</spacer>
+46 -11
View File
@@ -34,14 +34,15 @@ ui(new Ui::ProgressWidget)
ui->checkBox->hide();
ui->textEdit->hide();
QFont newFont(ui->textEdit->font());
newFont.setFamily("Courier");
#ifdef __APPLE__
QFont newFont("Courier", 13);
ui->textEdit->setFont(newFont);
newFont.setPointSize(13);
ui->textEdit->setAttribute(Qt::WA_MacNormalSize);
#elif defined WIN32 || !defined __GNUC__
QFont newFont("Courier", 9);
ui->textEdit->setFont(newFont);
newFont.setPointSize(9);
#endif
ui->textEdit->setFont(newFont);
}
ProgressWidget::~ProgressWidget()
@@ -81,14 +82,10 @@ void ProgressWidget::setValue(int value)
ui->progressBar->setValue(value);
}
void ProgressWidget::addText(const QString &text)
void ProgressWidget::addText(const QString &text, const bool richText)
{
ui->checkBox->setVisible(true);
if (g.outputDisplayDetails()) {
ui->checkBox->setChecked(true);
ui->textEdit->setVisible(true);
}
ui->checkBox->setChecked(g.outputDisplayDetails());
QTextCursor cursor(ui->textEdit->textCursor());
@@ -96,13 +93,51 @@ void ProgressWidget::addText(const QString &text)
bool atEnd = (ui->textEdit->verticalScrollBar()->value() == ui->textEdit->verticalScrollBar()->maximum());
cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor, 1);
cursor.insertText(text);
if (richText)
cursor.insertHtml(text);
else
cursor.insertText(text);
if (atEnd) {
ui->textEdit->verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMaximum);
}
}
void ProgressWidget::addHtml(const QString & text)
{
addText(text, true);
}
void ProgressWidget::addMessage(const QString & text, const int & type)
{
QString color;
switch (type) {
case QtDebugMsg:
color = "dimgrey"; // not important messages, may be filtered out
break;
case QtWarningMsg: // use warning level as emphasis
color = "darkblue";
break;
case QtCriticalMsg: // use critical as a warning
color = "#ff7900";
break;
case QtFatalMsg: // fatal for hard errors
color = "red";
break;
case QtInfoMsg: // default plain text
default:
break;
}
if (color.isEmpty()) {
if (text.contains(QRegExp("<[^>]+>"))) // detect html (rouhgly)
addHtml(text % "<br>");
else
addText(text % "\n", false);
}
else
addHtml(QString("<font color=%1>").arg(color) % text % "</font><br>");
}
QString ProgressWidget::getText()
{
return ui->textEdit->toPlainText();
+7 -1
View File
@@ -23,6 +23,10 @@
#include <QWidget>
#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))
#define QtInfoMsg QtMsgType(4)
#endif
namespace Ui {
class ProgressWidget;
}
@@ -35,7 +39,9 @@ class ProgressWidget : public QWidget
explicit ProgressWidget(QWidget *parent);
~ProgressWidget();
void lock(bool lock);
void addText(const QString &text);
void addText(const QString &text, const bool richText = false);
void addHtml(const QString &text);
void addMessage(const QString & text, const int & type = QtInfoMsg);
QString getText();
void setInfo(const QString &text);
void setMaximum(int value);
+86 -55
View File
@@ -9,26 +9,26 @@
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>244</height>
<width>753</width>
<height>474</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>700</width>
<width>650</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1,0">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
@@ -43,56 +43,79 @@
</property>
<item>
<widget class="QLabel" name="info">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
<string notr="true"/>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<item>
<widget class="QProgressBar" name="progressBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Show Details</string>
</property>
</widget>
</item>
</layout>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Show Details</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="textEdit">
<widget class="QTextEdit" name="textEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>100</height>
<width>0</width>
<height>350</height>
</size>
</property>
<property name="font">
@@ -101,32 +124,40 @@
<pointsize>10</pointsize>
</font>
</property>
<property name="lineWidth">
<number>80</number>
</property>
<property name="midLineWidth">
<number>80</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="plainText">
<string/>
<property name="html">
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Courier'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByMouse</set>
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
+11 -1
View File
@@ -171,6 +171,16 @@ void GeneralSettings::convert(Board::Type before, Board::Type after)
}
}
/*
* RadioData
*/
RadioData::RadioData()
{
models.resize(getCurrentFirmware()->getCapability(Models));
}
void RadioData::setCurrentModel(unsigned int index)
{
generalSettings.currModelIndex = index;
@@ -244,4 +254,4 @@ void RadioData::convert(Board::Type before, Board::Type after)
if (IS_HORUS(after)) {
fixModelFilenames();
}
}
}
+9 -2
View File
@@ -231,6 +231,7 @@ class RawSource {
}
bool isTimeBased() const;
bool isStick(int * potsIndex = NULL) const;
bool isPot(int * potsIndex = NULL) const;
bool isSlider(int * sliderIndex = NULL) const;
@@ -315,7 +316,7 @@ class CurveReference {
CurveRefType type;
int value;
QString toString() const;
QString toString(const ModelData * model = NULL, bool verbose = true) const;
};
enum InputMode {
@@ -360,6 +361,8 @@ class CurveData {
CurveData();
void clear(int count);
bool isEmpty() const;
QString nameToString(const int idx) const;
CurveType type;
bool smooth;
int count;
@@ -467,7 +470,9 @@ class LogicalSwitchData { // Logical Switches data
unsigned int delay;
unsigned int duration;
int andsw;
void clear() { memset(this, 0, sizeof(LogicalSwitchData)); }
bool isEmpty() const;
CSFunctionFamily getFunctionFamily() const;
unsigned int getRangeFlags() const;
QString funcToString() const;
@@ -530,8 +535,10 @@ class CustomFunctionData { // Function Switches data
unsigned int enabled; // TODO perhaps not any more the right name
unsigned int adjustMode;
int repeatParam;
void clear();
QString funcToString() const;
bool isEmpty() const;
QString funcToString(const ModelData * model = NULL) const;
QString paramToString(const ModelData * model) const;
QString repeatToString() const;
QString enabledToString() const;
+48 -40
View File
@@ -25,15 +25,10 @@
#include "radionotfound.h"
#include "burnconfigdialog.h"
#include "helpers.h"
#include "mountlist.h"
#include "process_copy.h"
#include "storage.h"
#include "progresswidget.h"
#if defined WIN32 || !defined __GNUC__
#include <windows.h>
#endif
QString getRadioInterfaceCmd()
{
burnConfigDialog bcd;
@@ -401,7 +396,9 @@ bool writeEeprom(const QString & filename, ProgressWidget * progress)
return false;
}
#if (QT_VERSION < QT_VERSION_CHECK(5, 4, 0))
#if defined WIN32 || !defined __GNUC__
#include <windows.h>
bool isRemovableMedia(const QString & vol)
{
char szDosDeviceName[MAX_PATH];
@@ -415,61 +412,69 @@ bool isRemovableMedia(const QString & vol)
}
return true;
}
#endif
#else
#include "mountlist.h"
#endif // defined WIN32 || !defined __GNUC__
#endif // (QT_VERSION < QT_VERSION_CHECK(5, 4, 0))
QString findMassstoragePath(const QString & filename, bool onlyPath)
{
QString temppath;
QStringList drives;
QString eepromfile;
QString fsname;
bool found = false;
QRegularExpression fstypeRe("^(v?fat|msdos)", QRegularExpression::CaseInsensitiveOption); // Linux: "vfat"; macOS: "msdos"; Win: "FAT32"
#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
foreach(const QStorageInfo & si, QStorageInfo::mountedVolumes()) {
//qDebug() << si.rootPath() << si.name() << si.device() << si.displayName() << si.fileSystemType() << si.isReady();
if (!si.isReady() || !QString(si.fileSystemType()).contains(fstypeRe))
continue;
temppath = si.rootPath();
eepromfile = temppath % "/" % filename;
qDebug() << "Searching for" << eepromfile;
if (QFile::exists(eepromfile)) {
found = true;
break;
}
}
#elif defined WIN32 || !defined __GNUC__
static QStringList blacklist;
#if defined WIN32 || !defined __GNUC__
foreach(QFileInfo drive, QDir::drives()) {
foreach(const QFileInfo & drive, QDir::drives()) {
temppath = drive.absolutePath();
if (blacklist.contains(temppath))
continue;
if (!isRemovableMedia(temppath)) {
blacklist.append(temppath);
continue;
}
WCHAR szVolumeName[256] ;
WCHAR szFileSystemName[256];
DWORD dwSerialNumber = 0;
DWORD dwMaxFileNameLength=256;
DWORD dwFileSystemFlags=0;
if (!blacklist.contains(drive.absolutePath())) {
if (!isRemovableMedia( drive.absolutePath() )) {
blacklist.append(drive.absolutePath());
} else {
bool ret = GetVolumeInformationW( (WCHAR *) drive.absolutePath().utf16(),szVolumeName,256,&dwSerialNumber,&dwMaxFileNameLength,&dwFileSystemFlags,szFileSystemName,256);
if (ret) {
QString vName = QString::fromUtf16 ( (const ushort *) szVolumeName) ;
temppath = drive.absolutePath();
eepromfile = temppath;
eepromfile.append("/" + filename);
if (QFile::exists(eepromfile)) {
return onlyPath ? temppath : eepromfile;
}
}
}
if (!GetVolumeInformationW( (WCHAR *) drive.absolutePath().utf16(),szVolumeName,256,&dwSerialNumber,&dwMaxFileNameLength,&dwFileSystemFlags,szFileSystemName,256))
continue;
eepromfile = temppath % "/" % filename;
qDebug() << "Searching for" << eepromfile;
if (QFile::exists(eepromfile)) {
found = true;
break;
}
}
#else
const static QStringList blacklist = QStringList() << "/" << "/net" << "/proc" << "/run";
QStringList drives;
struct mount_entry *entry;
struct mount_entry *firstEntry;
firstEntry = entry = read_file_system_list(true);
while (entry != NULL) {
if (!drives.contains(entry->me_devname)) {
temppath = entry->me_mountdir;
if (!drives.contains(entry->me_devname) && !blacklist.contains(temppath) && QString(entry->me_type).contains(fstypeRe)) {
drives.append(entry->me_devname);
temppath = entry->me_mountdir;
eepromfile = temppath;
eepromfile.append("/" + filename);
eepromfile = temppath % "/" % filename;
qDebug() << "Searching for" << eepromfile;
#if !defined __APPLE__
QString fstype = entry->me_type;
// qDebug() << eepromfile;
if (fstype.contains("fat") && QFile::exists(eepromfile)) {
#else
if (QFile::exists(eepromfile)) {
#endif
free_file_system_list(firstEntry);
return onlyPath ? temppath : eepromfile;
found = true;
break;
}
}
entry = entry->me_next;
@@ -477,5 +482,8 @@ QString findMassstoragePath(const QString & filename, bool onlyPath)
free_file_system_list(firstEntry);
#endif
return QString();
if (found)
return onlyPath ? temppath : eepromfile;
else
return QString();
}
@@ -267,7 +267,7 @@ QWidget * RadioOutputsWidget::createLogicalSwitch(QWidget * parent, int switchNo
swtch->setMinimumWidth(swtch->fontMetrics().width("99") + 10);
font.setBold(false);
swtch->setFont(font);
swtch->setText(QString("%1").arg(RawSwitch(SWITCH_TYPE_VIRTUAL, switchNo+1).toString().remove("L"), 2, QLatin1Char('0')));
swtch->setText(QString("%1").arg(switchNo+1, 2, 10, QChar('0')));
swtch->setAlignment(Qt::AlignCenter);
m_logicSwitchMap.insert(switchNo, swtch);
return swtch;
@@ -38,40 +38,40 @@ SimulatedUIWidget9X::SimulatedUIWidget9X(SimulatorInterface * simulator, QWidget
int x = 68, y = 91, oR = 63;
polygon << QPoint(x, y) << polyArc(x, y, oR, -45, 45);
act = new RadioUiAction(3, QList<int>() << Qt::Key_Up << Qt::Key_PageUp, tr(SIMU_STR_HLP_KEYS_GO_UP) % (hasRotEnc ? "" : tr("|" SIMU_STR_HLP_MOUSE_UP)), tr(SIMU_STR_HLP_ACT_UP));
act = new RadioUiAction(3, QList<int>() << Qt::Key_Up << Qt::Key_PageUp, SIMU_STR_HLP_KEYS_GO_UP % (hasRotEnc ? QString("") : "|" % SIMU_STR_HLP_MOUSE_UP), SIMU_STR_HLP_ACT_UP);
addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursup.png", act));
polygon.clear();
polygon << QPoint(x, y) << polyArc(x, y, oR, 135, 225);
act = new RadioUiAction(2, QList<int>() << Qt::Key_Down << Qt::Key_PageDown, tr(SIMU_STR_HLP_KEYS_GO_DN) % (hasRotEnc ? "" : tr("|" SIMU_STR_HLP_MOUSE_DN)), tr(SIMU_STR_HLP_ACT_DN));
act = new RadioUiAction(2, QList<int>() << Qt::Key_Down << Qt::Key_PageDown, SIMU_STR_HLP_KEYS_GO_DN % (hasRotEnc ? QString("") : "|" % SIMU_STR_HLP_MOUSE_DN), SIMU_STR_HLP_ACT_DN);
addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursdown.png", act));
polygon.clear();
polygon << QPoint(x, y) << polyArc(x, y, oR, 45, 135);
act = new RadioUiAction(4, QList<int>() << Qt::Key_Right << Qt::Key_Minus, tr(SIMU_STR_HLP_KEY_RGT "|" SIMU_STR_HLP_KEY_MIN), tr(SIMU_STR_HLP_ACT_MIN));
act = new RadioUiAction(4, QList<int>() << Qt::Key_Right << Qt::Key_Minus, SIMU_STR_HLP_KEY_RGT % "|" % SIMU_STR_HLP_KEY_MIN, SIMU_STR_HLP_ACT_MIN);
addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursmin.png", act));
polygon.clear();
polygon << QPoint(x, y) << polyArc(x, y, oR, 225, 315);
act = new RadioUiAction(5, QList<int>() << Qt::Key_Left << Qt::Key_Plus << Qt::Key_Equal, tr(SIMU_STR_HLP_KEY_LFT "|" SIMU_STR_HLP_KEY_PLS), tr(SIMU_STR_HLP_ACT_PLS));
act = new RadioUiAction(5, QList<int>() << Qt::Key_Left << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_LFT % "|" % SIMU_STR_HLP_KEY_PLS, SIMU_STR_HLP_ACT_PLS);
addRadioWidget(ui->leftbuttons->addArea(polygon, "9X/9xcursplus.png", act));
act = new RadioUiAction(0, QList<int>() << Qt::Key_Enter << Qt::Key_Return, tr(SIMU_STR_HLP_KEY_ENTER), tr(SIMU_STR_HLP_ACT_MENU));
act = new RadioUiAction(0, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEY_ENTER, SIMU_STR_HLP_ACT_MENU);
addRadioWidget(ui->rightbuttons->addArea(QRect(16, 54, 60, 34), "9X/9xmenumenu.png", act));
if (!hasRotEnc) {
m_mouseMidClickAction = act;
m_mouseMidClickAction->setText(act->getText() % "|" SIMU_STR_HLP_MOUSE_MID);
m_mouseMidClickAction->setText(act->getText() % "|" % SIMU_STR_HLP_MOUSE_MID);
}
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr(SIMU_STR_HLP_KEYS_EXIT), tr(SIMU_STR_HLP_ACT_EXIT));
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
addRadioWidget(ui->rightbuttons->addArea(QRect(16, 114, 60, 34), "9X/9xmenuexit.png", act));
addRadioWidget(ui->leftbuttons->addArea(QRect(6, 149, 30, 30), "9X/9xcursphoto.png", m_screenshotAction));
if (hasRotEnc) {
addRadioAction(new RadioUiAction(-1, 0, tr(SIMU_STR_HLP_MOUSE_SCRL), tr(SIMU_STR_HLP_ROTENC " " SIMU_STR_HLP_ROTENC_LR)));
m_mouseMidClickAction = new RadioUiAction(14, Qt::Key_Insert, tr(SIMU_STR_HLP_KEY_INS "|" SIMU_STR_HLP_MOUSE_MID), tr(SIMU_STR_HLP_ACT_ROT_DN));
addRadioAction(new RadioUiAction(-1, 0, SIMU_STR_HLP_MOUSE_SCRL, SIMU_STR_HLP_ROTENC % "|" % SIMU_STR_HLP_ROTENC_LR));
m_mouseMidClickAction = new RadioUiAction(14, Qt::Key_Insert, SIMU_STR_HLP_KEY_INS % "|" % SIMU_STR_HLP_MOUSE_MID, SIMU_STR_HLP_ACT_ROT_DN);
addRadioWidget(ui->leftbuttons->addArea(QRect(0, 0, 0, 0), "9X/9xcurs.png", m_mouseMidClickAction));
}
@@ -35,40 +35,40 @@ SimulatedUIWidgetX12::SimulatedUIWidgetX12(SimulatorInterface *simulator, QWidge
int x = 74, y = 190, oR = 63, iR = 40;
polygon << polyArc(x, y, oR, 225, 315) << polyArc(x, y, iR, 225, 315);
act = new RadioUiAction(0, QList<int>() << Qt::Key_PageUp, tr(SIMU_STR_HLP_KEY_PGUP), tr(SIMU_STR_HLP_ACT_PGUP));
act = new RadioUiAction(0, QList<int>() << Qt::Key_PageUp, SIMU_STR_HLP_KEY_PGUP, SIMU_STR_HLP_ACT_PGUP);
addRadioWidget(ui->leftbuttons->addArea(polygon, "Horus/left_btn1.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, 135, 225) << polyArc(x, y, iR, 135, 225);
act = new RadioUiAction(1, QList<int>() << Qt::Key_PageDown, tr(SIMU_STR_HLP_KEY_PGDN), tr(SIMU_STR_HLP_ACT_PGDN));
act = new RadioUiAction(1, QList<int>() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN);
addRadioWidget(ui->leftbuttons->addArea(polygon, "Horus/left_btn2.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, -45, 45) << polyArc(x, y, iR, -45, 45);
act = new RadioUiAction(3, QList<int>() << Qt::Key_Up, tr(SIMU_STR_HLP_KEY_UP), tr(SIMU_STR_HLP_ACT_MDL));
act = new RadioUiAction(3, QList<int>() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL);
addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnU.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, 225, 315) << polyArc(x, y, iR, 225, 315);
act = new RadioUiAction(6, QList<int>() << Qt::Key_Left, tr(SIMU_STR_HLP_KEY_LFT), tr(SIMU_STR_HLP_ACT_SYS));
act = new RadioUiAction(6, QList<int>() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS);
addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnL.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, 45, 135) << polyArc(x, y, iR, 45, 135);
act = new RadioUiAction(5, QList<int>() << Qt::Key_Right, tr(SIMU_STR_HLP_KEY_RGT), tr(SIMU_STR_HLP_ACT_TELE));
act = new RadioUiAction(5, QList<int>() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE);
addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnR.png", act));
polygon.clear();
polygon << polyArc(x, y, oR, 135, 225) << polyArc(x, y, iR, 135, 225);
act = new RadioUiAction(4, QList<int>() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace,
tr(SIMU_STR_HLP_KEY_DN "<br>" SIMU_STR_HLP_KEYS_EXIT), tr(SIMU_STR_HLP_ACT_RTN));
SIMU_STR_HLP_KEY_DN % "<br>" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN);
addRadioWidget(ui->rightbuttons->addArea(polygon, "Horus/right_btnD.png", act));
m_scrollUpAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Minus, tr(SIMU_STR_HLP_KEY_MIN "|" SIMU_STR_HLP_MOUSE_UP), tr(SIMU_STR_HLP_ACT_ROT_LFT));
m_scrollDnAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Equal, tr(SIMU_STR_HLP_KEY_PLS "|" SIMU_STR_HLP_MOUSE_DN), tr(SIMU_STR_HLP_ACT_ROT_RGT));
m_scrollUpAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT);
m_scrollDnAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT);
connectScrollActions();
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, tr(SIMU_STR_HLP_KEYS_ACTIVATE), tr(SIMU_STR_HLP_ACT_ROT_DN));
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
addRadioWidget(ui->rightbuttons->addArea(polyArc(x, y, iR), "Horus/right_ent.png", m_mouseMidClickAction));
addRadioWidget(ui->leftbuttons->addArea(QRect(9, 259, 30, 30), "Horus/left_scrnsht.png", m_screenshotAction));
@@ -14,22 +14,22 @@ SimulatedUIWidgetX7::SimulatedUIWidgetX7(SimulatorInterface *simulator, QWidget
QPoint ctr(70, 91);
polygon << polyArc(ctr.x(), ctr.y(), 50, -90, 90) << polyArc(ctr.x(), ctr.y(), 22, -90, 90);
act = new RadioUiAction(3, QList<int>() << Qt::Key_PageUp << Qt::Key_Up, tr(SIMU_STR_HLP_KEYS_GO_UP), tr(SIMU_STR_HLP_ACT_PAGE));
act = new RadioUiAction(3, QList<int>() << Qt::Key_PageUp << Qt::Key_Up, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_PAGE);
addRadioWidget(ui->leftbuttons->addArea(polygon, "X7/left_page.png", act));
act = new RadioUiAction(0, QList<int>() << Qt::Key_PageDown << Qt::Key_Down, tr(SIMU_STR_HLP_KEYS_GO_DN), tr(SIMU_STR_HLP_ACT_MENU_ICN));
act = new RadioUiAction(0, QList<int>() << Qt::Key_PageDown << Qt::Key_Down, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_MENU_ICN);
addRadioWidget(ui->leftbuttons->addArea(polyArc(ctr.x(), ctr.y(), 20), "X7/left_menu.png", act));
polygon.clear();
polygon << polyArc(ctr.x(), ctr.y(), 50, 90, 270) << polyArc(ctr.x(), ctr.y(), 22, 90, 270);
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr(SIMU_STR_HLP_KEYS_EXIT), tr(SIMU_STR_HLP_ACT_EXIT));
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
addRadioWidget(ui->leftbuttons->addArea(polygon, "X7/left_exit.png", act));
m_scrollUpAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Left, tr(SIMU_STR_HLP_KEYS_GO_LFT), tr(SIMU_STR_HLP_ACT_ROT_LFT));
m_scrollDnAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Right, tr(SIMU_STR_HLP_KEYS_GO_RGT), tr(SIMU_STR_HLP_ACT_ROT_RGT));
m_scrollUpAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Left, SIMU_STR_HLP_KEYS_GO_LFT, SIMU_STR_HLP_ACT_ROT_LFT);
m_scrollDnAction = new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Right, SIMU_STR_HLP_KEYS_GO_RGT, SIMU_STR_HLP_ACT_ROT_RGT);
connectScrollActions();
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, tr(SIMU_STR_HLP_KEYS_ACTIVATE), tr(SIMU_STR_HLP_ACT_ROT_DN));
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
addRadioWidget(ui->rightbuttons->addArea(polyArc(88, 92, 33), "X7/right_ent.png", m_mouseMidClickAction));
addRadioWidget(ui->leftbuttons->addArea(QRect(9, 154, 30, 30), "X7/left_scrnshot.png", m_screenshotAction));
@@ -37,21 +37,21 @@ SimulatedUIWidgetX9::SimulatedUIWidgetX9(SimulatorInterface *simulator, QWidget
// left side
act = new RadioUiAction(0, QList<int>() << Qt::Key_Up << Qt::Key_PageUp, tr(SIMU_STR_HLP_KEYS_GO_UP), tr(SIMU_STR_HLP_ACT_MENU));
act = new RadioUiAction(0, QList<int>() << Qt::Key_Up << Qt::Key_PageUp, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU);
addRadioWidget(ui->leftbuttons->addArea(btn, "Taranis/x9l1.png", act));
btn.moveTop(btn.top() + btn.height() + vsp);
act = new RadioUiAction(3, QList<int>() << Qt::Key_Down << Qt::Key_PageDown, tr(SIMU_STR_HLP_KEYS_GO_DN), tr(SIMU_STR_HLP_ACT_PAGE));
act = new RadioUiAction(3, QList<int>() << Qt::Key_Down << Qt::Key_PageDown, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE);
addRadioWidget(ui->leftbuttons->addArea(btn, "Taranis/x9l2.png", act));
btn.moveTop(btn.top() + btn.height() + vsp);
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr(SIMU_STR_HLP_KEYS_EXIT), tr(SIMU_STR_HLP_ACT_EXIT));
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
addRadioWidget(ui->leftbuttons->addArea(btn, "Taranis/x9l3.png", act));
m_scrollUpAction = new RadioUiAction(4, QList<int>() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Left,
tr(SIMU_STR_HLP_KEY_LFT "|" SIMU_STR_HLP_KEY_PLS "|" SIMU_STR_HLP_MOUSE_UP), tr(SIMU_STR_HLP_ACT_PLS));
SIMU_STR_HLP_KEY_LFT % "|" % SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_PLS);
m_scrollDnAction = new RadioUiAction(5, QList<int>() << Qt::Key_Minus << Qt::Key_Right,
tr(SIMU_STR_HLP_KEY_RGT "|" SIMU_STR_HLP_KEY_MIN "|" SIMU_STR_HLP_MOUSE_DN), tr(SIMU_STR_HLP_ACT_MIN));
SIMU_STR_HLP_KEY_RGT % "|" % SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_MIN);
// right side
btn.moveTopLeft(QPoint(58, btop));
@@ -62,7 +62,7 @@ SimulatedUIWidgetX9::SimulatedUIWidgetX9(SimulatorInterface *simulator, QWidget
addRadioWidget(ui->rightbuttons->addArea(btn, "Taranis/x9r2.png", m_scrollDnAction));
btn.moveTop(btn.top() + btn.height() + vsp);
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, tr(SIMU_STR_HLP_KEYS_ACTIVATE), tr(SIMU_STR_HLP_ACT_ENT));
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ENT);
addRadioWidget(ui->rightbuttons->addArea(btn, "Taranis/x9r3.png", m_mouseMidClickAction));
addRadioWidget(ui->leftbuttons->addArea(QRect(89, 177, 30, 20), "Taranis/x9l4.png", m_screenshotAction));
@@ -35,24 +35,24 @@ SimulatedUIWidgetX9E::SimulatedUIWidgetX9E(SimulatorInterface *simulator, QWidge
QPoint ctr(70, 100);
polygon << polyArc(ctr.x(), ctr.y(), 60, -90, 0) << ctr;
act = new RadioUiAction(0, QList<int>() << Qt::Key_Up << Qt::Key_PageUp, tr(SIMU_STR_HLP_KEYS_GO_UP), tr(SIMU_STR_HLP_ACT_MENU));
act = new RadioUiAction(0, QList<int>() << Qt::Key_Up << Qt::Key_PageUp, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU);
addRadioWidget(ui->leftbuttons->addArea(polygon, "X9E/left_menu.png", act));
polygon.clear();
polygon << polyArc(ctr.x(), ctr.y(), 45, 0, 180);
act = new RadioUiAction(3, QList<int>() << Qt::Key_Down << Qt::Key_PageDown, tr(SIMU_STR_HLP_KEYS_GO_DN), tr(SIMU_STR_HLP_ACT_PAGE));
act = new RadioUiAction(3, QList<int>() << Qt::Key_Down << Qt::Key_PageDown, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE);
addRadioWidget(ui->leftbuttons->addArea(polygon, "X9E/left_page.png", act));
polygon.clear();
polygon << polyArc(ctr.x(), ctr.y(), 60, 180, 270) << ctr;
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, tr(SIMU_STR_HLP_KEYS_EXIT), tr(SIMU_STR_HLP_ACT_EXIT));
act = new RadioUiAction(1, QList<int>() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
addRadioWidget(ui->leftbuttons->addArea(polygon, "X9E/left_exit.png", act));
m_scrollUpAction = addRadioAction(new RadioUiAction(-1, QList<int>() << Qt::Key_Minus << Qt::Key_Left, tr(SIMU_STR_HLP_KEYS_GO_LFT), tr(SIMU_STR_HLP_ACT_ROT_LFT)));
m_scrollDnAction = addRadioAction(new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Right, tr(SIMU_STR_HLP_KEYS_GO_RGT), tr(SIMU_STR_HLP_ACT_ROT_RGT)));
m_scrollUpAction = addRadioAction(new RadioUiAction(-1, QList<int>() << Qt::Key_Minus << Qt::Key_Left, SIMU_STR_HLP_KEYS_GO_LFT, SIMU_STR_HLP_ACT_ROT_LFT));
m_scrollDnAction = addRadioAction(new RadioUiAction(-1, QList<int>() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Right, SIMU_STR_HLP_KEYS_GO_RGT, SIMU_STR_HLP_ACT_ROT_RGT));
connectScrollActions();
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, tr(SIMU_STR_HLP_KEYS_ACTIVATE), tr(SIMU_STR_HLP_ACT_ROT_DN));
m_mouseMidClickAction = new RadioUiAction(2, QList<int>() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
addRadioWidget(ui->rightbuttons->addArea(polyArc(90, 100, 50), "X9E/right_enter.png", m_mouseMidClickAction));
addRadioWidget(ui->leftbuttons->addArea(QRect(10, 170, 30, 30), "X9E/left_scrnshot.png", m_screenshotAction));
+52 -52
View File
@@ -1,66 +1,66 @@
#ifndef SIMULATOR_STRINGS_H
#define SIMULATOR_STRINGS_H
#include <QtGlobal>
#include <QCoreApplication>
#define SIMU_STR_HLP_KEY_ENTER QT_TRANSLATE_NOOP("SimulatedUIWidget", "ENTER")
#define SIMU_STR_HLP_KEY_PGUP QT_TRANSLATE_NOOP("SimulatedUIWidget", "PG-UP")
#define SIMU_STR_HLP_KEY_PGDN QT_TRANSLATE_NOOP("SimulatedUIWidget", "PG-DN")
#define SIMU_STR_HLP_KEY_DEL QT_TRANSLATE_NOOP("SimulatedUIWidget", "DEL")
#define SIMU_STR_HLP_KEY_BKSP QT_TRANSLATE_NOOP("SimulatedUIWidget", "BKSP")
#define SIMU_STR_HLP_KEY_ESC QT_TRANSLATE_NOOP("SimulatedUIWidget", "ESC")
#define SIMU_STR_HLP_KEY_INS QT_TRANSLATE_NOOP("SimulatedUIWidget", "INS")
#define SIMU_STR_HLP_KEY_PLS QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>+</font>")
#define SIMU_STR_HLP_KEY_MIN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>-</font>")
#define SIMU_STR_HLP_KEY_ENTER QCoreApplication::translate("SimulatedUIWidget", "ENTER")
#define SIMU_STR_HLP_KEY_PGUP QCoreApplication::translate("SimulatedUIWidget", "PG-UP")
#define SIMU_STR_HLP_KEY_PGDN QCoreApplication::translate("SimulatedUIWidget", "PG-DN")
#define SIMU_STR_HLP_KEY_DEL QCoreApplication::translate("SimulatedUIWidget", "DEL")
#define SIMU_STR_HLP_KEY_BKSP QCoreApplication::translate("SimulatedUIWidget", "BKSP")
#define SIMU_STR_HLP_KEY_ESC QCoreApplication::translate("SimulatedUIWidget", "ESC")
#define SIMU_STR_HLP_KEY_INS QCoreApplication::translate("SimulatedUIWidget", "INS")
#define SIMU_STR_HLP_KEY_PLS QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>+</font>")
#define SIMU_STR_HLP_KEY_MIN QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>-</font>")
#define SIMU_STR_HLP_KEY_LFT QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&larr;</font>") // ←
#define SIMU_STR_HLP_KEY_RGT QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&rarr;</font>") // →
#define SIMU_STR_HLP_KEY_UP QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&uarr;</font>") // ↑
#define SIMU_STR_HLP_KEY_DN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&darr;</font>") // ↓
#define SIMU_STR_HLP_KEY_LFT QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&larr;</font>") // ←
#define SIMU_STR_HLP_KEY_RGT QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&rarr;</font>") // →
#define SIMU_STR_HLP_KEY_UP QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&uarr;</font>") // ↑
#define SIMU_STR_HLP_KEY_DN QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&darr;</font>") // ↓
#define SIMU_STR_HLP_ROTENC QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x2686;</font>") // ⚆
#define SIMU_STR_HLP_ROTENC_LFT QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x21b6;</font>") // ↶
#define SIMU_STR_HLP_ROTENC_RGT QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x21b7;</font>") // ↷
#define SIMU_STR_HLP_ROTENC_LR QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x21c6;</font>") // ⇆
#define SIMU_STR_HLP_ROTENC_DN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x21d3;</font>") // ⇓
#define SIMU_STR_HLP_ROTENC QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x2686;</font>") // ⚆
#define SIMU_STR_HLP_ROTENC_LFT QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x21b6;</font>") // ↶
#define SIMU_STR_HLP_ROTENC_RGT QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x21b7;</font>") // ↷
#define SIMU_STR_HLP_ROTENC_LR QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x21c6;</font>") // ⇆
#define SIMU_STR_HLP_ROTENC_DN QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x21d3;</font>") // ⇓
#define SIMU_STR_HLP_SCRL_UP QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x21d1;</font>") // ⇑
#define SIMU_STR_HLP_SCRL_DN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x21d3;</font>") // ⇓
#define SIMU_STR_HLP_SCRL_UD QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x21d5;</font>") // ⇕
#define SIMU_STR_HLP_SCRL_UP QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x21d1;</font>") // ⇑
#define SIMU_STR_HLP_SCRL_DN QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x21d3;</font>") // ⇓
#define SIMU_STR_HLP_SCRL_UD QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x21d5;</font>") // ⇕
#define SIMU_STR_HLP_MOUSE QT_TRANSLATE_NOOP("SimulatedUIWidget", "<img src='qrc:/images/simulator/icons/svg/mouse.svg' width=20 height=18 />")
#define SIMU_STR_HLP_CLICK QT_TRANSLATE_NOOP("SimulatedUIWidget", "<img src='qrc:/images/simulator/icons/svg/arrow_click.svg' width=18 height=18 />")
#define SIMU_STR_HLP_MOUSE_MID SIMU_STR_HLP_MOUSE SIMU_STR_HLP_CLICK
#define SIMU_STR_HLP_MOUSE_UP SIMU_STR_HLP_MOUSE SIMU_STR_HLP_SCRL_UP
#define SIMU_STR_HLP_MOUSE_DN SIMU_STR_HLP_MOUSE SIMU_STR_HLP_SCRL_DN
#define SIMU_STR_HLP_MOUSE_SCRL SIMU_STR_HLP_MOUSE SIMU_STR_HLP_SCRL_UD
#define SIMU_STR_HLP_MOUSE QCoreApplication::translate("SimulatedUIWidget", "<img src='qrc:/images/simulator/icons/svg/mouse.svg' width=20 height=18 />")
#define SIMU_STR_HLP_CLICK QCoreApplication::translate("SimulatedUIWidget", "<img src='qrc:/images/simulator/icons/svg/arrow_click.svg' width=18 height=18 />")
#define SIMU_STR_HLP_MOUSE_MID SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_CLICK
#define SIMU_STR_HLP_MOUSE_UP SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_SCRL_UP
#define SIMU_STR_HLP_MOUSE_DN SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_SCRL_DN
#define SIMU_STR_HLP_MOUSE_SCRL SIMU_STR_HLP_MOUSE % SIMU_STR_HLP_SCRL_UD
#define SIMU_STR_HLP_ACT_MENU QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ MENU ]</pre>")
#define SIMU_STR_HLP_ACT_PAGE QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ PAGE ]</pre>")
#define SIMU_STR_HLP_ACT_EXIT QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ EXIT ]</pre>")
#define SIMU_STR_HLP_ACT_ENT QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ ENT ]</pre>")
#define SIMU_STR_HLP_ACT_UP QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ UP ]</pre>")
#define SIMU_STR_HLP_ACT_DN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ DN ]</pre>")
#define SIMU_STR_HLP_ACT_PLS QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ <font size=+2>+</font> ]</pre>")
#define SIMU_STR_HLP_ACT_MIN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ <font size=+2>-</font> ]</pre>")
#define SIMU_STR_HLP_ACT_PGUP QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ PgUp ]</pre>")
#define SIMU_STR_HLP_ACT_PGDN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ PgDn ]</pre>")
#define SIMU_STR_HLP_ACT_MDL QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ MDL ]</pre>")
#define SIMU_STR_HLP_ACT_RTN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ RTN ]</pre>")
#define SIMU_STR_HLP_ACT_SYS QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ SYS ]</pre>")
#define SIMU_STR_HLP_ACT_TELE QT_TRANSLATE_NOOP("SimulatedUIWidget", "<pre>[ TELE ]</pre>")
#define SIMU_STR_HLP_ACT_MENU_ICN QT_TRANSLATE_NOOP("SimulatedUIWidget", "<font size=+3>&#x2261;</font>") // ≡
#define SIMU_STR_HLP_ACT_MENU QCoreApplication::translate("SimulatedUIWidget", "<pre>[ MENU ]</pre>")
#define SIMU_STR_HLP_ACT_PAGE QCoreApplication::translate("SimulatedUIWidget", "<pre>[ PAGE ]</pre>")
#define SIMU_STR_HLP_ACT_EXIT QCoreApplication::translate("SimulatedUIWidget", "<pre>[ EXIT ]</pre>")
#define SIMU_STR_HLP_ACT_ENT QCoreApplication::translate("SimulatedUIWidget", "<pre>[ ENT ]</pre>")
#define SIMU_STR_HLP_ACT_UP QCoreApplication::translate("SimulatedUIWidget", "<pre>[ UP ]</pre>")
#define SIMU_STR_HLP_ACT_DN QCoreApplication::translate("SimulatedUIWidget", "<pre>[ DN ]</pre>")
#define SIMU_STR_HLP_ACT_PLS QCoreApplication::translate("SimulatedUIWidget", "<pre>[ <font size=+2>+</font> ]</pre>")
#define SIMU_STR_HLP_ACT_MIN QCoreApplication::translate("SimulatedUIWidget", "<pre>[ <font size=+2>-</font> ]</pre>")
#define SIMU_STR_HLP_ACT_PGUP QCoreApplication::translate("SimulatedUIWidget", "<pre>[ PgUp ]</pre>")
#define SIMU_STR_HLP_ACT_PGDN QCoreApplication::translate("SimulatedUIWidget", "<pre>[ PgDn ]</pre>")
#define SIMU_STR_HLP_ACT_MDL QCoreApplication::translate("SimulatedUIWidget", "<pre>[ MDL ]</pre>")
#define SIMU_STR_HLP_ACT_RTN QCoreApplication::translate("SimulatedUIWidget", "<pre>[ RTN ]</pre>")
#define SIMU_STR_HLP_ACT_SYS QCoreApplication::translate("SimulatedUIWidget", "<pre>[ SYS ]</pre>")
#define SIMU_STR_HLP_ACT_TELE QCoreApplication::translate("SimulatedUIWidget", "<pre>[ TELE ]</pre>")
#define SIMU_STR_HLP_ACT_MENU_ICN QCoreApplication::translate("SimulatedUIWidget", "<font size=+3>&#x2261;</font>") // ≡
#define SIMU_STR_HLP_KEYS_EXIT SIMU_STR_HLP_KEY_DEL "|" SIMU_STR_HLP_KEY_BKSP "|" SIMU_STR_HLP_KEY_ESC
#define SIMU_STR_HLP_KEYS_ACTIVATE SIMU_STR_HLP_KEY_ENTER "|" SIMU_STR_HLP_MOUSE_MID
#define SIMU_STR_HLP_KEYS_GO_UP SIMU_STR_HLP_KEY_UP "|" SIMU_STR_HLP_KEY_PGUP
#define SIMU_STR_HLP_KEYS_GO_DN SIMU_STR_HLP_KEY_DN "|" SIMU_STR_HLP_KEY_PGDN
#define SIMU_STR_HLP_KEYS_GO_LFT SIMU_STR_HLP_KEY_LFT "|" SIMU_STR_HLP_KEY_MIN "|" SIMU_STR_HLP_MOUSE_UP
#define SIMU_STR_HLP_KEYS_GO_RGT SIMU_STR_HLP_KEY_RGT "|" SIMU_STR_HLP_KEY_PLS "|" SIMU_STR_HLP_MOUSE_DN
#define SIMU_STR_HLP_KEYS_EXIT SIMU_STR_HLP_KEY_DEL % "|" % SIMU_STR_HLP_KEY_BKSP % "|" % SIMU_STR_HLP_KEY_ESC
#define SIMU_STR_HLP_KEYS_ACTIVATE SIMU_STR_HLP_KEY_ENTER % "|" % SIMU_STR_HLP_MOUSE_MID
#define SIMU_STR_HLP_KEYS_GO_UP SIMU_STR_HLP_KEY_UP % "|" % SIMU_STR_HLP_KEY_PGUP
#define SIMU_STR_HLP_KEYS_GO_DN SIMU_STR_HLP_KEY_DN % "|" % SIMU_STR_HLP_KEY_PGDN
#define SIMU_STR_HLP_KEYS_GO_LFT SIMU_STR_HLP_KEY_LFT % "|" % SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP
#define SIMU_STR_HLP_KEYS_GO_RGT SIMU_STR_HLP_KEY_RGT % "|" % SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN
#define SIMU_STR_HLP_ACT_ROT_LFT SIMU_STR_HLP_ROTENC " " SIMU_STR_HLP_ROTENC_LFT
#define SIMU_STR_HLP_ACT_ROT_RGT SIMU_STR_HLP_ROTENC " " SIMU_STR_HLP_ROTENC_RGT
#define SIMU_STR_HLP_ACT_ROT_DN SIMU_STR_HLP_ROTENC " " SIMU_STR_HLP_ROTENC_DN
#define SIMU_STR_HLP_ACT_ROT_LFT SIMU_STR_HLP_ROTENC % " " % SIMU_STR_HLP_ROTENC_LFT
#define SIMU_STR_HLP_ACT_ROT_RGT SIMU_STR_HLP_ROTENC % " " % SIMU_STR_HLP_ROTENC_RGT
#define SIMU_STR_HLP_ACT_ROT_DN SIMU_STR_HLP_ROTENC % " " % SIMU_STR_HLP_ROTENC_DN
#endif // SIMULATOR_STRINGS_H
@@ -227,7 +227,7 @@ void SimulatorStartupDialog::onRadioTypeChanged(int index)
void SimulatorStartupDialog::onDataFileSelect(bool)
{
QString filter = tr(EEPROM_FILES_FILTER) + tr("All files (*.*)");
QString filter = EEPROM_FILES_FILTER % tr("All files (*.*)");
QString file = QFileDialog::getSaveFileName(this, QObject::tr("Select a data file"), ui->dataFile->text(),
filter, NULL, QFileDialog::DontConfirmOverwrite);
if (!file.isEmpty()) {
+1 -1
View File
@@ -528,7 +528,7 @@ Timestamp</string>
</font>
</property>
<property name="text">
<string>SWR</string>
<string>RAS</string>
</property>
</widget>
</item>
+195 -77
View File
@@ -19,6 +19,7 @@
*/
#include <QApplication>
#include <QCommandLineParser>
#include <QMessageBox>
#include <QString>
#include <QTextStream>
@@ -36,7 +37,6 @@
#include "simulatormainwindow.h"
#include "simulatorstartupdialog.h"
#include "storage.h"
#include "qxtcommandoptions.h"
#include "translations.h"
#include "version.h"
@@ -44,28 +44,188 @@ using namespace Simulator;
int finish(int exitCode);
void showMessage(const QString & message, enum QMessageBox::Icon icon = QMessageBox::NoIcon)
void showMessage(const QString & message, enum QMessageBox::Icon icon = QMessageBox::NoIcon, bool useConsole = false)
{
if (useConsole) {
if (icon < QMessageBox::Warning)
QTextStream(stdout) << message << endl;
else
QTextStream(stderr) << message << endl;
return;
}
// use GUI
QMessageBox msgBox;
msgBox.setText(message);
QString escMsg(message);
escMsg.replace("<", "&lt;");
msgBox.setText("<html><body><pre>" + escMsg + "</pre></body></html>");
msgBox.setIcon(icon);
msgBox.exec();
}
void sharedHelpText(QTextStream &stream)
const QString sharedHelpText()
{
QString ret;
QTextStream stream(&ret);
// list all available profiles
stream << endl << QObject::tr("Available profiles:") << endl;
stream << endl << QApplication::translate("SimulatorMain", "Available profiles:") << endl;
QMapIterator<int, QString> pi(g.getActiveProfiles());
while (pi.hasNext()) {
pi.next();
stream << "\t" << QObject::tr("ID: ") << pi.key() << QObject::tr(" Name: ") << pi.value() << endl;
stream << "\t" << QApplication::translate("SimulatorMain", "ID: ") << pi.key() << "; " << QApplication::translate("SimulatorMain", "Name: ") << pi.value() << endl;
}
// list all available radios
stream << endl << QObject::tr("Available radios:") << endl;
stream << endl << QApplication::translate("SimulatorMain", "Available radios:") << endl;
foreach(QString name, SimulatorLoader::getAvailableSimulators()) {
stream << "\t" << name << endl;
}
return ret;
}
void showHelp(QCommandLineParser & parser, const QString & addMsg = QString(), int exitCode = 0) {
QString msg = "\n";
if (!addMsg.isEmpty())
msg.append(addMsg).append("\n\n");
msg.append(parser.helpText());
msg.append(sharedHelpText());
// display
showMessage(msg, (exitCode ? QMessageBox::Warning : QMessageBox::Information));
}
enum CommandLineParseResult
{
CommandLineNone,
CommandLineFound,
CommandLineExitOk,
CommandLineExitErr
};
CommandLineParseResult cliOptions(SimulatorOptions * simOptions, int * profileId)
{
QCommandLineParser cliOptions;
bool cliOptsFound = false;
int pId = *profileId;
const QCommandLineOption optHelp = cliOptions.addHelpOption();
const QCommandLineOption optVer = cliOptions.addVersionOption();
const QCommandLineOption optProfi(QStringList() << "profile" << "p",
QApplication::translate("SimulatorMain", "Radio profile ID or Name to use for simulator."),
QApplication::translate("SimulatorMain", "profile"));
const QCommandLineOption optRadio(QStringList() << "radio" << "r",
QApplication::translate("SimulatorMain", "Radio type to simulate (usually defined in profile)."),
QApplication::translate("SimulatorMain", "radio"));
const QCommandLineOption optSdDir(QStringList() << "sd-path" << "s",
QApplication::translate("SimulatorMain", "Directory containing the SD card image to use. The default is configured in the chosen Radio Profile."),
QApplication::translate("SimulatorMain", "path"));
const QCommandLineOption optStart(QStringList() << "start-with" << "w",
QApplication::translate("SimulatorMain", "Data source type to use (applicable to Horus only). One of:") + " (file|folder|sd)",
QApplication::translate("SimulatorMain", "type"));
cliOptions.addPositionalArgument(QApplication::translate("SimulatorMain", "data-source"),
QApplication::translate("SimulatorMain", "Radio data (.bin/.eeprom/.otx) image file to use OR data folder path (for Horus-style radios).\n"
"NOTE: any existing EEPROM data incompatible with the selected radio type may be overwritten!"),
QApplication::translate("SimulatorMain", "[data-source]"));
cliOptions.addOption(optProfi);
cliOptions.addOption(optRadio);
cliOptions.addOption(optSdDir);
cliOptions.addOption(optStart);
QStringList args = QCoreApplication::arguments();
#ifdef Q_OS_WIN
// For backwards compat. with QxtCommandOptions, convert Windows-style CLI switches (/opt) since QCommandLineParser doesn't support them
for (int i=0; i < args.size(); ++i) {
args[i].replace(QRegExp("^/([^\\s]{2,10})$"), "--\\1"); // long opts
args[i].replace(QRegExp("^/([^\\s]){1}$"), "-\\1"); // short opts
}
#endif
if (!cliOptions.parse(args)) {
showHelp(cliOptions, cliOptions.errorText());
return CommandLineExitErr;
}
if (cliOptions.isSet(optHelp)) {
showHelp(cliOptions);
return CommandLineExitOk;
}
if (cliOptions.isSet(optVer)) {
showMessage(APP_SIMULATOR " v" VERSION " " __DATE__, QMessageBox::Information);
return CommandLineExitOk;
}
if (cliOptions.isSet(optProfi)) {
bool chk;
pId = cliOptions.value(optProfi).toInt(&chk);
if (!chk)
pId = g.getActiveProfiles().key(cliOptions.value(optProfi), -1);
if (!g.getActiveProfiles().contains(pId)) {
showHelp(cliOptions, QApplication::translate("SimulatorMain", "Error: Profile ID %1 was not found.").arg(pId));
return CommandLineExitErr;
}
*simOptions = g.profile[pId].simulatorOptions();
cliOptsFound = true;
}
if (cliOptions.isSet(optRadio)) {
simOptions->firmwareId = cliOptions.value(optRadio);
cliOptsFound = true;
}
if (cliOptsFound || (simOptions->dataFile.isEmpty() && !simOptions->firmwareId.isEmpty())) {
// this constructs a new default radio data file name in the user-configured eeprom directory
simOptions->dataFile = SimulatorStartupDialog::radioEepromFileName(simOptions->firmwareId, g.eepromDir());
}
if (cliOptions.isSet(optSdDir)) {
simOptions->sdPath = cliOptions.value(optSdDir);
cliOptsFound = true;
}
if (cliOptions.positionalArguments().size()) {
QString datasrc = cliOptions.positionalArguments().at(0);
if (datasrc.contains(QRegExp(".*\\.[\\w]{2,6}$"))) {
simOptions->dataFile = datasrc;
simOptions->startupDataType = SimulatorOptions::START_WITH_FILE;
}
else {
simOptions->dataFolder = datasrc;
simOptions->startupDataType = SimulatorOptions::START_WITH_FOLDER;
}
cliOptsFound = true;
}
if (cliOptions.isSet(optStart)) {
QString stTyp = cliOptions.value(optStart);
if (stTyp == "file") {
simOptions->startupDataType = SimulatorOptions::START_WITH_FILE;
}
else if (stTyp == "folder") {
simOptions->startupDataType = SimulatorOptions::START_WITH_FOLDER;
}
else if (stTyp == "sd") {
simOptions->startupDataType = SimulatorOptions::START_WITH_SDPATH;
}
else {
showHelp(cliOptions, QApplication::translate("SimulatorMain", "Unrecognized startup data source type: %1").arg(stTyp));
return CommandLineExitErr;
}
cliOptsFound = true;
}
*profileId = pId;
if (cliOptsFound)
return CommandLineFound;
else
return CommandLineNone;
}
int main(int argc, char *argv[])
@@ -78,6 +238,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
app.setApplicationName(APP_SIMULATOR);
app.setApplicationVersion(VERSION);
app.setOrganizationName(COMPANY);
app.setOrganizationDomain(COMPANY_DOMAIN);
@@ -88,9 +249,7 @@ int main(int argc, char *argv[])
CustomDebug::setFilterRules();
g.init();
QString resultMsg;
g.init(); // init settings before installing translations
Translations::installTranslators();
@@ -103,41 +262,21 @@ int main(int argc, char *argv[])
sdlFlags |= SDL_INIT_AUDIO;
#endif
if (SDL_Init(sdlFlags) < 0) {
showMessage(QObject::tr("WARNING: couldn't initialize SDL:\n%1").arg(SDL_GetError()), QMessageBox::Warning);
showMessage(QApplication::translate("SimulatorMain", "WARNING: couldn't initialize SDL:\n%1").arg(SDL_GetError()), QMessageBox::Warning);
}
#endif
QxtCommandOptions cliOptions;
bool cliOptsFound = false;
int profileId = (g.simuLastProfId() > -1 ? g.simuLastProfId() : g.id());
SimulatorOptions simOptions = g.profile[profileId].simulatorOptions();
registerStorageFactories();
registerOpenTxFirmwares();
SimulatorLoader::registerSimulators();
if (!SimulatorLoader::getAvailableSimulators().size()) {
showMessage(QObject::tr("ERROR: No simulator libraries available."), QMessageBox::Critical);
showMessage(QApplication::translate("SimulatorMain", "ERROR: No simulator libraries available."), QMessageBox::Critical);
return finish(3);
}
cliOptions.add("profile", QObject::tr("Radio profile ID or Name to use for simulator."), QxtCommandOptions::ValueRequired);
cliOptions.alias("profile", "p");
cliOptions.add("radio", QObject::tr("Radio type to simulate (usually defined in profile)."), QxtCommandOptions::ValueRequired);
cliOptions.alias("radio", "r");
cliOptions.add("help", QObject::tr("show this help text"));
cliOptions.alias("help", "h");
cliOptions.parse(QCoreApplication::arguments());
if (cliOptions.count("help") || cliOptions.showUnrecognizedWarning()) {
QTextStream stream(&resultMsg);
stream << QObject::tr("Usage: simulator [OPTION]... [EEPROM.BIN FILE OR DATA FOLDER] ") << endl << endl;
stream << QObject::tr("Options:") << endl;
cliOptions.showUsage(false, stream);
sharedHelpText(stream);
// display
showMessage(resultMsg, QMessageBox::Information);
return finish(1);
}
int profileId = (g.simuLastProfId() > -1 ? g.simuLastProfId() : g.id());
SimulatorOptions simOptions = g.profile[profileId].simulatorOptions();
// TODO : defaults should be set in Profile::init()
if (simOptions.firmwareId.isEmpty())
@@ -147,44 +286,18 @@ int main(int argc, char *argv[])
if (simOptions.sdPath.isEmpty())
simOptions.sdPath = g.profile[profileId].sdPath();
if (cliOptions.count("profile") == 1) {
bool chk;
int pid = cliOptions.value("profile").toInt(&chk);
if (chk)
profileId = pid;
else
profileId = g.getActiveProfiles().key(cliOptions.value("profile").toString(), -1);
// Handle startup options
if (!g.getActiveProfiles().contains(profileId)) {
fprintf(stderr, "Error: Profile ID %d was not found.", profileId);
return finish(1);
}
// check for command-line options
CommandLineParseResult cliResult = cliOptions(&simOptions, &profileId);
simOptions = g.profile[profileId].simulatorOptions();
cliOptsFound = true;
}
if (cliResult == CommandLineExitOk)
return finish(0);
if (cliResult == CommandLineExitErr)
return finish(1);
if (cliOptions.count("radio") == 1) {
simOptions.firmwareId = cliOptions.value("radio").toString();
cliOptsFound = true;
}
if (cliOptsFound || (simOptions.dataFile.isEmpty() && !simOptions.firmwareId.isEmpty()))
simOptions.dataFile = SimulatorStartupDialog::radioEepromFileName(simOptions.firmwareId, g.eepromDir());
if (!cliOptions.positional().isEmpty()) {
if (QString(cliOptions.positional().at(0)).contains(QRegExp(".*\\.[\\w]{2,6}$"))) {
simOptions.dataFile = cliOptions.positional()[0];
simOptions.startupDataType = SimulatorOptions::START_WITH_FILE;
}
else {
simOptions.dataFolder = cliOptions.positional()[0];
simOptions.startupDataType = SimulatorOptions::START_WITH_FOLDER;
}
cliOptsFound = true;
}
if (!cliOptsFound || profileId == -1 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
// Present GUI startup options dialog if necessary
if (cliResult == CommandLineNone || profileId == -1 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
SimulatorStartupDialog * dlg = new SimulatorStartupDialog(&simOptions, &profileId);
int ret = dlg->exec();
delete dlg;
@@ -192,32 +305,37 @@ int main(int argc, char *argv[])
return finish(0);
}
}
qDebug() << "profileId=" << profileId << simOptions;
qDebug() << "Starting with options: profileId=" << profileId << simOptions;
// Validate startup options
QString resultMsg;
if (profileId < 0 || simOptions.firmwareId.isEmpty() || (simOptions.dataFile.isEmpty() && simOptions.dataFolder.isEmpty())) {
resultMsg = QObject::tr("ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\n Profile ID: [%1]; Radio ID: [%2];\nData File: [%3]");
resultMsg = QApplication::translate("SimulatorMain", "ERROR: Couldn't start simulator, missing radio/profile/data file/folder.\n Profile ID: [%1]; Radio ID: [%2];\nData File: [%3]");
showMessage(resultMsg.arg(profileId).arg(simOptions.firmwareId, simOptions.dataFile), QMessageBox::Critical);
return finish(1);
}
if (!g.getActiveProfiles().contains(profileId) || !SimulatorLoader::getAvailableSimulators().contains(simOptions.firmwareId)) {
QTextStream stream(&resultMsg);
stream << QObject::tr("ERROR: Radio profile or simulator firmware not found.\nProfile ID: [%1]; Radio ID: [%2]")
.arg(profileId).arg(simOptions.firmwareId);
sharedHelpText(stream);
stream << QApplication::translate("SimulatorMain", "ERROR: Radio profile or simulator firmware not found.\nProfile ID: [%1]; Radio ID: [%2]").arg(profileId).arg(simOptions.firmwareId);
stream << sharedHelpText();
showMessage(resultMsg, QMessageBox::Critical);
return finish(2);
return finish(1);
}
Firmware::setCurrentVariant(Firmware::getFirmwareForId(simOptions.firmwareId));
// All checks passed, save profile ID and start simulator
g.sessionId(profileId);
g.simuLastProfId(profileId);
// Set global firmware environment
Firmware::setCurrentVariant(Firmware::getFirmwareForId(simOptions.firmwareId));
int result = 0;
SimulatorMainWindow * mainWindow = new SimulatorMainWindow(NULL, simOptions.firmwareId, SIMULATOR_FLAGS_STANDALONE);
if ((result = mainWindow->getExitStatus(&resultMsg))) {
if (resultMsg.isEmpty())
resultMsg = QObject::tr("Uknown error during Simulator startup.");
resultMsg = QApplication::translate("SimulatorMain", "Uknown error during Simulator startup.");
showMessage(resultMsg, QMessageBox::Critical);
}
else if (mainWindow->setOptions(simOptions, true)) {
+71 -29
View File
@@ -557,9 +557,15 @@ void AppData::init()
{
qRegisterMetaTypeStreamOperators<SimulatorOptions>("SimulatorOptions");
firstUse = false;
upgradeFromVersion = "";
QSettings settings(COMPANY, PRODUCT);
if (!settings.contains("settings_version"))
importSettings(settings);
if (!settings.contains("settings_version")) {
if (!importSettings(settings))
firstUse = true;
}
convertSettings(settings);
// Initialize the profiles
for (int i=0; i<MAX_PROFILES; i++)
@@ -649,23 +655,69 @@ QMap<int, QString> AppData::getActiveProfiles()
return active;
}
void AppData::convertSettings(QSettings & settings)
{
// convert old settings to new
if (settings.contains("useWizard")) {
if (!settings.contains("newModelAction")) {
newModelAction(settings.value("useWizard").toBool() ? 1 : 2);
}
settings.remove("useWizard");
}
if (settings.contains("warningId") && settings.value("warningId").toInt() == 7) {
// meaning of warningId changed during v2.2 development but value of "7" indicates old setting, removing it will restore defaults
settings.remove("warningId");
}
}
bool AppData::importSettings(QSettings & toSettings)
{
QSettings * fromSettings = NULL;
QSettings settings21("OpenTX", "Companion 2.1");
QSettings settings20("OpenTX", "Companion 2.0");
QSettings settings16("OpenTX", "OpenTX Companion");
QSettings settings9x("companion9x", "companion9x");
if (settings21.contains("settings_version"))
if (settings21.contains("settings_version")) {
fromSettings = &settings21;
else if (settings20.contains("settings_version"))
fromSettings = &settings20;
else if (settings16.contains("settings_version"))
fromSettings = &settings16;
else if (settings9x.contains("default_mode"))
fromSettings = &settings9x;
upgradeFromVersion = "2.1";
}
else {
settings21.clear();
}
if (!fromSettings) {
QSettings settings20("OpenTX", "Companion 2.0");
if (settings20.contains("settings_version")) {
fromSettings = &settings20;
upgradeFromVersion = "2.0";
}
else {
settings20.clear();
}
}
if (!fromSettings) {
QSettings settings16("OpenTX", "OpenTX Companion");
if (settings16.contains("settings_version")) {
fromSettings = &settings16;
upgradeFromVersion = "1.x";
}
else {
settings16.clear();
}
}
if (!fromSettings) {
QSettings settings9x("companion9x", "companion9x");
if (settings9x.contains("default_mode")) {
fromSettings = &settings9x;
upgradeFromVersion = "Companion9X";
}
else {
settings9x.clear();
}
}
if (!fromSettings)
return false;
// do not copy these settings
QStringList excludeKeys = QStringList() << "compilation-server";
@@ -677,16 +729,14 @@ bool AppData::importSettings(QSettings & toSettings)
#endif
// import settings
if (fromSettings) {
foreach (const QString & key, fromSettings->allKeys()) {
if (fromSettings->value(key).isValid() && !excludeKeys.contains(key)) {
toSettings.setValue(key, fromSettings->value(key));
}
foreach (const QString & key, fromSettings->allKeys()) {
if (fromSettings->value(key).isValid() && !excludeKeys.contains(key)) {
toSettings.setValue(key, fromSettings->value(key));
}
}
// Additional adjustments for companion9x settings
if (fromSettings && fromSettings->applicationName() == "companion9x") {
if (fromSettings->applicationName() == "companion9x") {
// Store old values in new locations
autoCheckApp(toSettings.value("startup_check_companion9x", true).toBool());
toSettings.setValue("useWizard", toSettings.value("wizardEnable", true));
@@ -726,20 +776,12 @@ bool AppData::importSettings(QSettings & toSettings)
toSettings.remove("sdPath");
toSettings.remove("SplashFileName");
toSettings.remove("startup_check_companion9x");
toSettings.remove("warningId");
toSettings.remove("wizardEnable");
// Select the new default profile as current profile
id( 0 );
}
// convert old settings to new
if (toSettings.contains("useWizard")) {
if (!toSettings.contains("newModelAction")) {
newModelAction(toSettings.value("useWizard").toBool() ? 1 : 2);
}
toSettings.remove("useWizard");
}
return fromSettings ? true : false;
return true;
}
+5
View File
@@ -429,10 +429,15 @@ class AppData: protected CompStoreObj
void init();
QMap<int, QString> getActiveProfiles();
inline bool isFirstUse() const { return firstUse; }
inline QString previousVersion() const { return upgradeFromVersion; }
protected:
void convertSettings(QSettings & settings);
bool importSettings(QSettings & toSettings);
bool firstUse;
QString upgradeFromVersion;
};
extern AppData g;
+1
View File
@@ -89,6 +89,7 @@ bool CategorizedStorageFormat::load(RadioData & radioData)
radioData.models.resize(modelIndex + 1);
}
if (!loadModelFromByteArray(radioData.models[modelIndex], modelBuffer)) {
setError(QObject::tr("Error loading models"));
return false;
}
strncpy(radioData.models[modelIndex].filename, qPrintable(fileName), sizeof(radioData.models[modelIndex].filename));
+30 -7
View File
@@ -67,15 +67,38 @@ class StorageFormat
return board;
}
static uint32_t getFourCC(Board::Type board)
{
switch (board) {
case Board::BOARD_X12S:
case Board::BOARD_X10:
return 0x3478746F;
case Board::BOARD_TARANIS_X7:
return 0x3678746F;
case Board::BOARD_TARANIS_X9E:
return 0x3578746F;
case Board::BOARD_TARANIS_X9D:
case Board::BOARD_TARANIS_X9DP:
return 0x3378746F;
case Board::BOARD_SKY9X:
case Board::BOARD_AR9X:
return 0x3278746F;
case Board::BOARD_MEGA2560:
case Board::BOARD_GRUVIN9X:
return 0x3178746F;
default:
return 0;
}
}
uint32_t getFourCC()
{
return getFourCC(board);
}
virtual bool isBoardCompatible(Board::Type board)
{
if (this->board == board)
return true;
if (IS_TARANIS_X9D(this->board) && IS_TARANIS_X9D(board))
return true;
return false;
return getFourCC() == getFourCC(board);
}
protected:
-7
View File
@@ -1,7 +0,0 @@
Arvid Picciani <aep@libqxt.org>
Adam Higerd <ahigerd@libqxt.org>
J-P Nurmi <jpnurmi@libqxt.org>
Benjamin Zeller <zbenjamin@libqxt.org>
Thomas Mueller <deepdiver@libqxt.org>
thanks for all the minor contributions, bug reports, beta tests, and the free beer :-)
-230
View File
@@ -1,230 +0,0 @@
LibQxt 0.6.2 contains improvements and bug fixes to the 0.6.x series. For more
details, see the documentation included in this package or online at
http://docs.libqxt.org.
0.6.2
-----
* QxtWindowSystem:
- X11 implementation cleanup/overhaul
- Fixed #85 QxtWindowSystem::windowGeometry issue
* QxtSpanSlider: Improved span drawing on Mac
* QxtGlobalShortcut:
- Fixed #51 QxtGlobalShortcut doesn't send signal
- Fixed #131 QxtGlobalShortcutKey unregistered other's shortcut key by mistake
* QxtZeroconf: Fixed a bug in the custom AvahiPoll introduced by a timestamp wrap-around that accured just last week.
* QxtCrumbView:
- Don't render delegate for invalid indexes
- Remove unnecessary padding
* QxtDataStreamSignalSerializer:
- Handle incomplete length
- Added cast to eliminate a compiler warning
* QxtMailMessage:
- Fix some encoding issues, support explicit transfer encodings
- Handle lines with only one word
* QxtJSON:
- Add support for long long ints
- Handle control characters in QxtJSON::stringify
- Fix \u decoding
- Fixed a error in json parsing code. Nested arrays were incorrectly combined into one big array.
* Build system
- Various enhancements
- Fixed #130 DEPENTPATH = DEPENDPATH?
* QxtLogger: Fixed the incorrect association of log level string names to their enumerations
* QxtAbstractHttpConnector: remove request disconnected on (QHash)"requests"
* QxtWebContent: Fix comparison on size
* QxtLanguageBox:
- Fixed #124 QxtLanguageBox logic maybe bug
- Fixed #125 QxtLanguageBox improvment in logic
0.6.1
-----
- Improvements
* Revised configure.bat:
- added -make-bin option
- removed -msvc from help
- added build_all config for -debug_and_release
- cleaned up possible mkdir/move output
* Added -I, -i and -L options to configure
* Revised QxtConfig.cmake, based on a proposal from zeke (thanks!)
* QxtGlobalShortcut/Mac: removed the extra route via QApplication::macEventFilter() - use qxt_mac_handle_hot_key() directly
* tests/other/app: changed the shortcut to "ctrl+alt+s" (ie. "cmd+alt+s" on mac)
* examples/jsonrpcclient: added CONFIG+=console to make windows users happy
* Configure: added -nomake docs
* Configure: added -no-openssl to -help
* Added MediaKeys to qxtglobalshortcut_win
* Added mod4 support in qxtglobalshortcut_x11
* Added QXT_RPCSERVICE_DEBUG environment variable for convenient network debugging
* Improved QxtSlotMapper docs
* Fixed qmake deprecation warnings
- Bug fixes
* #48 Won't build using Qt 4.4.3 b/c of QVariant::Hash
* #6 QxtFileLockTest::rw_same() does not pass on Windows
* Fixed QxtFileLock docs
* Fixed examples/jsonrpcclient: exit properly with no arguments set
* Fixed config.tests/db version check to respect MAJOR>4
* #69 Documentation errors
* #46 Install on Mac
* #62 QxtXMLFileLoggerEngine vs QxtXmlFileLoggerEngine
* #60 including <QxtBasicFileLoggerEngine> doens't work
* #63 QxtCheckComboBox display not correct
* Fixed qdoc3 tags in QxtZeroConf docs
* QxtSerialDevice: fixed r/w in open, disable ionotifier on error
* #77 QxtXmlRpcCall: default type not handled
* #78 Case of an empty string as return parameter without type specified
* #79 Missing <value> element inside <param> element in XML-RPC
* #65 QxtCountryComboBox
* #70 QxtConfigWidget display not correct
* QxtAbstractHttpConnector: don't add null devices to buffer list
* QxtZeroconf: Fixed the avahipoll so that the avahi mdns implementation work
0.6.0
-----
- General
* Revised the build system
* Revised docs (now based on qdoc3)
* QxtConfig.cmake
- Bug fixes
* #4 QxtDaemon::daemonize() compilation warning
* #24 QxtFlowView::currentIndex()
* #29 qxtwecore
* #33 Problem in QxtMailMessage
* #34 Debug PDB files
* #36 QxtCommandoptions on Windows wrong option parsing
* #41 Compilation issue on Mac
- QxtCore
* Added QxtModelSerializer
* Removed obsolete QxtSemaphore
* Added QxtJSON
- QxtGui
* Added rich text support to QxtItemDelegate
* Removed obsolete QxtTabWidget::TabMovementMode & QxtTabBar
* Removed obsolete QxtDockWidget
* Revised QxtConfigDialog & QxtConfigWidget
* Enhanced QxtWindowSystem::idleTime() to resolve libXss at run-time
* Added QxtCrumbView::crumbDelegate()
* Added QxtFilterDialog and QxtLookupLineEdit
- QxtNetwork
* Added QxtXmlRpc
* Added QxtMainAttachment::fromFile()
* Revised QxtSmtp
* Added QxtJSONRpcClient and QxtJSONRpcCall
- Added QxtZeroConf module
0.5.2
-----
- Bug fixes
* QxtSerialDevice: update QIODevice status when device is closed
* QxtSerialDevice: destroy QSocketNotifier when device is closed
* Modified QxtGlobalShortcut to use XSetErrorHandler() to catch X(Un)GrabKey() errors on X11
0.5.1
-----
- Bug fixes
* #3 [Vista/Qt 4.5.0] - static build issue
* #9 QxtCheckComboBox display is inconsistent
* #10 qxtwindowsystem_win.cpp(105) : error C2065: 'LASTINPUTINFO': undeclared identifier
* #16 Static lib linkage problem in Qt Creator
* #17 QxtPushButton::minimumSizeHint returns wrong value
* Fixed QxtGlobalShortcut to allow NumLock on X11
* Fixed compilation problems with the GCC-4.4.X series
* Fixed QxtGlobalShortcut::shortcut()
0.5.0
-----
- General
* Added LGPL license option
* Run Krazy checks and fixed found issues
* Improved configure.bat
* Added missing export macros
* Added missing convenience headers
* Improved compatibility
- QT_FORWARD_DECLARE_CLASS
- Q_SLOTS, Q_SIGNALS & Q_FOREACH in headers
- interface
- QxtCore
* Revised QxtFifo
* Added QxtAlgorithms
* Added QxtSerialDevice
* Added QxtSlotMapper
- QxtCrypto
* Revised QxtBlowfish
- QxtGui
* Added QxtWindowSystem::idleTime()
* Added QxtCrumbView
* Improved QxtScheduleView
* Added QxtSortFilterProxyModel
* Improved QxtSpanSlider
- Added QxtSpanSlider::HandleMovementMode
* Improved QxtItemDelegate
- Added ProgressMinimumRole & ProgressMaximumRole
- Added support for busy indicator mode
* Improved QxtLetterBoxWidget
- Added QxtLetterBoxWidget::margin
- Added QxtLetterBoxWidget::resizeWidget
- QxtWeb
* Added QxtWebCgiService
0.4.0
-----
- QxtCore
* Added QxtDeplex
* Added QxtLocale
* Added QxtPointerList
* Added QxtMultiSignalWaiter
* Added QxtSignalGroup
* Added QxtCommandOptions
* Added QxtLogger
* Added QxtAbstractConnectionManager
* Added QxtDataStreamSignalSerializer
* Added QxtAbstractSignalSerializer
- QxtCrypto
* Added QxtHmac
- QxtGui
* Added QxtItemEditorCreatorBase
* Added QxtStandardItemEditorCreator
* Added QxtItemEditorCreator
* Added QxtBaseSpinBox
* Added QxtCountryComboBox
* Added QxtCountryModel
* Added QxtLanguageComboBox
* Added QxtScheduleView
* Added QxtTabBar
* Added QxtFlowView
* Added QxtLetterBoxWidget
* Improved QxtTabWidget
- Added QxtTabWidget::alwaysShowTabBar
- Added QxtTabWidget::tabAnimation
- Added QxtTabWidget::tabMovementMode
* Improved QxtConfirmationMessage
- Added QxtConfirmationMessage::settingsFormat
- Added QxtConfirmationMessage::rememberOnReject
- Added QxtConfirmationMessage::overrideSettingsApplication
- Added QxtConfirmationMessage::overrideSettingsKey
- Added QxtConfirmationMessage::overrideSettingsOrganization
- QxtBerkeley
* Added QxtBdbTree
- QxtWeb
* Revised the whole module
- QxtNetwork
* Added QxtTcpConnectionManager
@@ -1,9 +0,0 @@
set(qxtcommandoptions_SRCS
qxtcommandoptions.cpp
)
qt5_wrap_cpp(qxtcommandoptions_SRCS)
add_library(qxtcommandoptions ${qxtcommandoptions_SRCS})
qt5_use_modules(qxtcommandoptions Widgets)
-89
View File
@@ -1,89 +0,0 @@
Qt Extension Library
Copyright (C) 2007 Qxt Foundation
------------------- Disclaimer ------------------------------------------------
Until the Qxt Foundation is legally established, copyright for the
source code falls back to the original contributor. For information about the
status of the Qxt Foundation, or about the copyright status of any part of Qxt,
contact the Qxt project maintainers at <foundation@libqxt.org>
Once the Qxt Foundation has been legally established, all contributors must
transfer all copyright interest to the Qxt Foundation before their submissions
will be added to the project.
------------------- License ---------------------------------------------------
This library is free software; you can redistribute it and/or modify it
under the terms of the Common Public License, version 1.0, as published by IBM
or under the terms of the GNU Lesser General Public License, version 2.1,
as published by the Free Software Foundation
This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
FITNESS FOR A PARTICULAR PURPOSE.
You should have received a copy of the CPL along with this file.
See the LICENSE file and the cpl1.0.txt file included with the source
distribution for more information. If you did not receive a copy of the
license, contact the Qxt Foundation.
You should have received a copy of the LGPL along with this file.
See the LICENSE file and the lgpl-2.1.txt file included with the source
distribution for more information. If you did not receive a copy of the
license, contact the Qxt Foundation.
Parts of Qxt depend on Qt 4 and/or other libraries that have their own
licenses. Qxt is independent of these licenses; however, use of these other
libraries is subject to their respective license agreements.
------------------- Intent ----------------------------------------------------
The following section describes the opinions and intent of the Qxt Foundation
with regards to the licensing and use of the Qxt source code and library. In
the event that the CPL is found to be illegal or invalid, or if any application
or clause of the license is subjected to question or abuse, this section is a
general statement of the desired interpretation.
This section has no legal standing and the statements made here are strictly
subject to the text of the CPL; that is, if this section and the CPL are in
disagreement, the text of the CPL takes precedence. In no way does this
intent grant you any additional rights or impose any additional restrictions.
If you have questions about licensing, contact the maintainers.
Qxt is built and supported by open-source enthusiasts.
- Please respect the open-source background of the contributors. The code is
provided for everyone's use; you may not restrict the rights of anyone to
use it.
- No individual may claim ownership of any part of the code. It belongs
to the community.
- You may modify the source code to suit your needs, but these changes
must be made free. If you distribute a modified form of Qxt, you must
also distribute the entire source code of the modified form.
- Digital Rights Management (DRM) puts unfair, unfree restrictions on
users and developers. It is the opposite of Free Software. We can't
stop you from using it, but please don't use the Qxt name for software
restricted by DRM.
- Please respect the time and effort put into the project by the developers.
- If you find Qxt useful, it would be appreciated if you would include
text in your application (for instance, in the About dialog) giving
acknowledgement to Qxt.
- If you make modifications to the source code, you must not call the
modified version "Qxt." It's okay to include "Qxt" in the name, but
anyone who receives the modified version needs to know that it's not
the same as the version distributed by the Qxt Foundation.
- We want everyone to be able to use Qxt without restrictions.
- If you distribute Qxt in compiled binary form, please ensure that
everyone who receives it can get the source code used to create it.
- You are free to use Qxt in closed-source applications as long as you
distribute Qxt in an open-source fashion. This does not require you
to make your entire application open-source.
- The Qxt Foundation is a non-profit, non-political organization.
- Please don't use the Qxt name in any political or semi-political
propaganda or publication. We don't like it.
- Qxt is distributed "as-is," with no warranty.
- If it makes your program crash, your computer blow up, or tiny demons
fly out of your nose, please don't sue us.
-213
View File
@@ -1,213 +0,0 @@
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
1. DEFINITIONS
"Contribution" means:
a) in the case of the initial Contributor, the initial code and
documentation distributed under this Agreement, and
b) in the case of each subsequent Contributor:
i) changes to the Program, and
ii) additions to the Program;
where such changes and/or additions to the Program originate from and are
distributed by that particular Contributor. A Contribution 'originates' from a
Contributor if it was added to the Program by such Contributor itself or anyone
acting on such Contributor's behalf. Contributions do not include additions to
the Program which: (i) are separate modules of software distributed in
conjunction with the Program under their own license agreement, and (ii) are not
derivative works of the Program.
"Contributor" means any person or entity that distributes the Program.
"Licensed Patents " mean patent claims licensable by a Contributor which are
necessarily infringed by the use or sale of its Contribution alone or when
combined with the Program.
"Program" means the Contributions distributed in accordance with this Agreement.
"Recipient" means anyone who receives the Program under this Agreement,
including all Contributors.
2. GRANT OF RIGHTS
a) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free copyright license to
reproduce, prepare derivative works of, publicly display, publicly perform,
distribute and sublicense the Contribution of such Contributor, if any, and such
derivative works, in source code and object code form.
b) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed
Patents to make, use, sell, offer to sell, import and otherwise transfer the
Contribution of such Contributor, if any, in source code and object code form.
This patent license shall apply to the combination of the Contribution and the
Program if, at the time the Contribution is added by the Contributor, such
addition of the Contribution causes such combination to be covered by the
Licensed Patents. The patent license shall not apply to any other combinations
which include the Contribution. No hardware per se is licensed hereunder.
c) Recipient understands that although each Contributor grants the licenses
to its Contributions set forth herein, no assurances are provided by any
Contributor that the Program does not infringe the patent or other intellectual
property rights of any other entity. Each Contributor disclaims any liability to
Recipient for claims brought by any other entity based on infringement of
intellectual property rights or otherwise. As a condition to exercising the
rights and licenses granted hereunder, each Recipient hereby assumes sole
responsibility to secure any other intellectual property rights needed, if any.
For example, if a third party patent license is required to allow Recipient to
distribute the Program, it is Recipient's responsibility to acquire that license
before distributing the Program.
d) Each Contributor represents that to its knowledge it has sufficient
copyright rights in its Contribution, if any, to grant the copyright license set
forth in this Agreement.
3. REQUIREMENTS
A Contributor may choose to distribute the Program in object code form under its
own license agreement, provided that:
a) it complies with the terms and conditions of this Agreement; and
b) its license agreement:
i) effectively disclaims on behalf of all Contributors all warranties and
conditions, express and implied, including warranties or conditions of title and
non-infringement, and implied warranties or conditions of merchantability and
fitness for a particular purpose;
ii) effectively excludes on behalf of all Contributors all liability for
damages, including direct, indirect, special, incidental and consequential
damages, such as lost profits;
iii) states that any provisions which differ from this Agreement are offered
by that Contributor alone and not by any other party; and
iv) states that source code for the Program is available from such
Contributor, and informs licensees how to obtain it in a reasonable manner on or
through a medium customarily used for software exchange.
When the Program is made available in source code form:
a) it must be made available under this Agreement; and
b) a copy of this Agreement must be included with each copy of the Program.
Contributors may not remove or alter any copyright notices contained within the
Program.
Each Contributor must identify itself as the originator of its Contribution, if
any, in a manner that reasonably allows subsequent Recipients to identify the
originator of the Contribution.
4. COMMERCIAL DISTRIBUTION
Commercial distributors of software may accept certain responsibilities with
respect to end users, business partners and the like. While this license is
intended to facilitate the commercial use of the Program, the Contributor who
includes the Program in a commercial product offering should do so in a manner
which does not create potential liability for other Contributors. Therefore, if
a Contributor includes the Program in a commercial product offering, such
Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
every other Contributor ("Indemnified Contributor") against any losses, damages
and costs (collectively "Losses") arising from claims, lawsuits and other legal
actions brought by a third party against the Indemnified Contributor to the
extent caused by the acts or omissions of such Commercial Contributor in
connection with its distribution of the Program in a commercial product
offering. The obligations in this section do not apply to any claims or Losses
relating to any actual or alleged intellectual property infringement. In order
to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
Contributor in writing of such claim, and b) allow the Commercial Contributor to
control, and cooperate with the Commercial Contributor in, the defense and any
related settlement negotiations. The Indemnified Contributor may participate in
any such claim at its own expense.
For example, a Contributor might include the Program in a commercial product
offering, Product X. That Contributor is then a Commercial Contributor. If that
Commercial Contributor then makes performance claims, or offers warranties
related to Product X, those performance claims and warranties are such
Commercial Contributor's responsibility alone. Under this section, the
Commercial Contributor would have to defend claims against the other
Contributors related to those performance claims and warranties, and if a court
requires any other Contributor to pay any damages as a result, the Commercial
Contributor must pay those damages.
5. NO WARRANTY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
Recipient is solely responsible for determining the appropriateness of using and
distributing the Program and assumes all risks associated with its exercise of
rights under this Agreement, including but not limited to the risks and costs of
program errors, compliance with applicable laws, damage to or loss of data,
programs or equipment, and unavailability or interruption of operations.
6. DISCLAIMER OF LIABILITY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. GENERAL
If any provision of this Agreement is invalid or unenforceable under applicable
law, it shall not affect the validity or enforceability of the remainder of the
terms of this Agreement, and without further action by the parties hereto, such
provision shall be reformed to the minimum extent necessary to make such
provision valid and enforceable.
If Recipient institutes patent litigation against a Contributor with respect to
a patent applicable to software (including a cross-claim or counterclaim in a
lawsuit), then any patent licenses granted by that Contributor to such Recipient
under this Agreement shall terminate as of the date such litigation is filed. In
addition, if Recipient institutes patent litigation against any entity
(including a cross-claim or counterclaim in a lawsuit) alleging that the Program
itself (excluding combinations of the Program with other software or hardware)
infringes such Recipient's patent(s), then such Recipient's rights granted under
Section 2(b) shall terminate as of the date such litigation is filed.
All Recipient's rights under this Agreement shall terminate if it fails to
comply with any of the material terms or conditions of this Agreement and does
not cure such failure in a reasonable period of time after becoming aware of
such noncompliance. If all Recipient's rights under this Agreement terminate,
Recipient agrees to cease use and distribution of the Program as soon as
reasonably practicable. However, Recipient's obligations under this Agreement
and any licenses granted by Recipient relating to the Program shall continue and
survive.
Everyone is permitted to copy and distribute copies of this Agreement, but in
order to avoid inconsistency the Agreement is copyrighted and may only be
modified in the following manner. The Agreement Steward reserves the right to
publish new versions (including revisions) of this Agreement from time to time.
No one other than the Agreement Steward has the right to modify this Agreement.
IBM is the initial Agreement Steward. IBM may assign the responsibility to serve
as the Agreement Steward to a suitable separate entity. Each new version of the
Agreement will be given a distinguishing version number. The Program (including
Contributions) may always be distributed subject to the version of the Agreement
under which it was received. In addition, after a new version of the Agreement
is published, Contributor may elect to distribute the Program (including its
Contributions) under the new version. Except as expressly stated in Sections
2(a) and 2(b) above, Recipient receives no rights or licenses to the
intellectual property of any Contributor under this Agreement, whether
expressly, by implication, estoppel or otherwise. All rights in the Program not
expressly granted under this Agreement are reserved.
This Agreement is governed by the laws of the State of New York and the
intellectual property laws of the United States of America. No party to this
Agreement will bring a legal action under this Agreement more than one year
after the cause of action arose. Each party waives its rights to a jury trial in
any resulting litigation.
-504
View File
@@ -1,504 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
@@ -1,914 +0,0 @@
/****************************************************************************
**
** Copyright (C) Qxt Foundation. Some rights reserved.
**
** This file is part of the QxtCore module of the Qxt library.
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the Common Public License, version 1.0, as published
** by IBM, and/or under the terms of the GNU Lesser General Public License,
** version 2.1, as published by the Free Software Foundation.
**
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL and the LGPL along with this
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
** included with the source distribution for more information.
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
**
** <http://libqxt.org> <foundation@libqxt.org>
**
****************************************************************************/
#include "qxtcommandoptions.h"
#include <QTextStream>
#include <QIODevice>
#include <QtDebug>
#include <QDir>
/*!
\class QxtCommandOptions
\inmodule QxtCore
\brief The QxtCommandOptions class is a Parser for command-line options
This class is used by applications that need to accept command-line arguments. It can
also automatically generate help text, which keeps it from accidentally falling out of
sync with the supported options, and it can produce warnings for common errors.
It accepts Windows-style ("/option"), UNIX-style ("-option"), and GNU-style
("--option") options. By default, QxtCommandOptions uses Windows-style options
(QxtCommandOptions::Slash) on Windows and GNU-style options (QxtCommandOptions::DoubleDash)
on UNIX and Mac. When using GNU-style options, single-character option names only
require a single leading dash and can be grouped together, for example, "-abc".
Any parameter that does not start with the option prefix is considered a positional
parameter. Most applications treat positional parameters as filenames. When using
GNU- or UNIX-style options, use a double dash ("--") alone to force the remaining
parameters to be interpreted as positional parameters.
To use QxtCommandOptions, first add the supported options using the add() and alias()
methods, then process the command line using the parse() method, and finally retrieve
the processed options using the positional(), count(), value() and/or parameters()
methods.
Mutually-exclusive options can be specified by using the \a group parameter to add().
Only one option in a group will be accepted on the command line; if multiple options
are provided, only the last one takes effect.
Some options may accept an optional or required parameter. Depending on the value
of the paramStyle() property, the parameter may be separated from the option by
an equals sign ("/option=value") or by a space ("-option value"). By default,
Windows uses an equals sign and UNIX and Mac accept both an equals sign and a
space. Optional parameters always require an equals sign. Note that, when using
GNU-style options, single-character options cannot have optional parameters.
A simple archiving application might use code similar to this:
\code
QxtCommandOptions options;
options.add("compress", "create a new archive");
options.alias("compress", "c");
options.add("extract", "extract files from an archive");
options.alias("extract", "x");
options.add("level", "set the compression level (0-9)", QxtCommandOptions::Required);
options.alias("level", "l");
options.add("verbose", "show more information about the process; specify twice for more detail", QxtCommandOptions::AllowMultiple);
options.alias("verbose", "v");
options.add("help", "show this help text");
options.alias("help", "h");
options.parse(QCoreApplication::arguments());
if(options.count("help") || options.showUnrecognizedWarning()) {
options.showUsage();
return -1;
}
bool verbose = options.count("verbose");
int level = 5;
if(options.count("level")) {
level = options.value("level").toInt();
}
\endcode
\sa QCoreApplication::arguments()
*/
static const char* qxt_qt_options[] =
{
"=style", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application GUI style"),
"=stylesheet", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application stylesheet"),
"=session", QT_TRANSLATE_NOOP("QxtCommandOptions", "restores the application from an earlier session"),
"widgetcount", QT_TRANSLATE_NOOP("QxtCommandOptions", "displays debugging information about widgets"),
"reverse", QT_TRANSLATE_NOOP("QxtCommandOptions", "use right-to-left layout"),
#ifdef QT_DEBUG
"nograb", QT_TRANSLATE_NOOP("QxtCommandOptions", "never grab the mouse or keyboard"),
#endif
#if defined(QT_DEBUG) && defined(Q_WS_X11)
"dograb", QT_TRANSLATE_NOOP("QxtCommandOptions", "grab the mouse/keyboard even in a debugger"),
"sync", QT_TRANSLATE_NOOP("QxtCommandOptions", "run in synchronous mode for debugging"),
#endif
#ifdef Q_WS_WIN
"direct3d", QT_TRANSLATE_NOOP("QxtCommandOptions", "use Direct3D by default"),
#endif
#ifdef Q_WS_X11
"=display", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the X11 display"),
"=geometry", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the geometry of the first window"),
"=font", "",
"=fn", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default font"),
"=background", "",
"=bg", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default background color"),
"=foreground", "",
"=fg", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default foreground color"),
"=button", "",
"=btn", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default button color"),
"=name", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application name"),
"=title", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application title"),
"=visual", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the X11 visual type"),
"=ncols", QT_TRANSLATE_NOOP("QxtCommandOptions", "limit the number of colors on an 8-bit display"),
"cmap", QT_TRANSLATE_NOOP("QxtCommandOptions", "use a private color map"),
"=im", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the input method server"),
"noxim", QT_TRANSLATE_NOOP("QxtCommandOptions", "disable the X Input Method"),
"=inputstyle", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the style used by the input method"),
#endif
0, 0
};
/*
* This function is used to check to see if a parameter
* is used by Qt.
*/
static int isQtOption(const QString& param)
{
// Qt options all start with a single dash regardless of platform
if (param.length() < 2) return 0;
if (param[0] != '-') return 0;
if (param[1] == '-') return 0;
#ifdef Q_OS_MAC
if (param.left(5) == "-psn_") return 1;
#endif
QString name = param.mid(1), value;
// bool hasEquals;
// Separate the option and the value, if present
if (name.indexOf('=') != -1)
{
value = param.section('=', 1);
name = param.section('=', 0, 0);
// hasEquals = true;
}
else
{
value = "";
// hasEquals = false;
}
const char* option;
bool optionHasValue;
for (int i = 0; qxt_qt_options[i]; i += 2)
{
option = qxt_qt_options[i];
// In the table above, options that require parameters start with =
if (option[0] == '=')
{
optionHasValue = true;
option = option + 1; // pointer math to skip =
}
else
{
optionHasValue = false;
}
// The return value indicates how many parameters to skip
if (name == option)
{
if (optionHasValue) return 2;
return 1;
}
}
return 0;
}
// Storage structure for option data
struct QxtCommandOption
{
QStringList names; // aliases accepted at the command line
QString canonicalName; // name used for alias()/count()/value()
QString desc; // documentation string
QStringList values; // values passed on command line
QxtCommandOptions::ParamTypes paramType; // flags
quint16 group; // mutual exclusion group
};
class QxtCommandOptionsPrivate : public QxtPrivate<QxtCommandOptions>
{
Q_DECLARE_TR_FUNCTIONS(QxtCommandOptions)
public:
QXT_DECLARE_PUBLIC(QxtCommandOptions)
QList<QxtCommandOption> options;
QHash<QString, QxtCommandOption*> lookup; // cache structure to simplify processing
QHash<int, QList<QxtCommandOption*> > groups; // cache structure to simplify processing
QxtCommandOptions::FlagStyle flagStyle;
QxtCommandOptions::ParamStyle paramStyle;
QStringList positional; // prefixless parameters
QStringList unrecognized; // prefixed parameters not in recognized options
QStringList missingParams; // parameters with required values missing
int screenWidth;
bool parsed;
QxtCommandOption* findOption(const QString& name);
const QxtCommandOption* findOption(const QString& name) const;
void setOption(QxtCommandOption* option, const QString& value = QString());
void parse(const QStringList& params);
};
/* Looks up an option in qxt_d().options by canonical name */
QxtCommandOption* QxtCommandOptionsPrivate::findOption(const QString& name)
{
// The backwards loop will find what we're looking for more quickly in the
// typical use case, where you add aliases immediately after adding the option.
for (int i = options.count() - 1; i >= 0; --i)
{
if (options[i].canonicalName == name) return &options[i];
}
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("option \"%1\" not found").arg(name));
return 0;
}
/* Looks up an option in qxt_d().options by canonical name
* This is a const overload for const functions */
const QxtCommandOption* QxtCommandOptionsPrivate::findOption(const QString& name) const
{
// The backwards loop will find what we're looking for more quickly in the
// typical use case, where you add aliases immediately after adding the option.
for (int i = options.count() - 1; i >= 0; --i)
{
if (options[i].canonicalName == name) return &(options.at(i));
}
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("option \"%1\" not found").arg(name));
return 0;
}
/*!
* Constructs a QxtCommandOptions object.
*/
QxtCommandOptions::QxtCommandOptions()
{
QXT_INIT_PRIVATE(QxtCommandOptions);
qxt_d().screenWidth = 80;
qxt_d().parsed = false;
#ifdef Q_OS_WIN
setFlagStyle(Slash);
setParamStyle(Equals);
#else
setFlagStyle(DoubleDash);
setParamStyle(SpaceAndEquals);
#endif
}
/*!
* Sets which prefix is used to identify options. The default value is Slash on Windows
* and DoubleDash on all other platforms.
*
* Note that Qt's built-in options (see QApplication) always use a single dash,
* regardless of this setting.
*/
void QxtCommandOptions::setFlagStyle(FlagStyle style)
{
qxt_d().flagStyle = style;
}
/*!
* Gets which prefix is used to identify options.
*/
QxtCommandOptions::FlagStyle QxtCommandOptions::flagStyle() const
{
return qxt_d().flagStyle;
}
/*!
* Sets which value separator is used for options that accept parameters.
* The default value is Equals on Windows and SpaceAndEquals on all other
* platforms.
*
* Single-letter options with optional parameters in DoubleDash mode
* always use an equals sign, regardless of this setting.
*
* Qt's built-in options always behave as SpaceAndEquals, regardless of
* this setting.
*/
void QxtCommandOptions::setParamStyle(ParamStyle style)
{
qxt_d().paramStyle = style;
}
/*!
* Sets which value separator is used for options that accept parameters.
*/
QxtCommandOptions::ParamStyle QxtCommandOptions::paramStyle() const
{
return qxt_d().paramStyle;
}
/*!
* Sets the width of the screen, in characters. This is used for word-wrapping
* the automatically-generated help text to the size of the screen. The default
* value is 80 characters. Pass 0 to disable word-wrapping.
*/
void QxtCommandOptions::setScreenWidth(quint16 width)
{
qxt_d().screenWidth = width;
}
/*!
* Gets the width of the screen, in characters.
*/
quint16 QxtCommandOptions::screenWidth() const
{
return qxt_d().screenWidth;
}
/*!
* Adds a section separator. Section separators are only used in generating
* help text, and can be used to visually separate related groups of
* options.
*/
void QxtCommandOptions::addSection(const QString& name)
{
QxtCommandOption option;
option.canonicalName.clear();
option.desc = name;
qxt_d().options.append(option);
}
/*!
* Adds an option to the parser.
*
* The name parameter defines the name that will be used by the alias(),
* count(), value(), and parameters() methods. Additional names for the
* same option can be defined using the alias() method.
*
* The group parameter, if used, defines a set of mutually-exclusive options.
* If more than one option in the same group is passed on the command line,
* only the last one takes effect.
*/
void QxtCommandOptions::add(const QString& name, const QString& desc, ParamTypes paramType, int group)
{
QxtCommandOption option;
option.canonicalName = name;
option.desc = desc;
option.paramType = paramType;
option.group = group;
qxt_d().options.append(option);
if (group != -1)
qxt_d().groups[group].append(&(qxt_d().options.last()));
// Connect the canonical name to a usable name
alias(name, name);
}
/*!
* Provides an alias for an option. An alias is another name for the option that can be
* given on the command line. Aliases cannot be used as parameters to alias(), count()
* or value() nor can single-letter aliases be created for options with an optional value.
*
* The from parameter must be a name has previously been added with the add() method.
*/
void QxtCommandOptions::alias(const QString& from, const QString& to)
{
QxtCommandOption* option = qxt_d().findOption(from);
if (!option) return; // findOption outputs the warning
option->names.append(to);
qxt_d().lookup[to] = option;
if (option->paramType & ValueOptional && qxt_d().flagStyle == DoubleDash && to.length() == 1)
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("Short options cannot have optional parameters"));
}
/*!
* Returns the positional parameters from the command line, that is, the arguments that
* do not begin with the option prefix.
*
* \sa flagStyle()
*/
QStringList QxtCommandOptions::positional() const
{
if (!qxt_d().parsed)
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("positional() called before parse()"));
return qxt_d().positional;
}
/*!
* Returns the options that could not be parsed.
*
* An argument is unrecognized if it begins with the option prefix but was never
* defined using the add() or alias() methods, or if it requires a value but the
* user did not provide one.
*/
QStringList QxtCommandOptions::unrecognized() const
{
if (!qxt_d().parsed)
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("unrecognized() called before parse()"));
return qxt_d().unrecognized + qxt_d().missingParams;
}
/*!
* Returns the number of times an option was passed on the command line.
*
* This function will only return 0 or 1 for options that were not created with the
* QxtCommandOptions::AllowMultiple flag set.
*/
int QxtCommandOptions::count(const QString& name) const
{
if (!qxt_d().parsed)
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("count() called before parse()"));
const QxtCommandOption* option = qxt_d().findOption(name);
if (!option) return 0; // findOption outputs the warning
return option->values.count();
}
/*!
* Returns the value or values for an option passed on the command line.
*
* If the option was not passed on the command line, this function returns a null QVariant.
* If the option was created with the QxtCommandOptions::AllowMultiple flag, and the option
* was passed more than once, this function returns a QStringList containing the values.
* Otherwise, this function returns the last (or only) value given to the option on the
* command line. When an option allowing an optional value is provided on the command
* line and for which no value is provided, an empty but non-null QString will be returned
* in the QVariant.
*/
QVariant QxtCommandOptions::value(const QString& name) const
{
if (!qxt_d().parsed)
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("value() called before parse()"));
const QxtCommandOption* option = qxt_d().findOption(name);
if (!option) return QVariant(); // findOption outputs the warning
int ct = option->values.count();
if (ct == 0) return QVariant();
if (ct == 1) return option->values.first();
return option->values;
}
/*!
* Returns all of the recognized options passed on the command line.
*/
QMultiHash<QString, QVariant> QxtCommandOptions::parameters() const
{
if (!qxt_d().parsed)
qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("parameters() called before parse()"));
QMultiHash<QString, QVariant> params;
int ct;
foreach(const QxtCommandOption& option, qxt_d().options)
{
ct = option.values.count();
if (!ct)
{
continue;
}
else if (!(option.paramType & (ValueOptional | ValueRequired)))
{
// Valueless options are really a true/false flag
params.insert(option.canonicalName, true);
}
else
{
foreach(const QVariant& value, option.values)
params.insert(option.canonicalName, value);
}
}
return params;
}
/*!
* This is an overloaded member function, provided for convenience.
*
* Process a set of command-line options. This overload accepts a number of
* arguments and a pointer to the list of arguments.
*
* Note that parse() may be invoked multiple times to handle arguments from
* more than one source.
*/
void QxtCommandOptions::parse(int argc, char** argv)
{
QStringList args;
for (int i = 0; i < argc; i++)
args << argv[i];
parse(args);
}
/*!
* Process a set of command-line options. This overload accepts a QStringList
* containing the command-line options, such as the one returned by
* QCoreApplication::arguments().
*
* Note that parse() may be invoked multiple times to handle arguments from
* more than one source.
*
* \sa QCoreApplication::arguments()
*/
void QxtCommandOptions::parse(QStringList params)
{
qxt_d().parse(params);
qxt_d().parsed = true;
}
/* Update the internal data structures with an option from the command line. */
void QxtCommandOptionsPrivate::setOption(QxtCommandOption* option, const QString& value)
{
if (groups.contains(option->group))
{
// Clear mutually-exclusive options
QList<QxtCommandOption*>& others = groups[option->group];
foreach(QxtCommandOption* other, others)
{
if (other != option) other->values.clear();
}
}
// Clear all previous values if multiples are not accepted
if (!(option->paramType & QxtCommandOptions::AllowMultiple))
option->values.clear();
option->values.append(value);
}
/* Do the work of parsing the command line */
void QxtCommandOptionsPrivate::parse(const QStringList& params)
{
int pos = 1; // 0 is the application name
int ct = params.count();
int skip = 0;
bool endFlags = false;
bool /*notUnrecognized, */hasEquals;
QString name, param, value;
while (pos < ct)
{
// Ignore Qt built-in options
while ((skip = isQtOption(params[pos])))
{
pos += skip;
if (pos >= ct)
return;
}
param = params[pos];
pos++;
if (!endFlags && ((flagStyle == QxtCommandOptions::Slash && param[0] == '/') ||
(flagStyle != QxtCommandOptions::Slash && param[0] == '-')))
{
// tagged argument
if (param.length() == 1)
{
// "-" or "/" alone can't possibly match a flag, so use positional.
positional.append(param);
continue;
}
// notUnrecognized = false;
if (flagStyle != QxtCommandOptions::Slash && param == "--")
{
// End of parameters flag
endFlags = true;
}
else if (flagStyle == QxtCommandOptions::DoubleDash && param[1] != '-')
{
// Handle short-form options
int len = param.length();
QxtCommandOption* option;
for (int i = 1; i < len; i++)
{
QString ch(param[i]);
if (ch == "-")
{
endFlags = true;
}
else
{
option = lookup.value(ch, 0);
if (!option)
{
// single-letter flag has no known equivalent
unrecognized.append(QString("-") + param[i]);
}
else
{
if (option->paramType & QxtCommandOptions::ValueRequired)
{
// Check for required parameters
// Short options can't have optional parameters
if (pos >= params.count())
{
missingParams.append(param);
break;
}
value = params[pos];
}
else
{
value = "";
}
setOption(option, value);
}
}
}
}
else
{
// Break apart a value
if (param.indexOf('=') != -1)
{
value = param.section('=', 1);
param = param.section('=', 0, 0);
hasEquals = true;
}
else
{
value = "";
hasEquals = false;
}
if (flagStyle == QxtCommandOptions::DoubleDash)
name = param.mid(2);
else
name = param.mid(1);
QxtCommandOption* option = lookup.value(name, 0);
if (!option)
{
unrecognized.append(param);
}
else
{
if (option->paramType & QxtCommandOptions::ValueRequired && !hasEquals)
{
// Check for parameters
if (pos >= params.count())
{
missingParams.append(param);
break;
}
value = params[pos];
pos++;
}
else if ((paramStyle & QxtCommandOptions::Space)
&& (option->paramType & QxtCommandOptions::ValueOptional)
&& !hasEquals)
{
if (pos < params.count())
{
if (!((flagStyle == QxtCommandOptions::Slash && params.at(pos)[0] == '/') ||
(flagStyle != QxtCommandOptions::Slash && params.at(pos)[0] == '-')))
{
value = params[pos];
pos++;
}
}
}
setOption(option, value);
}
}
}
else
{
// positional argument
positional.append(param);
}
}
}
/*!
* This is an overloaded member function, provided for convenience.
*
* Outputs a warning about any unrecognized options to the provided device, or
* standard error by default. The device must already be opened for writing.
*
* This function returns true if any warnings were output, or false otherwise.
*
* If a QCoreApplication or a subclass of QCoreApplication has been instantiated,
* this function uses QCoreApplication::applicationFilePath() to get the name
* of the executable to include in the message.
*
* \sa QCoreApplication::applicationFilePath()
*/
bool QxtCommandOptions::showUnrecognizedWarning(QIODevice* device) const
{
if (!device)
{
QTextStream stream(stderr);
return showUnrecognizedWarning(*&stream);
}
else
{
QTextStream stream(device);
return showUnrecognizedWarning(*&stream);
}
}
/*!
* Returns the automatically-generated warning text about any unrecognized options.
*
* If a QCoreApplication or a subclass of QCoreApplication has been instantiated,
* this function uses QCoreApplication::applicationFilePath() to get the name
* of the executable to include in the message.
*
* \sa QCoreApplication::applicationFilePath()
*/
QString QxtCommandOptions::getUnrecognizedWarning() const
{
QString usage;
QTextStream stream(&usage);
showUnrecognizedWarning(*&stream);
return usage;
}
/*!
* This is an overloaded member function, provided for convenience.
*
* Outputs a warning about any unrecognized options to the provided stream.
*
* This function returns true if any warnings were output, or false otherwise.
*
* If a QCoreApplication or a subclass of QCoreApplication has been instantiated,
* this function uses QCoreApplication::applicationFilePath() to get the name
* of the executable to include in the message.
*
* \sa QCoreApplication::applicationFilePath()
*/
bool QxtCommandOptions::showUnrecognizedWarning(QTextStream& stream) const
{
if (!qxt_d().unrecognized.count() && !qxt_d().missingParams.count()) return false;
QString name;
if (QCoreApplication::instance())
name = QDir(QCoreApplication::applicationFilePath()).dirName();
if (name.isEmpty())
name = "QxtCommandOptions";
if (qxt_d().unrecognized.count())
stream << name << ": " << tr("unrecognized parameters: ") << qxt_d().unrecognized.join(" ") << endl;
foreach(const QString& param, qxt_d().missingParams)
stream << name << ": " << tr("%1 requires a parameter").arg(param) << endl;
return true;
}
/*!
* This is an overloaded member function, provided for convenience.
*
* Outputs automatically-generated usage text for the accepted options to the provided
* device, or standard error by default. The device must already be opened for writing.
*
* Pass true to showQtOptions to output usage text for the options recognized by
* QApplication.
*
* \sa QApplication
*/
void QxtCommandOptions::showUsage(bool showQtOptions, QIODevice* device) const
{
if (!device)
{
QTextStream stream(stdout);
showUsage(showQtOptions, *&stream);
}
else
{
QTextStream stream(device);
showUsage(showQtOptions, *&stream);
}
}
/*!
* Returns the automatically-generated usage text for the accepted options.
*/
QString QxtCommandOptions::getUsage(bool showQtOptions) const
{
QString usage;
QTextStream stream(&usage);
showUsage(showQtOptions, *&stream);
return usage;
}
/*!
* This is an overloaded member function, provided for convenience.
*
* Outputs automatically-generated usage text for the accepted options to the provided
* stream.
*
* Pass true to showQtOptions to output usage text for the options recognized by
* QApplication.
*
* \sa QApplication
*/
void QxtCommandOptions::showUsage(bool showQtOptions, QTextStream& stream) const
{
QStringList names;
QStringList descs;
int maxNameLength = 0;
QString name;
foreach(const QxtCommandOption& option, qxt_d().options)
{
// Don't generate usage for undocumented parameters
if (option.paramType & Undocumented) continue;
foreach(const QString& n, option.names)
{
if (name.length()) name += ", ";
if (qxt_d().flagStyle == Slash)
name += '/';
else if (qxt_d().flagStyle == DoubleDash && n.length() > 1)
name += "--";
else
name += '-';
name += n;
if (option.paramType & (ValueOptional | ValueRequired))
{
if (option.paramType & ValueOptional)
name += "[=x]";
else if (qxt_d().paramStyle == SpaceAndEquals)
name += "[=]x";
else if (qxt_d().paramStyle == Equals)
name += "=x";
else
name += " x";
}
}
// The maximum name length is used for formatting the output columns
if (name.length() > maxNameLength)
maxNameLength = name.length();
names.append(name);
descs.append(option.desc);
name = "";
}
if (showQtOptions)
{
// Add a section header
names.append(QString());
descs.append("Common Qt Options");
// Parse through qxt_qt_options
const char* option;
bool optionHasValue;
for (int i = 0; qxt_qt_options[i]; i += 2)
{
option = qxt_qt_options[i];
if (option[0] == '=')
{
// The option takes a parameter
optionHasValue = true;
option = option + 1; // pointer math to skip the =
}
else
{
optionHasValue = false;
}
// Concatenate on the option alias
if (!name.isEmpty()) name += ", ";
name += '-';
name += option;
if (optionHasValue) name += "[=]x";
if (qxt_qt_options[i+1][0] != 0)
{
// The last alias for the option has the description
if (name.length() > maxNameLength)
maxNameLength = name.length();
names.append(name);
descs.append(qxt_qt_options[i+1]);
name = "";
}
}
}
int ct = names.count();
QString line, wrap(maxNameLength + 3, ' ');
for (int i = 0; i < ct; i++)
{
if (names[i].isEmpty())
{
// Section headers have no name entry
stream << endl << descs[i] << ":" << endl;
continue;
}
line = ' ' + names[i] + QString(maxNameLength - names[i].length() + 2, ' ');
foreach(const QString& word, descs[i].split(' ', QString::SkipEmptyParts))
{
if (qxt_d().screenWidth > 0 && line.length() + word.length() >= qxt_d().screenWidth)
{
stream << line << endl;
line = wrap;
}
line += word + ' ';
}
stream << line << endl;
}
}
@@ -1,124 +0,0 @@
/****************************************************************************
**
** Copyright (C) Qxt Foundation. Some rights reserved.
**
** This file is part of the QxtCore module of the Qxt library.
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the Common Public License, version 1.0, as published
** by IBM, and/or under the terms of the GNU Lesser General Public License,
** version 2.1, as published by the Free Software Foundation.
**
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL and the LGPL along with this
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
** included with the source distribution for more information.
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
**
** <http://libqxt.org> <foundation@libqxt.org>
**
****************************************************************************/
#ifndef QXTCOMMANDOPTIONS_H
#define QXTCOMMANDOPTIONS_H
#include <qxtglobal.h>
#include <QStringList>
#include <QVariant>
#include <QCoreApplication> // for Q_DECLARE_TR_FUNCTIONS
#include <QMultiHash>
#include <QFlags>
class QxtCommandOptionsPrivate;
QT_FORWARD_DECLARE_CLASS(QTextStream)
QT_FORWARD_DECLARE_CLASS(QIODevice)
class QxtCommandOptions
{
Q_DECLARE_TR_FUNCTIONS(QxtCommandOptions)
public:
/*!
* \enum QxtCommandOptions::FlagStyle
* This enum type defines which type of option prefix is used.
* Slash is the default on Windows.
* DoubleDash is the default on all other platforms.
*/
enum FlagStyle
{
DoubleDash, /*!< Two dashes (GNU-style) */
SingleDash, /*!< One dash (UNIX-style) */
Slash /*!< Forward slash (Windows-style) */
};
/*!
* \enum QxtCommandOptions::ParamStyle
* This enum type defines what syntax is used for options that
* require parameters. Equals is the default on Windows.
* SpaceAndEquals is the default on all other platforms.
*/
enum ParamStyle
{
Space = 1, /*!< Space ("-option value") */
Equals = 2, /*!< Equals sign ("/option=value") */
SpaceAndEquals = 3 /*!< Accept either */
};
/*!
* \enum QxtCommandOptions::ParamType
* \flags QxtCommandOptions::ParamTypes
* This enum type is used to specify flags that control the
* interpretation of an option.
*
* The ParamTypes type is a typedef for QFlags<ParamType>. It stores
* an OR combination of ParamType values.
*/
enum ParamType
{
NoValue = 0, /*!< The option does not accept a value. */
ValueOptional = 1, /*!< The option may accept a value. */
ValueRequired = 2, /*!< The option requires a value. */
Optional = ValueOptional, /*!< The option may accept a value. Deprecated in favor of ValueOptional. */
Required = ValueRequired, /*!< The option requires a value. Deprecated in favor of ValueRequired. */
AllowMultiple = 4, /*!< The option may be passed multiple times. */
Undocumented = 8 /*!< The option is not output in the help text. */
};
Q_DECLARE_FLAGS(ParamTypes, ParamType)
QxtCommandOptions();
void setFlagStyle(FlagStyle style);
FlagStyle flagStyle() const;
void setParamStyle(ParamStyle style);
ParamStyle paramStyle() const;
void setScreenWidth(quint16 width);
quint16 screenWidth() const;
void addSection(const QString& name);
void add(const QString& name, const QString& desc = QString(), ParamTypes paramType = NoValue, int group = -1);
void alias(const QString& from, const QString& to);
QStringList positional() const;
QStringList unrecognized() const;
int count(const QString& name) const;
QVariant value(const QString& name) const;
QMultiHash<QString, QVariant> parameters() const;
void parse(int argc, char** argv);
void parse(QStringList params);
void showUsage(bool showQtOptions = false, QIODevice* device = 0) const;
void showUsage(bool showQtOptions, QTextStream& stream) const;
QString getUsage(bool showQtOptions = false) const;
bool showUnrecognizedWarning(QIODevice* device = 0) const;
bool showUnrecognizedWarning(QTextStream& stream) const;
QString getUnrecognizedWarning() const;
private:
QXT_DECLARE_PRIVATE(QxtCommandOptions)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QxtCommandOptions::ParamTypes)
#endif // QXTCOMMANDOPTIONS_H
-207
View File
@@ -1,207 +0,0 @@
/****************************************************************************
**
** Copyright (C) Qxt Foundation. Some rights reserved.
**
** This file is part of the QxtCore module of the Qxt library.
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the Common Public License, version 1.0, as published
** by IBM, and/or under the terms of the GNU Lesser General Public License,
** version 2.1, as published by the Free Software Foundation.
**
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL and the LGPL along with this
** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
** included with the source distribution for more information.
** If you did not receive a copy of the licenses, contact the Qxt Foundation.
**
** <http://libqxt.org> <foundation@libqxt.org>
**
****************************************************************************/
#ifndef QXTGLOBAL_H
#define QXTGLOBAL_H
#include <QtGlobal>
#define QXT_VERSION 0x000602
#define QXT_VERSION_STR "0.6.2"
//--------------------------global macros------------------------------
#ifndef QXT_NO_MACROS
#endif // QXT_NO_MACROS
//--------------------------export macros------------------------------
#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
#if !defined(QXT_STATIC)
# if defined(BUILD_QXT_CORE)
# define QXT_CORE_EXPORT Q_DECL_EXPORT
# else
# define QXT_CORE_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_CORE_EXPORT
#endif // BUILD_QXT_CORE
#if !defined(QXT_STATIC)
# if defined(BUILD_QXT_GUI)
# define QXT_GUI_EXPORT Q_DECL_EXPORT
# else
# define QXT_GUI_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_GUI_EXPORT
#endif // BUILD_QXT_GUI
#if !defined(QXT_STATIC)
# if defined(BUILD_QXT_NETWORK)
# define QXT_NETWORK_EXPORT Q_DECL_EXPORT
# else
# define QXT_NETWORK_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_NETWORK_EXPORT
#endif // BUILD_QXT_NETWORK
#if !defined(QXT_STATIC)
# if defined(BUILD_QXT_SQL)
# define QXT_SQL_EXPORT Q_DECL_EXPORT
# else
# define QXT_SQL_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_SQL_EXPORT
#endif // BUILD_QXT_SQL
#if !defined(QXT_STATIC)
# if defined(BUILD_QXT_WEB)
# define QXT_WEB_EXPORT Q_DECL_EXPORT
# else
# define QXT_WEB_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_WEB_EXPORT
#endif // BUILD_QXT_WEB
#if !defined(QXT_STATIC)
# if defined(BUILD_QXT_BERKELEY)
# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT
# else
# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_BERKELEY_EXPORT
#endif // BUILD_QXT_BERKELEY
#if !defined(QXT_STATIC)
# if defined(BUILD_QXT_ZEROCONF)
# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT
# else
# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_ZEROCONF_EXPORT
#endif // QXT_ZEROCONF_EXPORT
#if defined BUILD_QXT_CORE || defined BUILD_QXT_GUI || defined BUILD_QXT_SQL || defined BUILD_QXT_NETWORK || defined BUILD_QXT_WEB || defined BUILD_QXT_BERKELEY || defined BUILD_QXT_ZEROCONF
# define BUILD_QXT
#endif
QXT_CORE_EXPORT const char* qxtVersion();
#ifndef QT_BEGIN_NAMESPACE
#define QT_BEGIN_NAMESPACE
#endif
#ifndef QT_END_NAMESPACE
#define QT_END_NAMESPACE
#endif
#ifndef QT_FORWARD_DECLARE_CLASS
#define QT_FORWARD_DECLARE_CLASS(Class) class Class;
#endif
/****************************************************************************
** This file is derived from code bearing the following notice:
** The sole author of this file, Adam Higerd, has explicitly disclaimed all
** copyright interest and protection for the content within. This file has
** been placed in the public domain according to United States copyright
** statute and case law. In jurisdictions where this public domain dedication
** is not legally recognized, anyone who receives a copy of this file is
** permitted to use, modify, duplicate, and redistribute this file, in whole
** or in part, with no restrictions or conditions. In these jurisdictions,
** this file shall be copyright (C) 2006-2008 by Adam Higerd.
****************************************************************************/
#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;
#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
#define QXT_D(PUB) PUB##Private& d = qxt_d()
#define QXT_P(PUB) PUB& p = qxt_p()
template <typename PUB>
class QxtPrivate
{
public:
virtual ~QxtPrivate()
{}
inline void QXT_setPublic(PUB* pub)
{
qxt_p_ptr = pub;
}
protected:
inline PUB& qxt_p()
{
return *qxt_p_ptr;
}
inline const PUB& qxt_p() const
{
return *qxt_p_ptr;
}
private:
PUB* qxt_p_ptr;
};
template <typename PUB, typename PVT>
class QxtPrivateInterface
{
friend class QxtPrivate<PUB>;
public:
QxtPrivateInterface()
{
pvt = new PVT;
}
~QxtPrivateInterface()
{
delete pvt;
}
inline void setPublic(PUB* pub)
{
pvt->QXT_setPublic(pub);
}
inline PVT& operator()()
{
return *static_cast<PVT*>(pvt);
}
inline const PVT& operator()() const
{
return *static_cast<PVT*>(pvt);
}
private:
QxtPrivateInterface(const QxtPrivateInterface&) { }
QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
QxtPrivate<PUB>* pvt;
};
#endif // QXT_GLOBAL
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -12264,7 +12264,7 @@ Please only use this if you know what you are doing. There are no error checks
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -12119,7 +12119,7 @@ m2560 for v4.1 boards</source>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -12284,7 +12284,7 @@ m2560 para las placas v4.1</translation>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -12332,7 +12332,7 @@ m2560 joka on v4.1 lähettimessä</translation>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -10505,7 +10505,7 @@ m2560 for v4.1 boards</source>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -12354,7 +12354,7 @@ m2560 per le schede v4.1</translation>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -10499,7 +10499,7 @@ m2560 for v4.1 boards</source>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -12564,7 +12564,7 @@ m2560 dla platformy V4</translation>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -10505,7 +10505,7 @@ m2560 for v4.1 boards</source>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -10549,7 +10549,7 @@ m2560 for v4.1 boards</source>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+1 -1
View File
@@ -9622,7 +9622,7 @@ m2560 för v4.1-kort</translation>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<source>Transmitter Splash Screen Editor</source>
<translation>Startbildsredigerare</translation>
@@ -12595,7 +12595,7 @@ v4.1版电路板应为m2560</translation>
</message>
</context>
<context>
<name>customizeSplashDialog</name>
<name>CustomizeSplashDialog</name>
<message>
<location filename="../customizesplashdialog.ui" line="23"/>
<source>Transmitter Splash Screen Editor</source>
+27 -3
View File
@@ -20,9 +20,33 @@
#ifndef _WARNINGS_H_
#define _WARNINGS_H_
#define WARNING_LEVEL 0
#define WARNING_ID 7
#define WARNING QObject::tr("Thank you for upgrading to OpenTX 2.0. This is a major upgrade that adds and modifies a lot of things, so please make sure that you read release notes carefully to learn about the changes, and thoroughly check each of your models for proper function.\n\nThe OpenTX Team.")
#define CPN_STR_MSG_WELCOME QCoreApplication::translate("Companion", \
"<p><b>Welcome to OpenTX v%1.</b></p>" \
"<p>As the first step, please configure the initial Radio Profile by selecting your Radio Type, Menu Language, and Build Options.</p>" \
"<p>You may also want to take this time to review the other available options in the displayed Settings dialog.</p>" \
"<p>After saving your settings, we recommend you download the latest firmware for your radio by using the <i>File -&gt; Download</i> menu option.</p>" \
"<p>Please visit <a href='http://www.open-tx.org'>open-tx.org</a> for latest news, updates and documentation. Thank you for choosing OpenTX!</p>" \
"- The OpenTX Team.")
#define CPN_STR_MSG_UPGRADED QCoreApplication::translate("Companion", \
"<p><b>Thank you for upgrading to OpenTX v%1.</b></p>" \
"<p>This is a major upgrade that adds and modifies a lot of things, so please make sure that you read release notes carefully" \
" to learn about the changes, and thoroughly check each of your models for proper function.</p>" \
"<p>Please visit <a href='http://www.open-tx.org'>open-tx.org</a> for release notes and other documentation.</p>" \
"- The OpenTX Team.")
namespace AppMessages {
// These are used for saving "[don't] show this message again" user preferences.
enum MessageCodes {
MSG_NONE = 0,
MSG_WELCOME = 0x01,
MSG_UPGRADED = 0x02,
MSG_RESERVED = 0x04, // reserved due to legacy code
};
} // namespace AppWarnings
#endif // _WARNINGS_H_
@@ -1 +1 @@
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666";
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666"
+189 -189
View File
@@ -1,190 +1,190 @@
/*
_____________________________________________________________________________
File Association
_____________________________________________________________________________
Based on code taken from http://nsis.sourceforge.net/File_Association
Usage in script:
1. !include "FileAssociation.nsh"
2. [Section|Function]
${FileAssociationFunction} "Param1" "Param2" "..." $var
[SectionEnd|FunctionEnd]
FileAssociationFunction=[RegisterExtension|UnRegisterExtension]
_____________________________________________________________________________
${RegisterExtension} "[executable]" "[extension]" "[description]"
"[executable]" ; executable which opens the file format
;
"[extension]" ; extension, which represents the file format to open
;
"[description]" ; description for the extension. This will be display in Windows Explorer.
;
${UnRegisterExtension} "[extension]" "[description]"
"[extension]" ; extension, which represents the file format to open
;
"[description]" ; description for the extension. This will be display in Windows Explorer.
;
_____________________________________________________________________________
Macros
_____________________________________________________________________________
Change log window verbosity (default: 3=no script)
Example:
!include "FileAssociation.nsh"
!insertmacro RegisterExtension
${FileAssociation_VERBOSE} 4 # all verbosity
!insertmacro UnRegisterExtension
${FileAssociation_VERBOSE} 3 # no script
*/
!ifndef FileAssociation_INCLUDED
!define FileAssociation_INCLUDED
!include Util.nsh
!verbose push
!verbose 3
!ifndef _FileAssociation_VERBOSE
!define _FileAssociation_VERBOSE 3
!endif
!verbose ${_FileAssociation_VERBOSE}
!define FileAssociation_VERBOSE `!insertmacro FileAssociation_VERBOSE`
!verbose pop
!macro FileAssociation_VERBOSE _VERBOSE
!verbose push
!verbose 3
!undef _FileAssociation_VERBOSE
!define _FileAssociation_VERBOSE ${_VERBOSE}
!verbose pop
!macroend
!macro RegisterExtensionCall _EXECUTABLE _EXTENSION _DESCRIPTION
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Push `${_DESCRIPTION}`
Push `${_EXTENSION}`
Push `${_EXECUTABLE}`
${CallArtificialFunction} RegisterExtension_
!verbose pop
!macroend
!macro UnRegisterExtensionCall _EXTENSION _DESCRIPTION
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Push `${_EXTENSION}`
Push `${_DESCRIPTION}`
${CallArtificialFunction} UnRegisterExtension_
!verbose pop
!macroend
!define RegisterExtension `!insertmacro RegisterExtensionCall`
!define un.RegisterExtension `!insertmacro RegisterExtensionCall`
!macro RegisterExtension
!macroend
!macro un.RegisterExtension
!macroend
!macro RegisterExtension_
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Exch $R2 ;exe
Exch
Exch $R1 ;ext
Exch
Exch 2
Exch $R0 ;desc
Exch 2
Push $0
Push $1
ReadRegStr $1 HKCR $R1 "" ; read current file association
StrCmp "$1" "" NoBackup ; is it empty
StrCmp "$1" "$R0" NoBackup ; is it our own
WriteRegStr HKCR $R1 "backup_val" "$1" ; backup current value
NoBackup:
WriteRegStr HKCR $R1 "" "$R0" ; set our file association
ReadRegStr $0 HKCR $R0 ""
StrCmp $0 "" 0 Skip
WriteRegStr HKCR "$R0" "" "$R0"
WriteRegStr HKCR "$R0\shell" "" "open"
WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,0"
Skip:
WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"'
WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0"
WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"'
Pop $1
Pop $0
Pop $R2
Pop $R1
Pop $R0
!verbose pop
!macroend
!define UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
!define un.UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
!macro UnRegisterExtension
!macroend
!macro un.UnRegisterExtension
!macroend
!macro UnRegisterExtension_
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Exch $R1 ;desc
Exch
Exch $R0 ;ext
Exch
Push $0
Push $1
ReadRegStr $1 HKCR $R0 ""
StrCmp $1 $R1 0 NoOwn ; only do this if we own it
ReadRegStr $1 HKCR $R0 "backup_val"
StrCmp $1 "" 0 Restore ; if backup="" then delete the whole key
DeleteRegKey HKCR $R0
Goto NoOwn
Restore:
WriteRegStr HKCR $R0 "" $1
DeleteRegValue HKCR $R0 "backup_val"
DeleteRegKey HKCR $R1 ;Delete key with association name settings
NoOwn:
Pop $1
Pop $0
Pop $R1
Pop $R0
!verbose pop
!macroend
/*
_____________________________________________________________________________
File Association
_____________________________________________________________________________
Based on code taken from http://nsis.sourceforge.net/File_Association
Usage in script:
1. !include "FileAssociation.nsh"
2. [Section|Function]
${FileAssociationFunction} "Param1" "Param2" "..." $var
[SectionEnd|FunctionEnd]
FileAssociationFunction=[RegisterExtension|UnRegisterExtension]
_____________________________________________________________________________
${RegisterExtension} "[executable]" "[extension]" "[description]"
"[executable]" ; executable which opens the file format
;
"[extension]" ; extension, which represents the file format to open
;
"[description]" ; description for the extension. This will be display in Windows Explorer.
;
${UnRegisterExtension} "[extension]" "[description]"
"[extension]" ; extension, which represents the file format to open
;
"[description]" ; description for the extension. This will be display in Windows Explorer.
;
_____________________________________________________________________________
Macros
_____________________________________________________________________________
Change log window verbosity (default: 3=no script)
Example:
!include "FileAssociation.nsh"
!insertmacro RegisterExtension
${FileAssociation_VERBOSE} 4 # all verbosity
!insertmacro UnRegisterExtension
${FileAssociation_VERBOSE} 3 # no script
*/
!ifndef FileAssociation_INCLUDED
!define FileAssociation_INCLUDED
!include Util.nsh
!verbose push
!verbose 3
!ifndef _FileAssociation_VERBOSE
!define _FileAssociation_VERBOSE 3
!endif
!verbose ${_FileAssociation_VERBOSE}
!define FileAssociation_VERBOSE `!insertmacro FileAssociation_VERBOSE`
!verbose pop
!macro FileAssociation_VERBOSE _VERBOSE
!verbose push
!verbose 3
!undef _FileAssociation_VERBOSE
!define _FileAssociation_VERBOSE ${_VERBOSE}
!verbose pop
!macroend
!macro RegisterExtensionCall _EXECUTABLE _EXTENSION _DESCRIPTION
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Push `${_DESCRIPTION}`
Push `${_EXTENSION}`
Push `${_EXECUTABLE}`
${CallArtificialFunction} RegisterExtension_
!verbose pop
!macroend
!macro UnRegisterExtensionCall _EXTENSION _DESCRIPTION
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Push `${_EXTENSION}`
Push `${_DESCRIPTION}`
${CallArtificialFunction} UnRegisterExtension_
!verbose pop
!macroend
!define RegisterExtension `!insertmacro RegisterExtensionCall`
!define un.RegisterExtension `!insertmacro RegisterExtensionCall`
!macro RegisterExtension
!macroend
!macro un.RegisterExtension
!macroend
!macro RegisterExtension_
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Exch $R2 ;exe
Exch
Exch $R1 ;ext
Exch
Exch 2
Exch $R0 ;desc
Exch 2
Push $0
Push $1
ReadRegStr $1 HKCR $R1 "" ; read current file association
StrCmp "$1" "" NoBackup ; is it empty
StrCmp "$1" "$R0" NoBackup ; is it our own
WriteRegStr HKCR $R1 "backup_val" "$1" ; backup current value
NoBackup:
WriteRegStr HKCR $R1 "" "$R0" ; set our file association
ReadRegStr $0 HKCR $R0 ""
StrCmp $0 "" 0 Skip
WriteRegStr HKCR "$R0" "" "$R0"
WriteRegStr HKCR "$R0\shell" "" "open"
WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,0"
Skip:
WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"'
WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0"
WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"'
Pop $1
Pop $0
Pop $R2
Pop $R1
Pop $R0
!verbose pop
!macroend
!define UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
!define un.UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
!macro UnRegisterExtension
!macroend
!macro un.UnRegisterExtension
!macroend
!macro UnRegisterExtension_
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Exch $R1 ;desc
Exch
Exch $R0 ;ext
Exch
Push $0
Push $1
ReadRegStr $1 HKCR $R0 ""
StrCmp $1 $R1 0 NoOwn ; only do this if we own it
ReadRegStr $1 HKCR $R0 "backup_val"
StrCmp $1 "" 0 Restore ; if backup="" then delete the whole key
DeleteRegKey HKCR $R0
Goto NoOwn
Restore:
WriteRegStr HKCR $R0 "" $1
DeleteRegValue HKCR $R0 "backup_val"
DeleteRegKey HKCR $R1 ;Delete key with association name settings
NoOwn:
Pop $1
Pop $0
Pop $R1
Pop $R0
!verbose pop
!macroend
!endif # !FileAssociation_INCLUDED
@@ -208,6 +208,7 @@ Section "Uninstall"
Delete "$INSTDIR\Qt5Network.dll"
Delete "$INSTDIR\Qt5Multimedia.dll"
Delete "$INSTDIR\Qt5Xml.dll"
Delete "$INSTDIR\Qt5Svg.dll"
Delete "$INSTDIR\avrdude.exe"
Delete "$INSTDIR\avrdude.conf"
Delete "$INSTDIR\libusb0.dll"
@@ -220,7 +221,7 @@ Section "Uninstall"
Delete "$INSTDIR\platforms\*.*"
Delete "$INSTDIR\printsupport\*.*"
Delete "$INSTDIR\mediaservice\*.*"
Delete "$INSTDIR\mediaservice\imageformats\*.*"
Delete "$INSTDIR\imageformats\*.*"
RMDir "$INSTDIR\lang"
RMDir "$INSTDIR\phonon_backend"
+11 -11
View File
@@ -1,12 +1,12 @@
Copyright © 2011-2016 OpenTX team
OpenTX Companion is based on code named eePe by author - Erez Raviv <erezraviv@gmail.com>
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software.
Copyright © 2011-2016 OpenTX team
OpenTX Companion is based on code named eePe by author - Erez Raviv <erezraviv@gmail.com>
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any distribution.

Some files were not shown because too many files have changed in this diff Show More