Compare commits
76 Commits
731566e7d1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 911f169b5e | |||
| 884e8e903e | |||
|
|
0b54793b08 | ||
|
|
b05180f575 | ||
|
|
c3e5092845 | ||
|
|
60706e5e52 | ||
|
|
b9f515950a | ||
| 075aadc665 | |||
| 5db2677d76 | |||
| b40f3cbd14 | |||
|
|
842129931f | ||
| 43508cd698 | |||
| 0389f98ba6 | |||
| c8a088173f | |||
|
|
2192910e8e | ||
|
|
f99c96a855 | ||
| 3410583931 | |||
|
|
0ea9ce2e0f | ||
|
|
afe8588cd3 | ||
|
|
7993247027 | ||
|
|
5a71884cfb | ||
| 1bb800f1e7 | |||
|
|
7647b01d62 | ||
| 37fcc5e888 | |||
|
|
ab4abd214e | ||
| 07c235afa2 | |||
|
|
4f44c588fa | ||
|
|
0d802fcec3 | ||
|
|
8639529bbe | ||
| 4309d2231e | |||
| 093b90fab6 | |||
| 6aec85418a | |||
| c6c058279a | |||
| 291695bcb9 | |||
|
|
95dd9d18e6 | ||
| beae1c1b3d | |||
|
|
c0ce6a81e3 | ||
| 9b1a1233f9 | |||
| 5c919e4d55 | |||
| 25e752e83b | |||
| 9c35c9ea42 | |||
| 6232b560b5 | |||
| d3c62335b1 | |||
| 7780657d82 | |||
| aa4b2a1b84 | |||
| cb553cf928 | |||
| dc3669f513 | |||
| 9f0382965f | |||
| 653aa49a7b | |||
| 2547ed6e1c | |||
| c81c38f780 | |||
| 1fc551d7d1 | |||
| 53b4d6e041 | |||
| 95765226e9 | |||
| d6da7aac9a | |||
| 6b03797600 | |||
|
|
f19a33cc5f | ||
| c40f288aaa | |||
| 23695bc7ef | |||
|
|
3bdc491830 | ||
| 7d43b0a694 | |||
| 407e2e41ed | |||
| 398d50c45c | |||
| 4dd278dbf7 | |||
| be44a70a57 | |||
| a325cc3826 | |||
| 6f5b8d8df6 | |||
| 50c82bca43 | |||
| a8a947ff0b | |||
| 221e0bc8c2 | |||
| e5f7ba569a | |||
| a57b45e21a | |||
| 1a2d815634 | |||
| 6c15d99119 | |||
| c21bb2cf4e | |||
| 5c52b1e936 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -20,3 +20,7 @@ Makefile
|
||||
ui_*
|
||||
|
||||
.qmake.stash
|
||||
.vs/
|
||||
debug/
|
||||
release/
|
||||
BionxControl.qtvscr
|
||||
|
||||
226
.qtcreator/BionxControl.pro.user.23a63a0
Normal file
226
.qtcreator/BionxControl.pro.user.23a63a0
Normal file
@@ -0,0 +1,226 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 19.0.0, 2026-04-01T10:25:51. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{23a63a0b-7f48-446f-a5f4-d5b7f38a6fae}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="qlonglong">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">false</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="RcSync">0</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{fad1a024-ac8c-47cf-928f-6229932645bf}</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">./build/%{Asciify:%{Kit:FileSystemName}-%{BuildConfig:Name}}</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">build/Desktop-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/mnt/c/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/mnt/c/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="qlonglong">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
860
.qtcreator/BionxControl.pro.user.628da39
Normal file
860
.qtcreator/BionxControl.pro.user.628da39
Normal file
@@ -0,0 +1,860 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 19.0.0, 2026-03-30T17:25:48. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{628da395-74db-4105-8489-c4b4db698d13}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="qlonglong">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="RcSync">0</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.11.0 MinGW 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.11.0 MinGW 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.6110.win64_mingw_kit</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\projects\BionxControl\build\Desktop_Qt_6_11_0_MinGW_64_bit-Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/projects/BionxControl/build/Desktop_Qt_6_11_0_MinGW_64_bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.11.0 MSVC2022 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.11.0 MSVC2022 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.6110.win64_msvc2022_64_kit</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\projects\BionxControl\build\Desktop_Qt_6_11_0_MSVC2022_64bit-Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/projects/BionxControl/build/Desktop_Qt_6_11_0_MSVC2022_64bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.11.0 llvm-mingw 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.11.0 llvm-mingw 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.6110.win64_llvm_mingw_kit</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\projects\BionxControl\build\Desktop_Qt_6_11_0_llvm_mingw_64_bit-Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/projects/BionxControl/build/Desktop_Qt_6_11_0_llvm_mingw_64_bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.SuppressionFiles"/>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.3</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.10.1 MinGW 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.10.1 MinGW 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.6101.win64_mingw_kit</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\projects\BionxControl\build\Desktop_Qt_6_10_1_MinGW_64_bit-Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/projects/BionxControl/build/Desktop_Qt_6_10_1_MinGW_64_bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.4</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.10.1 llvm-mingw 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.10.1 llvm-mingw 64-bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.6101.win64_llvm_mingw_kit</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\projects\BionxControl\build\Desktop_Qt_6_10_1_llvm_mingw_64_bit-Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/projects/BionxControl/build/Desktop_Qt_6_10_1_llvm_mingw_64_bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.5</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.10.1 MSVC2022 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.10.1 MSVC2022 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.6101.win64_msvc2022_64_kit</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\projects\BionxControl\build\Desktop_Qt_6_10_1_MSVC2022_64bit-Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/projects/BionxControl/build/Desktop_Qt_6_10_1_MSVC2022_64bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/projects/BionxControl/BionxControl.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="qlonglong">6</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -1,59 +1,31 @@
|
||||
QT += core gui svg
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
QT += core gui svg widgets
|
||||
|
||||
CONFIG += c++23
|
||||
|
||||
QMAKE_CXXFLAGS += -std=c++23
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
INCLUDEPATH += . libwin
|
||||
|
||||
linux:contains(QT_ARCH, arm.*)
|
||||
{
|
||||
message("Konfiguration für Raspberry Pi (ARM) erkannt.")
|
||||
|
||||
# 1. Header-Dateien (z.B. für bcm2835.h oder eigene Treiber)
|
||||
#INCLUDEPATH += /usr/local/include \
|
||||
# /home/pi/my_custom_drivers/include
|
||||
|
||||
# not used at the moment
|
||||
# 2. Bibliotheken linken
|
||||
# -L sagt dem Linker WO er suchen soll
|
||||
# -l sagt dem Linker WAS er nehmen soll (z.B. libwiringPi.so -> -lwiringPi)
|
||||
#LIBS += -L/usr/lib \
|
||||
# -lmhstcan
|
||||
|
||||
|
||||
# Optional: Spezielle Compiler-Flags für den Pi (Optimierung)
|
||||
#QMAKE_CXXFLAGS += -O3
|
||||
}
|
||||
|
||||
li
|
||||
|
||||
windows
|
||||
{
|
||||
#LIBS += -L$$PWD/can_api -lmhstcan -lAdvapi32
|
||||
}
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
aalegacy.cpp \
|
||||
bc.cpp \
|
||||
bcanimateddelegate.cpp \
|
||||
bcdelightpmwidget.cpp \
|
||||
bcdeviceview.cpp \
|
||||
bcdriver.cpp \
|
||||
bcdriverstatewidget.cpp \
|
||||
bcdrivertinycan.cpp \
|
||||
bcguihelpers.cpp \
|
||||
bcthemebutton.cpp \
|
||||
bctoggleswitch.cpp \
|
||||
bctransmitter.cpp \
|
||||
bcvalue.cpp \
|
||||
bcvaluedelegate.cpp \
|
||||
bcvaluemodel.cpp \
|
||||
bcvalueslider.cpp \
|
||||
bcxmlloader.cpp \
|
||||
libwin/can_drv_win.c \
|
||||
libwin/mhs_can_drv.c \
|
||||
@@ -62,19 +34,24 @@ SOURCES += \
|
||||
|
||||
HEADERS += \
|
||||
bc.h \
|
||||
bcanimateddelegate.h \
|
||||
bcdelightpmwidget.h \
|
||||
bcdeviceview.h \
|
||||
bcdriver.h \
|
||||
bcdriverstatewidget.h \
|
||||
bcdrivertinycan.h \
|
||||
bcguihelpers.h \
|
||||
bcmainwindow.h \
|
||||
bcthemebutton.h \
|
||||
bctoggleswitch.h \
|
||||
bctransmitter.h \
|
||||
bcvalue.h \
|
||||
bcvaluedelegate.h \
|
||||
bcvaluemodel.h \
|
||||
bcvalueslider.h \
|
||||
bcxmlloader.h
|
||||
|
||||
FORMS += \
|
||||
bcmainwindow.ui
|
||||
bcmainwindow.ui \
|
||||
bcvalueslider.ui
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
|
||||
6
BionxControl.slnx
Normal file
6
BionxControl.slnx
Normal file
@@ -0,0 +1,6 @@
|
||||
<Solution>
|
||||
<Configurations>
|
||||
<Platform Name="x64" />
|
||||
</Configurations>
|
||||
<Project Path="BionxControl.vcxproj" Id="84c4d2da-be54-3c31-bef9-6bccdd5c3277" />
|
||||
</Solution>
|
||||
293
BionxControl.vcxproj
Normal file
293
BionxControl.vcxproj
Normal file
@@ -0,0 +1,293 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{84C4D2DA-BE54-3C31-BEF9-6BCCDD5C3277}</ProjectGuid>
|
||||
<RootNamespace>BionxControl</RootNamespace>
|
||||
<Keyword>QtVS_v304</Keyword>
|
||||
<QtMsBuild Condition="'$(QtMsBuild)'=='' OR !Exists('$(QtMsBuild)\qt.targets')">$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<OutputDirectory>release\</OutputDirectory>
|
||||
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<IntermediateDirectory>release\</IntermediateDirectory>
|
||||
<PrimaryOutput>BionxControl</PrimaryOutput>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<OutputDirectory>debug\</OutputDirectory>
|
||||
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<IntermediateDirectory>debug\</IntermediateDirectory>
|
||||
<PrimaryOutput>BionxControl</PrimaryOutput>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(QtMsBuild)\qt_defaults.props" Condition="Exists('$(QtMsBuild)\qt_defaults.props')" />
|
||||
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<QtInstall>msvc2022x64Qt6</QtInstall>
|
||||
<QtModules>core;gui;widgets;svg</QtModules>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<QtInstall>msvc2022x64Qt6</QtInstall>
|
||||
<QtModules>core;gui;widgets;svg</QtModules>
|
||||
</PropertyGroup>
|
||||
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') OR !Exists('$(QtMsBuild)\Qt.props')">
|
||||
<Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
|
||||
</Target>
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
<Import Project="$(QtMsBuild)\Qt.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
|
||||
<Import Project="$(QtMsBuild)\Qt.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">release\</IntDir>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">BionxControl</TargetName>
|
||||
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">debug\</IntDir>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">BionxControl</TargetName>
|
||||
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>GeneratedFiles\$(ConfigurationName);GeneratedFiles;.;libwin;..\..\Qt\6.11.0\msvc2022_64\include;..\..\Qt\6.11.0\msvc2022_64\include\QtSvg;..\..\Qt\6.11.0\msvc2022_64\include\QtWidgets;..\..\Qt\6.11.0\msvc2022_64\include\QtGui;..\..\Qt\6.11.0\msvc2022_64\include\QtCore;release;/include;..\..\Qt\6.11.0\msvc2022_64\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -utf-8 -w34100 -w34189 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AssemblerListingLocation>release\</AssemblerListingLocation>
|
||||
<BrowseInformation>false</BrowseInformation>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<ObjectFileName>release\</ObjectFileName>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessToFile>false</PreprocessToFile>
|
||||
<ProgramDataBaseFileName>
|
||||
</ProgramDataBaseFileName>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<UseFullPaths>false</UseFullPaths>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>C:\Qt\6.11.0\msvc2022_64\lib\Qt6EntryPoint.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<OutputFile>$(OutDir)\BionxControl.exe</OutputFile>
|
||||
<RandomizedBaseAddress>true</RandomizedBaseAddress>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
</Link>
|
||||
<Midl>
|
||||
<DefaultCharType>Unsigned</DefaultCharType>
|
||||
<EnableErrorChecks>None</EnableErrorChecks>
|
||||
<WarningLevel>0</WarningLevel>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<QtMoc>
|
||||
<CompilerFlavor>msvc</CompilerFlavor>
|
||||
<Include>C:/projects/BionxControl/$(Configuration)/moc_predefs.h</Include>
|
||||
<ExecutionDescription>Moc'ing %(Identity)...</ExecutionDescription>
|
||||
<DynamicSource>output</DynamicSource>
|
||||
<QtMocDir>$(Configuration)</QtMocDir>
|
||||
<QtMocFileName>moc_%(Filename).cpp</QtMocFileName>
|
||||
</QtMoc>
|
||||
<QtRcc>
|
||||
<InitFuncName>bionxcontrol</InitFuncName>
|
||||
<Compression>default</Compression>
|
||||
<NoZstd>true</NoZstd>
|
||||
<ExecutionDescription>Rcc'ing %(Identity)...</ExecutionDescription>
|
||||
<QtRccDir>$(Configuration)</QtRccDir>
|
||||
<QtRccFileName>qrc_%(Filename).cpp</QtRccFileName>
|
||||
</QtRcc>
|
||||
<QtUic>
|
||||
<ExecutionDescription>Uic'ing %(Identity)...</ExecutionDescription>
|
||||
<QtUicDir>$(ProjectDir)</QtUicDir>
|
||||
<QtUicFileName>ui_%(Filename).h</QtUicFileName>
|
||||
</QtUic>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>GeneratedFiles\$(ConfigurationName);GeneratedFiles;.;libwin;..\..\Qt\6.11.0\msvc2022_64\include;..\..\Qt\6.11.0\msvc2022_64\include\QtSvg;..\..\Qt\6.11.0\msvc2022_64\include\QtWidgets;..\..\Qt\6.11.0\msvc2022_64\include\QtGui;..\..\Qt\6.11.0\msvc2022_64\include\QtCore;debug;/include;..\..\Qt\6.11.0\msvc2022_64\mkspecs\win32-msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -utf-8 -w34100 -w34189 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AssemblerListingLocation>debug\</AssemblerListingLocation>
|
||||
<BrowseInformation>false</BrowseInformation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<ObjectFileName>debug\</ObjectFileName>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessToFile>false</PreprocessToFile>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<UseFullPaths>false</UseFullPaths>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>C:\Qt\6.11.0\msvc2022_64\lib\Qt6EntryPointd.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<OutputFile>$(OutDir)\BionxControl.exe</OutputFile>
|
||||
<RandomizedBaseAddress>true</RandomizedBaseAddress>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
</Link>
|
||||
<Midl>
|
||||
<DefaultCharType>Unsigned</DefaultCharType>
|
||||
<EnableErrorChecks>None</EnableErrorChecks>
|
||||
<WarningLevel>0</WarningLevel>
|
||||
</Midl>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<QtMoc>
|
||||
<CompilerFlavor>msvc</CompilerFlavor>
|
||||
<Include>C:/projects/BionxControl/$(Configuration)/moc_predefs.h</Include>
|
||||
<ExecutionDescription>Moc'ing %(Identity)...</ExecutionDescription>
|
||||
<DynamicSource>output</DynamicSource>
|
||||
<QtMocDir>$(Configuration)</QtMocDir>
|
||||
<QtMocFileName>moc_%(Filename).cpp</QtMocFileName>
|
||||
</QtMoc>
|
||||
<QtRcc>
|
||||
<InitFuncName>bionxcontrol</InitFuncName>
|
||||
<Compression>default</Compression>
|
||||
<NoZstd>true</NoZstd>
|
||||
<ExecutionDescription>Rcc'ing %(Identity)...</ExecutionDescription>
|
||||
<QtRccDir>$(Configuration)</QtRccDir>
|
||||
<QtRccFileName>qrc_%(Filename).cpp</QtRccFileName>
|
||||
</QtRcc>
|
||||
<QtUic>
|
||||
<ExecutionDescription>Uic'ing %(Identity)...</ExecutionDescription>
|
||||
<QtUicDir>$(ProjectDir)</QtUicDir>
|
||||
<QtUicFileName>ui_%(Filename).h</QtUicFileName>
|
||||
</QtUic>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bc.cpp" />
|
||||
<ClCompile Include="bcdelightpmwidget.cpp" />
|
||||
<ClCompile Include="bcdeviceview.cpp" />
|
||||
<ClCompile Include="bcdriver.cpp" />
|
||||
<ClCompile Include="bcdriverstatewidget.cpp" />
|
||||
<ClCompile Include="bcdrivertinycan.cpp" />
|
||||
<ClCompile Include="bcmainwindow.cpp" />
|
||||
<ClCompile Include="bcthemeswitchbutton.cpp" />
|
||||
<ClCompile Include="bctoggleswitch.cpp" />
|
||||
<ClCompile Include="bctransmitter.cpp" />
|
||||
<ClCompile Include="bcvalue.cpp" />
|
||||
<ClCompile Include="bcvaluedelegate.cpp" />
|
||||
<ClCompile Include="bcvaluemodel.cpp" />
|
||||
<ClCompile Include="bcvalueslider.cpp" />
|
||||
<ClCompile Include="bcxmlloader.cpp" />
|
||||
<ClCompile Include="libwin\can_drv_win.c" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="bc.h" />
|
||||
<QtMoc Include="bcdelightpmwidget.h" />
|
||||
<QtMoc Include="bcdeviceview.h" />
|
||||
<QtMoc Include="bcdriver.h" />
|
||||
<QtMoc Include="bcdriverstatewidget.h" />
|
||||
<ClInclude Include="bcdrivertinycan.h" />
|
||||
<QtMoc Include="bcmainwindow.h" />
|
||||
<QtMoc Include="bcthemeswitchbutton.h" />
|
||||
<QtMoc Include="bctoggleswitch.h" />
|
||||
<QtMoc Include="bctransmitter.h" />
|
||||
<QtMoc Include="bcvalue.h" />
|
||||
<QtMoc Include="bcvaluedelegate.h" />
|
||||
<QtMoc Include="bcvaluemodel.h" />
|
||||
<QtMoc Include="bcvalueslider.h" />
|
||||
<QtMoc Include="bcxmlloader.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||
<FileType>Document</FileType>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\Qt\6.11.0\msvc2022_64\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -BxC:\Qt\6.11.0\msvc2022_64\bin\qmake.exe -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -Zi -MDd -std:c++latest -utf-8 -W3 -w34100 -w34189 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E ..\..\Qt\6.11.0\msvc2022_64\mkspecs\features\data\dummy.cpp 2>NUL >$(IntDir)\moc_predefs.h</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generate moc_predefs.h</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)\moc_predefs.h;%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="release\moc_predefs.h.cbt">
|
||||
<FileType>Document</FileType>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\Qt\6.11.0\msvc2022_64\mkspecs\features\data\dummy.cpp;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -BxC:\Qt\6.11.0\msvc2022_64\bin\qmake.exe -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -O2 -MD -std:c++latest -utf-8 -W3 -w34100 -w34189 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E ..\..\Qt\6.11.0\msvc2022_64\mkspecs\features\data\dummy.cpp 2>NUL >$(IntDir)\moc_predefs.h</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generate moc_predefs.h</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)\moc_predefs.h;%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="bcmainwindow.ui" />
|
||||
<QtUic Include="bcvalueslider.ui" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="resources\bc_dark.qss" />
|
||||
<None Include="resources\bc_light.qss" />
|
||||
<None Include="resources\bikeinfo.xml" />
|
||||
<None Include="resources\bionx_akku.png" />
|
||||
<None Include="resources\bionx_console.png" />
|
||||
<None Include="resources\bionx_motor.png" />
|
||||
<QtRcc Include="bionxcontrol.qrc" />
|
||||
<None Include="resources\connect.png" />
|
||||
<None Include="resources\exit.png" />
|
||||
<None Include="resources\exit_red.png" />
|
||||
<None Include="resources\smile\face-angel.png" />
|
||||
<None Include="resources\smile\face-angry.png" />
|
||||
<None Include="resources\smile\face-cool.png" />
|
||||
<None Include="resources\smile\face-crying.png" />
|
||||
<None Include="resources\smile\face-embarrassed.png" />
|
||||
<None Include="resources\smile\face-glasses.png" />
|
||||
<None Include="resources\smile\face-kiss.png" />
|
||||
<None Include="resources\smile\face-laugh.png" />
|
||||
<None Include="resources\smile\face-monkey.png" />
|
||||
<None Include="resources\smile\face-plain.png" />
|
||||
<None Include="resources\smile\face-raspberry.png" />
|
||||
<None Include="resources\smile\face-sad.png" />
|
||||
<None Include="resources\smile\face-sick.png" />
|
||||
<None Include="resources\smile\face-smile-big.png" />
|
||||
<None Include="resources\smile\face-smile.png" />
|
||||
<None Include="resources\smile\face-smirk.png" />
|
||||
<None Include="resources\smile\face-surprise.png" />
|
||||
<None Include="resources\sync.png" />
|
||||
<None Include="resources\sync_green.png" />
|
||||
<None Include="resources\sync_yellow.png" />
|
||||
<None Include="resources\update.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(QtMsBuild)\qt.targets" Condition="Exists('$(QtMsBuild)\qt.targets')" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
260
BionxControl.vcxproj.filters
Normal file
260
BionxControl.vcxproj.filters
Normal file
@@ -0,0 +1,260 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Form Files">
|
||||
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
|
||||
<Extensions>ui</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Form Files">
|
||||
<UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
|
||||
<Extensions>ui</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;moc;h;def;odl;idl;res;</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
|
||||
<Extensions>qrc;*</Extensions>
|
||||
<ParseFiles>false</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcdelightpmwidget.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcdeviceview.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcdriver.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcdriverstatewidget.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcdrivertinycan.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcmainwindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcthemeswitchbutton.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bctoggleswitch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bctransmitter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcvalue.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcvaluedelegate.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcvaluemodel.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcvalueslider.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="bcxmlloader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libwin\can_drv_win.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="bc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcdelightpmwidget.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcdeviceview.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcdriver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcdriverstatewidget.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<ClInclude Include="bcdrivertinycan.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<QtMoc Include="bcmainwindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcthemeswitchbutton.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bctoggleswitch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bctransmitter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcvalue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcvaluedelegate.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcvaluemodel.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcvalueslider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="bcxmlloader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||
<Filter>Generated Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="release\moc_predefs.h.cbt">
|
||||
<Filter>Generated Files</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="bcmainwindow.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</QtUic>
|
||||
<QtUic Include="bcvalueslider.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</QtUic>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="resources\bc_dark.qss">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\bc_light.qss">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\bikeinfo.xml">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\bionx_akku.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\bionx_console.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\bionx_motor.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<QtRcc Include="bionxcontrol.qrc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</QtRcc>
|
||||
<None Include="resources\connect.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\exit.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\exit_red.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-angel.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-angry.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-cool.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-crying.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-embarrassed.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-glasses.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-kiss.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-laugh.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-monkey.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-plain.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-raspberry.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-sad.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-sick.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-smile-big.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-smile.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-smirk.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\smile\face-surprise.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\sync.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\sync_green.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\sync_yellow.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources\update.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
21
BionxControl.vcxproj.user
Normal file
21
BionxControl.vcxproj.user
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\Qt\6.11.0\msvc2022_64\bin;%PATH%
|
||||
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\Qt\6.11.0\msvc2022_64\bin;%PATH%
|
||||
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<QtTouchProperty>
|
||||
</QtTouchProperty>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<QtTouchProperty>
|
||||
</QtTouchProperty>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
137
CMakeLists.txt
Normal file
137
CMakeLists.txt
Normal file
@@ -0,0 +1,137 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(BionxControl VERSION 1.0 LANGUAGES C CXX)
|
||||
# --- C++23 aktivieren ---
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# set(CMAKE_CXX_EXTENSIONS OFF) # Optional: Auf OFF setzen, wenn du reines C++23 statt GNU++23 erzwingen willst
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Gui Svg Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(BionxControl WIN32 MACOSX_BUNDLE
|
||||
bc.cpp bc.h
|
||||
bcdelightpmwidget.cpp bcdelightpmwidget.h
|
||||
bcdeviceview.cpp bcdeviceview.h
|
||||
bcdriver.cpp bcdriver.h
|
||||
bcdriverstatewidget.cpp bcdriverstatewidget.h
|
||||
bcdrivertinycan.cpp bcdrivertinycan.h
|
||||
bcmainwindow.cpp bcmainwindow.h bcmainwindow.ui
|
||||
bcthemebutton.cpp bcthemebutton.h
|
||||
bctoggleswitch.cpp bctoggleswitch.h
|
||||
bctransmitter.cpp bctransmitter.h
|
||||
bcvalue.cpp bcvalue.h
|
||||
bcvaluedelegate.cpp bcvaluedelegate.h
|
||||
bcvaluemodel.cpp bcvaluemodel.h
|
||||
bcvalueslider.cpp bcvalueslider.h bcvalueslider.ui
|
||||
bcxmlloader.cpp bcxmlloader.h
|
||||
main.cpp
|
||||
)
|
||||
|
||||
# Plattformspezifische CAN-Treiber einbinden
|
||||
if(WIN32)
|
||||
target_sources(BionxControl PRIVATE libwin/can_drv_win.c)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
target_sources(BionxControl PRIVATE libwin/mhs_can_drv.c)
|
||||
endif()
|
||||
|
||||
target_include_directories(BionxControl PRIVATE
|
||||
.
|
||||
libwin
|
||||
)
|
||||
|
||||
target_link_libraries(BionxControl PRIVATE
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
Qt::Svg
|
||||
Qt::Widgets
|
||||
)
|
||||
|
||||
|
||||
# Resources:
|
||||
set_source_files_properties("resources/bc_dark.qss"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "bc_dark.qss"
|
||||
)
|
||||
set_source_files_properties("resources/bc_light.qss"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "bc_light.qss"
|
||||
)
|
||||
set_source_files_properties("resources/bikeinfo.xml"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "bikeinfo.xml"
|
||||
)
|
||||
set_source_files_properties("resources/bionx_akku.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "bionx_akku.png"
|
||||
)
|
||||
set_source_files_properties("resources/bionx_console.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "bionx_console.png"
|
||||
)
|
||||
set_source_files_properties("resources/bionx_motor.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "bionx_motor.png"
|
||||
)
|
||||
set_source_files_properties("resources/connect.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "connect.png"
|
||||
)
|
||||
set_source_files_properties("resources/exit.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "exit.png"
|
||||
)
|
||||
set_source_files_properties("resources/exit_red.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "exit_red.png"
|
||||
)
|
||||
set_source_files_properties("resources/sync.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "sync.png"
|
||||
)
|
||||
set_source_files_properties("resources/sync_green.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "sync_green.png"
|
||||
)
|
||||
set_source_files_properties("resources/sync_yellow.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "sync_yellow.png"
|
||||
)
|
||||
set_source_files_properties("resources/update.png"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "update.png"
|
||||
)
|
||||
set(bionxcontrol_resource_files
|
||||
"resources/bc_dark.qss"
|
||||
"resources/bc_light.qss"
|
||||
"resources/bikeinfo.xml"
|
||||
"resources/bionx_akku.png"
|
||||
"resources/bionx_console.png"
|
||||
"resources/bionx_motor.png"
|
||||
"resources/connect.png"
|
||||
"resources/exit.png"
|
||||
"resources/exit_red.png"
|
||||
"resources/smile/face-angel.png"
|
||||
"resources/smile/face-angry.png"
|
||||
"resources/smile/face-cool.png"
|
||||
"resources/smile/face-crying.png"
|
||||
"resources/smile/face-embarrassed.png"
|
||||
"resources/smile/face-glasses.png"
|
||||
"resources/smile/face-kiss.png"
|
||||
"resources/smile/face-laugh.png"
|
||||
"resources/smile/face-monkey.png"
|
||||
"resources/smile/face-plain.png"
|
||||
"resources/smile/face-raspberry.png"
|
||||
"resources/smile/face-sad.png"
|
||||
"resources/smile/face-sick.png"
|
||||
"resources/smile/face-smile-big.png"
|
||||
"resources/smile/face-smile.png"
|
||||
"resources/smile/face-smirk.png"
|
||||
"resources/smile/face-surprise.png"
|
||||
"resources/sync.png"
|
||||
"resources/sync_green.png"
|
||||
"resources/sync_yellow.png"
|
||||
"resources/update.png"
|
||||
)
|
||||
|
||||
qt_add_resources(BionxControl "bionxcontrol"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${bionxcontrol_resource_files}
|
||||
)
|
||||
|
||||
install(TARGETS BionxControl
|
||||
BUNDLE DESTINATION .
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
36
Dockerfile
Normal file
36
Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
||||
# Wir nutzen Debian Trixie als Basis für das aktuelle Raspberry Pi OS
|
||||
FROM debian:trixie
|
||||
|
||||
# Verhindert interaktive Prompts während der Installation
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# 1. Multiarch für armhf aktivieren
|
||||
RUN dpkg --add-architecture armhf && \
|
||||
apt-get update && \
|
||||
apt-get upgrade -y
|
||||
|
||||
# 2. Host-Build-Tools und Cross-Compiler für 32-Bit installieren
|
||||
RUN apt-get install -y \
|
||||
build-essential \
|
||||
crossbuild-essential-armhf \
|
||||
cmake \
|
||||
ninja-build \
|
||||
git \
|
||||
pkg-config
|
||||
|
||||
# 3. Qt6 für den HOST installieren (für moc, uic, etc.)
|
||||
RUN apt-get install -y \
|
||||
qt6-base-dev \
|
||||
qt6-tools-dev-tools \
|
||||
qt6-svg-dev
|
||||
|
||||
# 4. Qt6 Bibliotheken für das TARGET (armhf) installieren
|
||||
RUN apt-get install -y \
|
||||
qt6-base-dev:armhf \
|
||||
libglvnd-dev:armhf \
|
||||
qt6-svg-dev:armhf
|
||||
|
||||
# Aufräumen
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /workspace
|
||||
744
aalegacy.cpp
744
aalegacy.cpp
@@ -1,744 +0,0 @@
|
||||
/* BigXionFlasher.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2011-2013 by Thomas König <info@bigxionflasher.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* BigXionFlasher Project. (http://www.bigxionflasher.org/)"
|
||||
*
|
||||
* 4. The name "BigXionFlasher" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* info@bigxionflasher.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "BigXionFlasher"
|
||||
* nor may "BigXionFlasher" appear in their names without prior written
|
||||
* permission of the BigXionFlasher Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* BigXionFlasher Project. (http://www.bigxionflasher.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE BigXionFlasher PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE BigXionFlasher PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* 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 OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#ifdef __WIN32__
|
||||
#include <conio.h>
|
||||
#define DEVICE_OPEN NULL
|
||||
#define TREIBER_NAME "mhstcan.dll"
|
||||
#define _NL "\n\r"
|
||||
#define _DEGREE_SIGN "o"
|
||||
#else
|
||||
#define DEVICE_OPEN NULL
|
||||
#define TREIBER_NAME "libmhstcan.so"
|
||||
#define _NL "\n"
|
||||
#define _DEGREE_SIGN "°"
|
||||
#endif
|
||||
#include "can_drv.h"
|
||||
|
||||
#define __DOSTR(v) #v
|
||||
#define __STR(v) __DOSTR(v)
|
||||
|
||||
#define __BXF_VERSION__ "V 0.2.4 rev. 97"
|
||||
|
||||
#define UNLIMITED_SPEED_VALUE 70 /* Km/h */
|
||||
#define UNLIMITED_MIN_SPEED_VALUE 30 /* Km/h */
|
||||
#define MAX_THROTTLE_SPEED_VALUE 70 /* Km/h */
|
||||
|
||||
//#include "registers.h"
|
||||
|
||||
#define TIMEOUT_VALUE 80
|
||||
#define TIMEOUT_US 10000 // 10ms
|
||||
|
||||
|
||||
|
||||
#define BATTERY_REF_HW 1
|
||||
#define BATTERY_REF_SW 1
|
||||
#define BATTERY_SN_PN_HI 1
|
||||
#define BATTERY_SN_PN_LO 1
|
||||
#define BATTERY_SN_ITEM_HI 1
|
||||
#define BATTERY_SN_ITEM_LO 1
|
||||
#define BATTERY_STATUS_VBATT_HI 1
|
||||
#define BATTERY_STATUS_VBATT_LO 1
|
||||
#define BATTERY_STATUS_LEVEL 1
|
||||
#define BATTERY_STATS_VBATTMAX 1
|
||||
#define BATTERY_STATS_VBATTMIN 1
|
||||
#define BATTERY_STATS_VBATTMEA 1
|
||||
#define BATTERY_STATS_VBATTMEAN 1
|
||||
#define BATTERY_STATS_RESET_HI 1
|
||||
#define BATTERY_STATS_RESET_LO 1
|
||||
#define BATTERY_STSTS_GGJSRCALIB 1
|
||||
|
||||
#define BATTERY_STSTS_VCTRLSHORTS 1
|
||||
#define BATTERY_STATS_LMD_HI 1
|
||||
#define BATTERY_STATS_LMD_LO 1
|
||||
#define BATTERY_CONFIG_CELLCAPACITY_HI 1
|
||||
#define BATTERY_CONFIG_CELLCAPACITY_LO 1
|
||||
|
||||
#define BATTERY_STATS_CHARGETIMEWORST_HI 1
|
||||
#define BATTERY_STATS_CHARGETIMEWORST_LO 1
|
||||
#define BATTERY_STATS_CHARGETIMEMEAN_HI 1
|
||||
#define BATTERY_STATS_CHARGETIMEMEAN_LO 1
|
||||
#define BATTERY_STATS_BATTCYCLES_HI 1
|
||||
#define BATTERY_STATS_BATTCYCLES_LO 1
|
||||
#define BATTERY_STATS_BATTFULLCYCLES_HI 1
|
||||
#define BATTERY_STATS_BATTFULLCYCLES_LO 1
|
||||
#define BATTERY_STATS_POWERCYCLES_HI 1
|
||||
#define BATTERY_STATS_POWERCYCLES_LO 1
|
||||
|
||||
#define BATTERY_STATS_TBATTMAX 1
|
||||
#define BATTERY_STATS_TBATTMIN 1
|
||||
#define MOTOR_REF_HW 1
|
||||
#define MOTOR_REF_SW 1
|
||||
#define MOTOR_REALTIME_TEMP 1
|
||||
#define MOTOR_SN_PN_HI 1
|
||||
#define MOTOR_SN_PN_LO 1
|
||||
#define MOTOR_SN_ITEM_HI 1
|
||||
#define MOTOR_SN_ITEM_LO 1
|
||||
|
||||
#define CONSOLE_STATUS_SLAVE 1
|
||||
#define BATTERY_CONFIG_SHUTDOWN 1
|
||||
|
||||
#define CONSOLE_ASSIST_MAXSPEEDFLAG 1
|
||||
#define CONSOLE_ASSIST_MAXSPEED_HI 1
|
||||
#define CONSOLE_ASSIST_MAXSPEED_LO 1
|
||||
#define MOTOR_PROTECT_UNLOCK 1
|
||||
#define MOTOR_PROTECT_UNLOCK_KEY 1
|
||||
#define MOTOR_ASSIST_MAXSPEED 1
|
||||
#define CONSOLE_GEOMETRY_CIRC_HI 1
|
||||
#define CONSOLE_GEOMETRY_CIRC_LO1
|
||||
|
||||
#define CONSOLE_GEOMETRY_CIRC_LO 1
|
||||
#define MOTOR_GEOMETRY_CIRC_HI1
|
||||
#define MOTOR_GEOMETRY_CIRC_HI 1
|
||||
#define MOTOR_GEOMETRY_CIRC_LO 1
|
||||
#define CONSOLE_ASSIST_MINSPEEDFLAG 1
|
||||
#define CONSOLE_ASSIST_MINSPEED 1
|
||||
|
||||
#define CONSOLE_THROTTLE_MAXSPEEDFLAG 1
|
||||
#define CONSOLE_THROTTLE_MAXSPEED_HI 1
|
||||
#define CONSOLE_THROTTLE_MAXSPEED_LO 1
|
||||
|
||||
#define BATTERY_CONFIG_PACKSERIAL 1
|
||||
#define BATTERY_CELLMON_BALANCERENABLED 1
|
||||
#define BATTERY_CONFIG_PACKPARALLEL 1
|
||||
#define BATTERY_CELLMON_CHANNELADDR 1
|
||||
#define BATTERY_CELLMON_CHANNELDATA_HI 1
|
||||
|
||||
#define BATTERY_STATUS_PACKTEMPERATURE1 1
|
||||
|
||||
#define BATTERY_CELLMON_CHANNELDATA_LO 1
|
||||
|
||||
#define CONSOLE_REF_HW 1
|
||||
#define CONSOLE_REF_SW 1
|
||||
#define CONSOLE_ASSIST_INITLEVEL 1
|
||||
#define CONSOLE_SN_PN_HI 1
|
||||
#define CONSOLE_SN_PN_LO 1
|
||||
#define CONSOLE_SN_ITEM_HI 1
|
||||
#define CONSOLE_SN_ITEM_LO 1
|
||||
#define CONSOLE_ASSIST_MOUNTAINCAP 1
|
||||
#define CONSOLE_STATS_BCValueTypeWord_1 1
|
||||
#define CONSOLE_STATS_BCValueTypeWord_2 1
|
||||
#define CONSOLE_STATS_BCValueTypeWord_3 1
|
||||
|
||||
#define CONSOLE_STATS_BCValueTypeWord_4 1
|
||||
|
||||
#define doSleep(x) usleep(x*1000)
|
||||
|
||||
int gAssistInitLevel = -1, gPrintSystemSettings = 0, gSkipShutdown = 0, gPowerOff = 0, gConsoleSetSlaveMode = 1, gNoSerialNumbers = 0, gSetMountainCap = -1, gSetWheelCircumference = 0;
|
||||
double gSetSpeedLimit = -1, gSetMinSpeedLimit = -1, gSetThrottleSpeedLimit = -1;
|
||||
|
||||
#define CONSOLE 1
|
||||
#define MOTOR 2
|
||||
#define BATTERY 3
|
||||
#define BIB 4
|
||||
|
||||
|
||||
|
||||
char *getNodeName(unsigned char id)
|
||||
{
|
||||
if (id == CONSOLE)
|
||||
return "console";
|
||||
else if (id == BATTERY)
|
||||
return "battery";
|
||||
else if (id == MOTOR)
|
||||
return "motor";
|
||||
else if (id == BIB)
|
||||
return "bib";
|
||||
else
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
void setValue(unsigned char receipient, unsigned char reg, unsigned char value)
|
||||
{
|
||||
struct TCanMsg msg;
|
||||
int timeout = TIMEOUT_VALUE;
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = receipient;
|
||||
msg.MsgLen = 4;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = reg;
|
||||
msg.MsgData[2] = 0x00;
|
||||
msg.MsgData[3] = value;
|
||||
|
||||
CanTransmit(0, &msg, 1);
|
||||
|
||||
while(timeout-- && CanTransmitGetCount(0))
|
||||
usleep(TIMEOUT_US);
|
||||
|
||||
if (timeout == -1)
|
||||
printf("error: could not send value to %s" _NL, getNodeName(receipient));
|
||||
}
|
||||
|
||||
unsigned int getValue(unsigned char receipient, unsigned char reg)
|
||||
{
|
||||
struct TCanMsg msg;
|
||||
int err, retry = 20;
|
||||
int timeout = TIMEOUT_VALUE;
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = receipient;
|
||||
msg.MsgLen = 2;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = reg;
|
||||
|
||||
CanTransmit(0, &msg, 1);
|
||||
|
||||
while(timeout-- && CanTransmitGetCount(0))
|
||||
usleep(TIMEOUT_US);
|
||||
|
||||
if (timeout == -1)
|
||||
printf("error: could not send value to node %s" _NL, getNodeName(receipient));
|
||||
|
||||
retry:
|
||||
|
||||
timeout = TIMEOUT_VALUE;
|
||||
while(timeout-- && !CanReceiveGetCount(0))
|
||||
usleep(TIMEOUT_US);
|
||||
|
||||
if (timeout == -1)
|
||||
{
|
||||
printf("error: no response from node %s" _NL, getNodeName(receipient));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((err = CanReceive(0, &msg, 1)) > 0)
|
||||
{
|
||||
if (--retry && (msg.Id != BIB || msg.MsgLen != 4 || msg.MsgData[1] != reg))
|
||||
goto retry;
|
||||
|
||||
if (!retry)
|
||||
{
|
||||
printf("error: no response from node %s to %s" _NL, getNodeName(receipient), getNodeName(BIB));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (unsigned int) msg.MsgData[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %d" _NL, err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void setSpeedLimit(double speed)
|
||||
{
|
||||
int limit = (speed != 0);
|
||||
|
||||
if (!speed)
|
||||
speed = UNLIMITED_SPEED_VALUE;
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEEDFLAG, limit);
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_HI, ((int)(speed * 10)) >> 8);
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_LO, ((int)(speed * 10)) & 0xff);
|
||||
setValue(MOTOR, MOTOR_PROTECT_UNLOCK, MOTOR_PROTECT_UNLOCK_KEY);
|
||||
setValue(MOTOR, MOTOR_ASSIST_MAXSPEED, (int)speed);
|
||||
}
|
||||
|
||||
|
||||
void setWheelCircumference(unsigned short circumference)
|
||||
{
|
||||
if (!circumference)
|
||||
return;
|
||||
|
||||
setValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_HI, (int) (circumference >> 8));
|
||||
setValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_LO, (int) (circumference & 0xff));
|
||||
setValue(MOTOR, MOTOR_PROTECT_UNLOCK, MOTOR_PROTECT_UNLOCK_KEY);
|
||||
setValue(MOTOR, MOTOR_GEOMETRY_CIRC_HI, (int) (circumference >> 8));
|
||||
setValue(MOTOR, MOTOR_GEOMETRY_CIRC_LO, (int) (circumference & 0xff));
|
||||
}
|
||||
|
||||
void setMinSpeedLimit(double speed)
|
||||
{
|
||||
char limit = (speed != 0);
|
||||
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_MINSPEEDFLAG, limit);
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_MINSPEED, (int)(speed * 10));
|
||||
}
|
||||
|
||||
|
||||
void setThrottleSpeedLimit(double speed)
|
||||
{
|
||||
int limit = (speed != 0);
|
||||
|
||||
if (!speed)
|
||||
speed = MAX_THROTTLE_SPEED_VALUE;
|
||||
|
||||
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEEDFLAG, limit);
|
||||
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_HI, ((int)(speed * 10)) >> 8);
|
||||
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_LO, ((int)(speed * 10)) & 0xff);
|
||||
}
|
||||
|
||||
void printBatteryStats()
|
||||
{
|
||||
int channel = 1, packSerial, packParallel;
|
||||
|
||||
printf( " balancer enabled ...: %s" _NL _NL, (getValue(BATTERY, BATTERY_CELLMON_BALANCERENABLED != 0) ? "yes" : "no"));
|
||||
|
||||
packSerial = getValue(BATTERY, BATTERY_CONFIG_PACKSERIAL);
|
||||
packParallel = getValue(BATTERY, BATTERY_CONFIG_PACKPARALLEL);
|
||||
|
||||
packSerial = (packSerial > 20) ? 0 : packSerial;
|
||||
packParallel = (packParallel > 20) ? 0 : packParallel;
|
||||
|
||||
for (;channel <= packSerial; channel++) {
|
||||
setValue(BATTERY, BATTERY_CELLMON_CHANNELADDR, (int)0x80 + channel);
|
||||
printf(" voltage cell #%02d ...: %.3fV" _NL, channel,
|
||||
((getValue(BATTERY, BATTERY_CELLMON_CHANNELDATA_HI) << 8) + getValue(BATTERY,BATTERY_CELLMON_CHANNELDATA_LO)) * 0.001);
|
||||
}
|
||||
|
||||
for (channel = 0 ; channel < packParallel ; channel ++)
|
||||
printf(" temperature pack #%02d: %d" _DEGREE_SIGN "C" _NL, channel + 1,
|
||||
getValue(BATTERY, BATTERY_STATUS_PACKTEMPERATURE1 + channel));
|
||||
|
||||
printf(_NL);
|
||||
}
|
||||
|
||||
void printChargeStats() {
|
||||
int channel = 1, totalChagres = 0, c;
|
||||
|
||||
for (channel = 1 ; channel <= 10; channel++) {
|
||||
setValue(BATTERY, 0xf6, channel);
|
||||
c = (getValue(BATTERY, 0xf7) << 8) + getValue(BATTERY,0xf8);
|
||||
totalChagres += c;
|
||||
printf(" charge level @ %03d%% : %04d" _NL, channel*10, c);
|
||||
}
|
||||
|
||||
printf(" total # of charges .: %04d" _NL _NL, totalChagres);
|
||||
}
|
||||
|
||||
double getVoltageValue(unsigned char in, unsigned char reg)
|
||||
{
|
||||
return (getValue(BATTERY, reg) + 20.8333) * 0.416667;
|
||||
}
|
||||
|
||||
void usage(void) {
|
||||
printf( "usage:" _NL
|
||||
" -l <speedLimit> .......... set the speed limit to <speedLimit> (1 - " __STR(UNLIMITED_SPEED_VALUE) "), 0 = remove the limit" _NL );
|
||||
}
|
||||
|
||||
int parseOptions(int argc, char **argv)
|
||||
{
|
||||
int oc;
|
||||
char odef[] = "l:t:m:sa:pnxio:c:h?";
|
||||
|
||||
while((oc = getopt(argc,argv,odef)) != -1) {
|
||||
switch(oc) {
|
||||
case 'p':
|
||||
gPowerOff = 1;
|
||||
break;
|
||||
case 'x':
|
||||
gSkipShutdown = 1;
|
||||
break;
|
||||
case 'l':
|
||||
gSetSpeedLimit = atof(optarg);
|
||||
if (gSetSpeedLimit > UNLIMITED_SPEED_VALUE || gSetSpeedLimit < 0) {
|
||||
printf("error: speed limit %.2f is out of range. exiting..." _NL, gSetSpeedLimit);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
gSetThrottleSpeedLimit = atof(optarg);
|
||||
if (gSetThrottleSpeedLimit > MAX_THROTTLE_SPEED_VALUE || gSetThrottleSpeedLimit < 0) {
|
||||
printf("error: throttle speed limit %.2f is out of range. exiting..." _NL, gSetThrottleSpeedLimit);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
gSetMinSpeedLimit = atof(optarg);
|
||||
if (gSetMinSpeedLimit > UNLIMITED_MIN_SPEED_VALUE || gSetMinSpeedLimit < 0) {
|
||||
printf("error: min speed limit %.2f is out of range. exiting..." _NL, gSetMinSpeedLimit);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
gAssistInitLevel = atoi(optarg);
|
||||
if (gAssistInitLevel > 4 || gAssistInitLevel < 0) {
|
||||
printf("error: initial assist level %d is out of range. exiting..." _NL, gAssistInitLevel);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
gSetMountainCap = atoi(optarg);
|
||||
if (gSetMountainCap > 100 || gSetMountainCap < 0) {
|
||||
printf("error: mountain cap level %d is out of range. exiting..." _NL, gSetMountainCap);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
gSetWheelCircumference = atoi(optarg);
|
||||
if (gSetWheelCircumference > 3000 || gSetWheelCircumference < 1000) {
|
||||
printf("error: wheel circumference %d is out of range. exiting..." _NL, gSetWheelCircumference);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
gConsoleSetSlaveMode = 0;
|
||||
break;
|
||||
case 'i':
|
||||
gNoSerialNumbers = 1;
|
||||
break;
|
||||
case 's':
|
||||
gPrintSystemSettings = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printSystemSettings()
|
||||
{
|
||||
int hwVersion, swVersion, wheelCirc;
|
||||
char *sl;
|
||||
double speedLimit = 0;
|
||||
|
||||
printf(_NL _NL);
|
||||
|
||||
hwVersion = getValue(CONSOLE, CONSOLE_REF_HW);
|
||||
|
||||
if (hwVersion == 0)
|
||||
printf("Console not responding" _NL _NL);
|
||||
else {
|
||||
swVersion = getValue(CONSOLE, CONSOLE_REF_SW);
|
||||
printf( "Console information:" _NL
|
||||
" hardware version ........: %02d" _NL
|
||||
" software version ........: %02d" _NL
|
||||
" assistance level ........: %d" _NL,
|
||||
hwVersion, swVersion,
|
||||
getValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL)
|
||||
);
|
||||
|
||||
if (!gNoSerialNumbers)
|
||||
printf( " part number .............: %05d" _NL
|
||||
" item number .............: %05d" _NL _NL,
|
||||
((getValue(CONSOLE, CONSOLE_SN_PN_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_PN_LO)),
|
||||
((getValue(CONSOLE, CONSOLE_SN_ITEM_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_ITEM_LO))
|
||||
);
|
||||
|
||||
/* ASSIST speed limit */
|
||||
sl = getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
|
||||
speedLimit = ((getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_HI) << 8) + getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_LO)) / (double)10;
|
||||
printf( " max limit enabled .......: %s" _NL
|
||||
" speed limit .............: %0.2f Km/h" _NL _NL, sl, speedLimit);
|
||||
|
||||
/* MIN speed limit */
|
||||
sl = getValue(CONSOLE, CONSOLE_ASSIST_MINSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
|
||||
speedLimit = (getValue(CONSOLE, CONSOLE_ASSIST_MINSPEED)) / (double)10;
|
||||
printf( " min limit enabled .......: %s" _NL
|
||||
" min speed limit .........: %0.2f Km/h" _NL _NL, sl, speedLimit);
|
||||
|
||||
/* THROTTLE speed limit */
|
||||
sl = getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
|
||||
speedLimit = ((getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_HI) << 8) + getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_LO)) / (double)10;
|
||||
printf( " throttle limit enabled ..: %s" _NL
|
||||
" throttle speed limit ....: %0.2f Km/h" _NL _NL, sl, speedLimit);
|
||||
|
||||
/* WHEEL CIRCUMFERENCE */
|
||||
wheelCirc = (getValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_HI) << 8) + getValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_LO);
|
||||
printf( " wheel circumference .....: %d mm" _NL _NL, wheelCirc);
|
||||
|
||||
if (swVersion >= 59)
|
||||
printf(
|
||||
" mountain cap ............: %0.2f%%" _NL,
|
||||
(getValue(CONSOLE, CONSOLE_ASSIST_MOUNTAINCAP) * 1.5625));
|
||||
|
||||
printf( " odo .....................: %0.2f Km" _NL _NL,
|
||||
((getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_1) << 24) +
|
||||
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_2) << 16) +
|
||||
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_3) << 8) +
|
||||
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_4))) / (double)10
|
||||
);
|
||||
}
|
||||
|
||||
hwVersion = getValue(BATTERY, BATTERY_REF_HW);
|
||||
if (hwVersion == 0)
|
||||
printf("Battery not responding" _NL _NL);
|
||||
else {
|
||||
printf( "Battery information:" _NL
|
||||
" hardware version ........: %02d" _NL
|
||||
" software version ........: %02d" _NL,
|
||||
hwVersion, getValue(BATTERY, BATTERY_REF_SW)
|
||||
);
|
||||
|
||||
if (!gNoSerialNumbers)
|
||||
printf( " part number .............: %05d" _NL
|
||||
" item number .............: %05d" _NL,
|
||||
((getValue(BATTERY, BATTERY_SN_PN_HI) << 8) + getValue(BATTERY, BATTERY_SN_PN_LO)),
|
||||
((getValue(BATTERY, BATTERY_SN_ITEM_HI) << 8) + getValue(BATTERY, BATTERY_SN_ITEM_LO))
|
||||
);
|
||||
|
||||
printf( " voltage .................: %0.2fV" _NL
|
||||
" battery level ...........: %0.2f%%" _NL
|
||||
" maximum voltage .........: %0.2f%%" _NL
|
||||
" minimum voltage .........: %0.2f%%" _NL
|
||||
" mean voltage ............: %0.2f%%" _NL
|
||||
" resets ..................: %0d" _NL
|
||||
" ggjrCalib ...............: %0d" _NL
|
||||
" vctrlShorts .............: %0d" _NL
|
||||
" lmd .....................: %0.2fAh" _NL
|
||||
" cell capacity ...........: %0.2fAh" _NL _NL,
|
||||
((getValue(BATTERY, BATTERY_STATUS_VBATT_HI) << 8) + getValue(BATTERY, BATTERY_STATUS_VBATT_LO)) * 0.001,
|
||||
(getValue(BATTERY, BATTERY_STATUS_LEVEL) * 6.6667),
|
||||
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMAX),
|
||||
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMIN),
|
||||
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMEAN),
|
||||
(getValue(BATTERY, BATTERY_STATS_RESET_HI) << 8) + getValue(BATTERY, BATTERY_STATS_RESET_LO),
|
||||
getValue(BATTERY, BATTERY_STSTS_GGJSRCALIB),
|
||||
getValue(BATTERY, BATTERY_STSTS_VCTRLSHORTS),
|
||||
((getValue(BATTERY, BATTERY_STATS_LMD_HI) << 8) + getValue(BATTERY, BATTERY_STATS_LMD_LO)) * 0.002142,
|
||||
((getValue(BATTERY, BATTERY_CONFIG_CELLCAPACITY_HI) << 8) + getValue(BATTERY, BATTERY_CONFIG_CELLCAPACITY_LO)) * 0.001
|
||||
);
|
||||
|
||||
|
||||
printf( " charge time worst .......: %0d" _NL
|
||||
" charge time mean ........: %0d" _NL
|
||||
" charge cycles ...........: %0d" _NL
|
||||
" full charge cycles ......: %0d" _NL
|
||||
" power cycles ............: %0d" _NL
|
||||
" battery temp max ........: %0d" _NL
|
||||
" battery temp min ........: %0d" _NL _NL,
|
||||
(getValue(BATTERY, BATTERY_STATS_CHARGETIMEWORST_HI) << 8) + getValue(BATTERY, BATTERY_STATS_CHARGETIMEWORST_LO),
|
||||
(getValue(BATTERY, BATTERY_STATS_CHARGETIMEMEAN_HI) << 8) + getValue(BATTERY, BATTERY_STATS_CHARGETIMEMEAN_LO),
|
||||
(getValue(BATTERY, BATTERY_STATS_BATTCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_BATTCYCLES_LO),
|
||||
(getValue(BATTERY, BATTERY_STATS_BATTFULLCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_BATTFULLCYCLES_LO),
|
||||
(getValue(BATTERY, BATTERY_STATS_POWERCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_POWERCYCLES_HI),
|
||||
getValue(BATTERY, BATTERY_STATS_TBATTMAX),
|
||||
getValue(BATTERY, BATTERY_STATS_TBATTMIN)
|
||||
);
|
||||
|
||||
printChargeStats();
|
||||
|
||||
if (hwVersion >= 60)
|
||||
printBatteryStats();
|
||||
else
|
||||
printf(" no battery details supported by battery hardware #%d" _NL _NL, hwVersion);
|
||||
}
|
||||
|
||||
hwVersion = getValue(MOTOR, MOTOR_REF_HW);
|
||||
if (hwVersion == 0)
|
||||
printf("Motor not responding" _NL _NL);
|
||||
else {
|
||||
printf( "Motor information:" _NL
|
||||
" hardware version ........: %02d" _NL
|
||||
" software version ........: %02d" _NL
|
||||
//" temperature .............: %02d" _DEGREE_SIGN "C"_NL
|
||||
" speed limit .............: %02d Km/h" _NL,
|
||||
hwVersion, getValue(MOTOR, MOTOR_REF_SW),
|
||||
getValue(MOTOR, MOTOR_REALTIME_TEMP),
|
||||
getValue(MOTOR, MOTOR_ASSIST_MAXSPEED)
|
||||
);
|
||||
|
||||
wheelCirc = (getValue(MOTOR, MOTOR_GEOMETRY_CIRC_HI) << 8) + getValue(MOTOR, MOTOR_GEOMETRY_CIRC_LO);
|
||||
printf( " wheel circumference .....: %d mm" _NL _NL, wheelCirc);
|
||||
|
||||
if (!gNoSerialNumbers)
|
||||
printf( " part number .............: %05d" _NL
|
||||
" item number .............: %05d" _NL _NL,
|
||||
((getValue(MOTOR, MOTOR_SN_PN_HI) << 8) + getValue(MOTOR, MOTOR_SN_PN_LO)),
|
||||
((getValue(MOTOR, MOTOR_SN_ITEM_HI) << 8) + getValue(MOTOR, MOTOR_SN_ITEM_LO))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int xmain(int argc, char **argv)
|
||||
{
|
||||
int err, doShutdown = 0, consoleInSlaveMode = 0;
|
||||
struct TDeviceStatus status;
|
||||
|
||||
printf("BigXionFlasher USB " __BXF_VERSION__ _NL " (c) 2011-2013 by Thomas Koenig <info@bigxionflasher.org> - www.bigxionflasher.org" _NL);
|
||||
|
||||
if ((err=parseOptions(argc, argv) < 0))
|
||||
exit(1);
|
||||
|
||||
if ((err = LoadDriver(TREIBER_NAME)) < 0) {
|
||||
printf("LoadDriver error: %d" _NL, err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((err = CanInitDriver(NULL)) < 0) {
|
||||
printf("CanInitDriver error: %d" _NL, err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((err = CanDeviceOpen(0, DEVICE_OPEN)) < 0) {
|
||||
printf("CanDeviceOpen error: %d" _NL, err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
CanSetSpeed(0, CAN_125K_BIT);
|
||||
CanSetMode(0, OP_CAN_START, CAN_CMD_ALL_CLEAR);
|
||||
CanGetDeviceStatus(0, &status);
|
||||
|
||||
if (status.DrvStatus >= DRV_STATUS_CAN_OPEN)
|
||||
{
|
||||
if (status.CanStatus == CAN_STATUS_BUS_OFF)
|
||||
{
|
||||
printf("CAN Status BusOff" _NL);
|
||||
CanSetMode(0, OP_CAN_RESET, CAN_CMD_NONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("error: could not open device" _NL);
|
||||
goto error;
|
||||
}
|
||||
|
||||
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
|
||||
|
||||
if (consoleInSlaveMode)
|
||||
{
|
||||
printf("console already in salve mode. good!" _NL _NL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gConsoleSetSlaveMode)
|
||||
{
|
||||
int retry = 20;
|
||||
|
||||
printf("putting console in salve mode ... ");
|
||||
do {
|
||||
setValue(CONSOLE, CONSOLE_STATUS_SLAVE, 1);
|
||||
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
|
||||
usleep(200000);
|
||||
} while(retry-- && !consoleInSlaveMode);
|
||||
|
||||
doSleep(500); // give the console some time to settle
|
||||
printf("%s" _NL _NL, consoleInSlaveMode ? "done" : "failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("console not in slave mode" _NL _NL);
|
||||
}
|
||||
}
|
||||
|
||||
if (gAssistInitLevel != -1)
|
||||
{
|
||||
printf("setting initial assistance level to %d" _NL, gAssistInitLevel);
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL, gAssistInitLevel);
|
||||
}
|
||||
|
||||
if (gSetSpeedLimit > 0)
|
||||
{
|
||||
printf("set speed limit to %0.2f km/h" _NL, gSetSpeedLimit);
|
||||
setSpeedLimit(gSetSpeedLimit);
|
||||
doShutdown = 1;
|
||||
} else if (gSetSpeedLimit == 0) {
|
||||
printf("disable speed limit, drive carefully" _NL);
|
||||
setSpeedLimit(0);
|
||||
doShutdown = 1;
|
||||
}
|
||||
|
||||
if (gSetMinSpeedLimit > 0) {
|
||||
printf("set minimal speed limit to %0.2f km/h" _NL, gSetMinSpeedLimit);
|
||||
setMinSpeedLimit(gSetMinSpeedLimit);
|
||||
doShutdown = 1;
|
||||
} else if (gSetMinSpeedLimit == 0) {
|
||||
printf("disable minimal speed limit, drive carefully" _NL);
|
||||
setMinSpeedLimit(0);
|
||||
doShutdown = 1;
|
||||
}
|
||||
|
||||
if (gSetThrottleSpeedLimit > 0) {
|
||||
printf("set throttle speed limit to %0.2f km/h" _NL, gSetThrottleSpeedLimit);
|
||||
setThrottleSpeedLimit(gSetThrottleSpeedLimit);
|
||||
doShutdown = 1;
|
||||
} else if (gSetThrottleSpeedLimit == 0) {
|
||||
printf("disable throttle speed limit, drive carefully" _NL);
|
||||
setThrottleSpeedLimit(0);
|
||||
doShutdown = 1;
|
||||
}
|
||||
|
||||
if (gSetMountainCap > 0) {
|
||||
printf("set mountain cap level to %0.2f%%" _NL, ((int)gSetMountainCap / 1.5625) * 1.5625);
|
||||
setValue(CONSOLE, CONSOLE_ASSIST_MOUNTAINCAP, gSetMountainCap / 1.5625);
|
||||
}
|
||||
|
||||
if (gSetWheelCircumference > 0) {
|
||||
printf("set wheel circumference to %d" _NL, gSetWheelCircumference);
|
||||
setWheelCircumference(gSetWheelCircumference);
|
||||
}
|
||||
|
||||
if (gPrintSystemSettings)
|
||||
printSystemSettings();
|
||||
|
||||
if ((doShutdown && !gSkipShutdown) || gPowerOff) {
|
||||
doSleep(1000);
|
||||
printf("shutting down system." _NL);
|
||||
setValue(BATTERY, BATTERY_CONFIG_SHUTDOWN, 1);
|
||||
}
|
||||
|
||||
CanDownDriver();
|
||||
UnloadDriver();
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
CanDownDriver();
|
||||
UnloadDriver();
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
25
armhf-toolchain.cmake
Normal file
25
armhf-toolchain.cmake
Normal file
@@ -0,0 +1,25 @@
|
||||
# Name des Zielsystems
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
# Die Cross-Compiler aus dem Debian-Paket für 32-Bit (armhf)
|
||||
set(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc)
|
||||
set(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++)
|
||||
|
||||
# Wo das System nach Bibliotheken und Headern suchen soll (Sysroot)
|
||||
set(CMAKE_SYSROOT /)
|
||||
|
||||
# Pfade für pkg-config anpassen, damit es die armhf .pc Dateien findet
|
||||
set(ENV{PKG_CONFIG_DIR} "")
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig")
|
||||
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
|
||||
|
||||
# Suchverhalten für find_package(), find_library() etc.
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # Programme (wie moc) auf dem Host suchen
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # Libs nur im Target (armhf) suchen
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Header nur im Target (armhf) suchen
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # CMake-Pakete nur im Target suchen
|
||||
|
||||
# *** WICHTIG FÜR QT6 ***
|
||||
# Sagt Qt, wo es die Host-Tools für das Code-Generieren findet
|
||||
set(QT_HOST_PATH "/usr")
|
||||
78
bc.h
78
bc.h
@@ -36,9 +36,39 @@
|
||||
#include <cstdint>
|
||||
#include <QDebug>
|
||||
#include <QObject> // Nötig für Q_GADGET/Q_ENUM Makros
|
||||
#include <QTime>
|
||||
|
||||
//uint8_t;
|
||||
|
||||
#define BCTimeStamp QTime::currentTime().toString("hh:mm:ss.zzz: ")
|
||||
|
||||
using namespace Qt::Literals::StringLiterals; // Für _L1
|
||||
|
||||
namespace BCTags
|
||||
{
|
||||
inline constexpr auto Bike = "Bike"_L1;
|
||||
inline constexpr auto Device = "Device"_L1;
|
||||
inline constexpr auto ID = "ID"_L1;
|
||||
inline constexpr auto Label = "Label"_L1;
|
||||
inline constexpr auto UnitLabel = "UnitLabel"_L1;
|
||||
inline constexpr auto IsWord = "IsWord"_L1;
|
||||
inline constexpr auto ReadOnly = "ReadOnly"_L1;
|
||||
inline constexpr auto Default = "Default"_L1;
|
||||
|
||||
inline constexpr auto Current = "Current"_L1;
|
||||
inline constexpr auto Enabled = "Enabled"_L1;
|
||||
inline constexpr auto ValueType = "ValueType"_L1;
|
||||
inline constexpr auto Min = "Min"_L1;
|
||||
inline constexpr auto Max = "Max"_L1;
|
||||
inline constexpr auto Factor = "Factor"_L1;
|
||||
|
||||
inline constexpr auto Yes = "Yes"_L1;
|
||||
inline constexpr auto No = "No"_L1;
|
||||
|
||||
inline constexpr auto Host = "bionxcontrol"_L1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simple exception class
|
||||
@@ -73,15 +103,6 @@ namespace bc
|
||||
[[maybe_unused]] constexpr static double NORMALIZED_VOLTAGE_OFFSET = 20.8333;
|
||||
[[maybe_unused]] constexpr static double NORMALIZED_VOLTAGE_FAKTOR = 0.416667;
|
||||
|
||||
// misc
|
||||
//#define cbc::Version "CanBusControl 0.0.01 / 02.07.2022"
|
||||
[[maybe_unused]] constexpr static const char* Version = "BionxControl 0.1.00 / 08.11.2022 © 2022 chris@sourceworx.org";
|
||||
|
||||
[[maybe_unused]] constexpr static const char* OrgName = "source::worx";
|
||||
[[maybe_unused]] constexpr static const char* DomainName = "sourceworx.org";
|
||||
[[maybe_unused]] constexpr static const char* AppName = "BionxControl";
|
||||
|
||||
|
||||
// timer
|
||||
void delay_seconds( uint32_t );
|
||||
void delay_millis( uint32_t );
|
||||
@@ -91,27 +112,6 @@ namespace bc
|
||||
QString formatInt( int count, int len );
|
||||
} // namespace bc
|
||||
|
||||
// abbreviations:
|
||||
// SOC = State Of Charge
|
||||
// LMD = Last Measured Discharge
|
||||
// NIP = ?
|
||||
|
||||
/*
|
||||
|
||||
Needed ?
|
||||
#include <type_traits>
|
||||
|
||||
template <typename E>
|
||||
constexpr auto to_u(E e) noexcept {
|
||||
return static_cast<std::underlying_type_t<E>>(e);
|
||||
}
|
||||
|
||||
// constants.h
|
||||
#pragma once
|
||||
#include <QLatin1StringView>
|
||||
|
||||
|
||||
*/
|
||||
|
||||
struct BC
|
||||
{
|
||||
@@ -766,23 +766,5 @@ public:
|
||||
Q_ENUM(ID)
|
||||
};
|
||||
|
||||
using namespace Qt::Literals::StringLiterals; // Für _L1
|
||||
|
||||
namespace BCTags
|
||||
{
|
||||
inline constexpr auto Device = "Device"_L1;
|
||||
inline constexpr auto ID = "ID"_L1;
|
||||
inline constexpr auto Label = "Label"_L1;
|
||||
inline constexpr auto UnitLabel = "UnitLabel"_L1;
|
||||
inline constexpr auto IsWord = "IsWord"_L1;
|
||||
inline constexpr auto Default = "Default"_L1;
|
||||
|
||||
inline constexpr auto Current = "Current"_L1;
|
||||
inline constexpr auto Enabled = "Enabled"_L1;
|
||||
inline constexpr auto ValueType = "ValueType"_L1;
|
||||
inline constexpr auto Min = "Min"_L1;
|
||||
inline constexpr auto Max = "Max"_L1;
|
||||
inline constexpr auto Factor = "Factor"_L1;
|
||||
}
|
||||
|
||||
#endif // BC_H
|
||||
|
||||
@@ -1,344 +0,0 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <QSlider>
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
#include <QTableView>
|
||||
|
||||
#include <QVariantAnimation>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QPainter>
|
||||
|
||||
#include "bcanimateddelegate.h"
|
||||
|
||||
|
||||
BCAnimatedDelegate::BCAnimatedDelegate(const BCValueList& valueList, QTableView* view)
|
||||
: QStyledItemDelegate{view}, _valueList{valueList}, _view{view}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
QString BCAnimatedDelegate::displayText(const QVariant& dataValue, const QLocale& locale) const
|
||||
{
|
||||
// Wir prüfen, ob im Variant unser Struct steckt
|
||||
if (dataValue.canConvert<const BCValue&>())
|
||||
{
|
||||
const BCValue& bc = dataValue.value<const BCValue/>();
|
||||
//qDebug() << " --- YES: " << bc.label;
|
||||
// Hier bauen wir den String zusammen, den man sieht,
|
||||
// wenn KEIN Editor offen ist.
|
||||
// Format: "Label: Wert Einheit"
|
||||
return QString("%1: %2 %3").arg(bc.label, bc.visibleValue, "mmX");
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << " --- Nö!";
|
||||
}
|
||||
|
||||
// Fallback für normale Strings/Zahlen
|
||||
return QStyledItemDelegate::displayText(dataValue, locale);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
QWidget *BCAnimatedDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const
|
||||
{
|
||||
QVariant rawData = index.data(Qt::EditRole);
|
||||
//if (!rawData.canConvert<BCValue*>())
|
||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
/*
|
||||
const BCValue& bc = *rawData.value<BCValue*>();
|
||||
|
||||
// Nur bei Integern den Slider-Editor bauen
|
||||
if (bc.value.typeId() == QMetaType::Int)
|
||||
{
|
||||
QWidget *container = new QWidget(parent);
|
||||
container->setAutoFillBackground(true);
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(container);
|
||||
layout->setContentsMargins(4, 0, 4, 0);
|
||||
layout->setSpacing(10);
|
||||
|
||||
// Linkes Label (Name)
|
||||
QLabel *lblName = new QLabel(bc.label, container);
|
||||
lblName->setFixedWidth(80);
|
||||
|
||||
// Slider
|
||||
QSlider *slider = new QSlider(Qt::Horizontal, container);
|
||||
slider->setRange(0, 100);
|
||||
slider->setObjectName("slider");
|
||||
|
||||
// Rechtes Label (Vorschau Wert + Einheit)
|
||||
QLabel *lblUnit = new QLabel(container);
|
||||
lblUnit->setFixedWidth(60);
|
||||
lblUnit->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
lblUnit->setObjectName("lblUnit");
|
||||
|
||||
layout->addWidget(lblName);
|
||||
layout->addWidget(slider);
|
||||
layout->addWidget(lblUnit);
|
||||
|
||||
// Live-Update des Labels im Editor (aber noch kein Speichern im Model)
|
||||
connect(slider, &QSlider::valueChanged, this, [=](int val){
|
||||
lblUnit->setText(QString("%1 %2").arg(val).arg("mm2"));
|
||||
});
|
||||
|
||||
return container;
|
||||
|
||||
}
|
||||
|
||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
*/
|
||||
}
|
||||
|
||||
void BCAnimatedDelegate::setEditorData(QWidget *editor, const QModelIndex& index) const
|
||||
{
|
||||
// Daten vom Model in den Editor laden
|
||||
const BCValue& bc = *index.data(Qt::EditRole).value<BCValue*>();
|
||||
|
||||
QSlider *slider = editor->findChild<QSlider*>("slider");
|
||||
QLabel *lblUnit = editor->findChild<QLabel*>("lblUnit");
|
||||
|
||||
if (slider && lblUnit) {
|
||||
bool olDriverState = slider->blockSignals(true);
|
||||
slider->setValue(bc.visibleValue.toInt());
|
||||
slider->blockSignals(olDriverState);
|
||||
|
||||
lblUnit->setText(QString("%1 %2").arg(bc.visibleValue.toInt()).arg( "mm3"));
|
||||
} else {
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
}
|
||||
|
||||
void BCAnimatedDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const
|
||||
{
|
||||
// Daten vom Editor zurück ins Model speichern (Beim Schließen)
|
||||
QSlider *slider = editor->findChild<QSlider*>("slider");
|
||||
|
||||
if (slider) {
|
||||
int value = slider->value();
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
} else {
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
}
|
||||
|
||||
void BCAnimatedDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex& index) const
|
||||
{
|
||||
// __fix!
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
QSize BCAnimatedDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex& index) const
|
||||
{
|
||||
return QStyledItemDelegate::sizeHint(option,index);
|
||||
/*
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
opt.text = formatDisplayString(index);
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), opt.widget);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void BCAnimatedDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
// 1. Standard-Zeichnen (Text, Hintergrund, Selection) durchführen
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
//QPen pen(QColor(255, 165, 0)); // Orange
|
||||
|
||||
/*
|
||||
if (index.row() == _highlightedRow && _opacity > 0.0)
|
||||
{
|
||||
painter->save();
|
||||
|
||||
qDebug() << " --- is highlight: " << index.row();
|
||||
|
||||
QColor highlightColor( 0xFF9800 );
|
||||
highlightColor.setAlphaF(_opacity);
|
||||
|
||||
QPen pen(highlightColor, 3);
|
||||
painter->setPen(pen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawRoundedRect(option.rect.adjusted(2, 2, -2, -2), 8, 8);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
int row = index.row();
|
||||
if (index.column() == 1 )
|
||||
{
|
||||
if( m_rowOpacities.contains(row))
|
||||
{
|
||||
paintHighlightRow(painter,option,index);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
qreal opacity = m_rowOpacities.value(row);
|
||||
if (opacity > 0.01)
|
||||
{
|
||||
painter->save();
|
||||
painter->setOpacity(opacity);
|
||||
painter->fillRect(option.rect, QColor(255, 140, 0, 120));
|
||||
painter->restore();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void BCAnimatedDelegate::paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
int row = index.row();
|
||||
qreal opacity = m_rowOpacities.value(row);
|
||||
painter->setOpacity(opacity);
|
||||
// Margin von 4px
|
||||
QRect itemRect = option.rect.adjusted(3, 3, -3, -3);
|
||||
|
||||
// Border von 2px berücksichtigen (nach innen)
|
||||
//QRect contentRect = itemRect.adjusted(2, 2, -2, -2);
|
||||
// painter->fillRect(contentRect,Qt::green);
|
||||
/*
|
||||
// Hintergrund (weiß)
|
||||
painter->setBrush(Qt::white);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRoundedRect(itemRect, 8, 8);
|
||||
*/
|
||||
// Border (2px solid #2196F3)
|
||||
QPen borderPen( Qt::red, 1);
|
||||
painter->setPen(borderPen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawRoundedRect(itemRect, 2, 2);
|
||||
|
||||
// Padding von 8px für den Content
|
||||
//QRect textRect = contentRect.adjusted(8, 8, -8, -8);
|
||||
|
||||
/*
|
||||
// Text zeichnen
|
||||
painter->setPen(Qt::black); // oder option.palette.color(QPalette::Text)
|
||||
QString text = index.data(Qt::DisplayRole).toString();
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
*/
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
|
||||
void BCAnimatedDelegate::onHighlightRow(int row)
|
||||
{
|
||||
// Alte Animation für diese Zeile stoppen falls vorhanden
|
||||
if (m_rowAnimations.contains(row))
|
||||
{
|
||||
m_rowAnimations[row]->stop();
|
||||
m_rowAnimations[row]->deleteLater();
|
||||
}
|
||||
|
||||
// QVariantAnimation ist flexibler als QPropertyAnimation
|
||||
auto* anim = new QVariantAnimation(this);
|
||||
anim->setDuration(800);
|
||||
anim->setStartValue(0.0);
|
||||
anim->setEndValue(1.0);
|
||||
|
||||
// Custom Easing für Fade-in/out Effekt
|
||||
anim->setEasingCurve(QEasingCurve::OutQuad);
|
||||
|
||||
connect(anim, &QVariantAnimation::valueChanged, this, [this, row](const QVariant& value)
|
||||
{
|
||||
qreal progress = value.toReal();
|
||||
qreal opacity;
|
||||
|
||||
// Schnelles Fade-in (20%), langsames Fade-out (80%)
|
||||
if (progress < 0.2) {
|
||||
opacity = progress * 5.0; // 0->1 in 20%
|
||||
} else {
|
||||
opacity = 1.0 - ((progress - 0.2) / 0.8); // 1->0 in 80%
|
||||
}
|
||||
|
||||
m_rowOpacities[row] = opacity;
|
||||
updateRow(row);
|
||||
});
|
||||
|
||||
connect(anim, &QVariantAnimation::finished, this, [this, row, anim]()
|
||||
{
|
||||
m_rowOpacities.remove(row);
|
||||
m_rowAnimations.remove(row);
|
||||
updateRow(row);
|
||||
anim->deleteLater();
|
||||
});
|
||||
|
||||
m_rowAnimations[row] = anim;
|
||||
anim->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
|
||||
// Optional: alle Highlights sofort clearen
|
||||
void BCAnimatedDelegate::clearAllHighlights()
|
||||
{
|
||||
for(auto* anim : std::as_const(m_rowAnimations))
|
||||
{
|
||||
anim->stop();
|
||||
anim->deleteLater();
|
||||
}
|
||||
m_rowAnimations.clear();
|
||||
m_rowOpacities.clear();
|
||||
|
||||
if (_view)
|
||||
{
|
||||
_view->viewport()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void BCAnimatedDelegate::updateRow(int row)
|
||||
{
|
||||
if (_view && _view->model() && row >= 0)
|
||||
{
|
||||
QModelIndex idx = _view->model()->index(row,1);
|
||||
QRect rect = _view->visualRect(idx);
|
||||
if (!rect.isEmpty()) {
|
||||
_view->viewport()->update(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
216
bcdelightpmwidget.cpp
Normal file
216
bcdelightpmwidget.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <QPropertyAnimation>
|
||||
#include <QSequentialAnimationGroup>
|
||||
#include <QParallelAnimationGroup>
|
||||
#include <QRandomGenerator>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QPainterPath>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QIcon>
|
||||
#include <QDirIterator>
|
||||
#include <QPushButton>
|
||||
|
||||
#include <bcdelightpmwidget.h>
|
||||
|
||||
|
||||
BCDelightPMWidget::BCDelightPMWidget(QWidget *parent)
|
||||
: QObject(parent), _playGround{parent}
|
||||
{
|
||||
loadWidgetsFromResources();
|
||||
}
|
||||
|
||||
|
||||
// Die Methode zum automatischen Einlesen
|
||||
void BCDelightPMWidget::loadWidgetsFromResources()
|
||||
{
|
||||
|
||||
QString resourcePath = ":/resources/smile";
|
||||
|
||||
QDirIterator it(resourcePath, QDir::Files);
|
||||
|
||||
while (it.hasNext())
|
||||
{
|
||||
QString fullPath = it.next();
|
||||
// Eine Zufallsfarbe für den Button-Hintergrund generieren
|
||||
QStringList colors = {"#ff5555", "#50fa7b", "#8be9fd", "#ffb86c"};
|
||||
|
||||
// Ihre Funktion aufrufen und den Pfad übergeben
|
||||
createFlyingWidget(fullPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BCDelightPMWidget::createFlyingWidget(const QString& iconPath)
|
||||
{
|
||||
// 1. Button als Kind des Playground erstellen
|
||||
QPushButton *btn = new QPushButton(_playGround);
|
||||
|
||||
// 2. Das Icon laden und setzen
|
||||
QPixmap pixmap(iconPath);
|
||||
QIcon icon(pixmap);
|
||||
btn->setIcon(icon);
|
||||
|
||||
// 3. WICHTIG: Icon-Größe und Button-Größe synchronisieren
|
||||
// Damit das Bild den Button voll ausfüllt
|
||||
QSize size(128, 128);
|
||||
btn->setFixedSize(size); // Die Klick-Fläche
|
||||
btn->setIconSize(size); // Das Bild darin
|
||||
|
||||
// 4. Stylesheet: Alle Standard-Rahmen und Hintergründe entfernen
|
||||
// "border: none" entfernt den 3D-Rahmen
|
||||
// "background: transparent" macht den Rest unsichtbar
|
||||
btn->setStyleSheet(
|
||||
"QPushButton {"
|
||||
" border: none;"
|
||||
" background-color: transparent;"
|
||||
" outline: none;" /* Entfernt den Fokus-Rahmen beim Klicken */
|
||||
"}"
|
||||
// Optional: Kleiner visueller Effekt beim Drücken (Bild bewegt sich leicht)
|
||||
"QPushButton:pressed {"
|
||||
" padding-top: 4px;"
|
||||
" padding-left: 4px;"
|
||||
"}"
|
||||
);
|
||||
|
||||
btn->show();
|
||||
|
||||
QGraphicsOpacityEffect *opacityEff = new QGraphicsOpacityEffect(btn);
|
||||
opacityEff->setOpacity(1.0);
|
||||
btn->setGraphicsEffect(opacityEff);
|
||||
// --------------------------------------
|
||||
|
||||
btn->show();
|
||||
|
||||
btn->move(50 + _flyingWidgets.size() * 60, 50);
|
||||
_flyingWidgets.append(btn);
|
||||
|
||||
btn->move(_playGround->width()/2, _playGround->height()/2);
|
||||
opacityEff->setOpacity(0.0);
|
||||
|
||||
}
|
||||
void BCDelightPMWidget::onStartChaos()
|
||||
{
|
||||
// Master-Gruppe, damit alle Widgets gleichzeitig starten
|
||||
QParallelAnimationGroup *masterGroup = new QParallelAnimationGroup(this);
|
||||
|
||||
// Gemeinsamer Startpunkt berechnen (Mitte des Playgrounds)
|
||||
// Wir ziehen die halbe Größe eines Widgets (ca. 25px) ab, damit sie wirklich zentriert sind
|
||||
int centerX = (_playGround->width() / 2) - 25;
|
||||
int centerY = (_playGround->height() / 2) - 25;
|
||||
QPoint startPoint(centerX, centerY);
|
||||
|
||||
for (QWidget *widget : std::as_const(_flyingWidgets))
|
||||
{
|
||||
|
||||
QParallelAnimationGroup *widgetGroup = new QParallelAnimationGroup(masterGroup);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// 1. Die Bogen-Animation (QVariantAnimation statt QPropertyAnimation)
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// ZIELE UND STÜTZPUNKTE BERECHNEN
|
||||
int maxX = _playGround->width() - widget->width();
|
||||
int maxY = _playGround->height() - widget->height();
|
||||
QPoint endPoint(
|
||||
QRandomGenerator::global()->bounded(qMax(0, maxX)),
|
||||
QRandomGenerator::global()->bounded(qMax(0, maxY))
|
||||
);
|
||||
|
||||
// Der Kontrollpunkt bestimmt die Kurve.
|
||||
// Für eine Rakete muss er viel HÖHER liegen als Start und Ziel.
|
||||
// Wir nehmen die Mitte zwischen Start/Ziel und gehen 300px nach oben (Y minus).
|
||||
int controlX = (startPoint.x() + endPoint.x()) / 2;
|
||||
int controlY = qMin(startPoint.y(), endPoint.y()) - 300;
|
||||
|
||||
// Pfad erstellen (Quadratische Bézierkurve)
|
||||
QPainterPath path;
|
||||
path.moveTo(startPoint);
|
||||
// quadTo(Kontrollpunkt, Endpunkt)
|
||||
path.quadTo(controlX, controlY, endPoint.x(), endPoint.y());
|
||||
|
||||
// Die Animation treibt den Fortschritt von 0.0 bis 1.0
|
||||
QVariantAnimation *animCurve = new QVariantAnimation();
|
||||
int duration = 2600 + QRandomGenerator::global()->bounded(800);
|
||||
animCurve->setDuration(duration);
|
||||
animCurve->setStartValue(0.0);
|
||||
animCurve->setEndValue(1.0);
|
||||
|
||||
// Für ballistische Flugbahnen ist 'OutQuad' oder 'OutSine' realistisch
|
||||
// (Schneller Start, oben langsamer, unten wieder schneller - physikalisch komplex,
|
||||
// aber OutQuad sieht gut aus für "Wurf")
|
||||
animCurve->setEasingCurve(QEasingCurve::OutQuad);
|
||||
|
||||
// WICHTIG: Lambda, um bei jedem Schritt die Position zu setzen
|
||||
// Wir müssen 'widget' und 'path' in das Lambda capturen (by value für path ist ok)
|
||||
connect(animCurve, &QVariantAnimation::valueChanged, [widget, path](const QVariant &val){
|
||||
qreal progress = val.toReal();
|
||||
|
||||
// Magie: Berechne den Punkt auf der Kurve bei 'progress' Prozent
|
||||
QPointF currentPos = path.pointAtPercent(progress);
|
||||
|
||||
widget->move(currentPos.toPoint());
|
||||
});
|
||||
|
||||
widgetGroup->addAnimation(animCurve);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// 2. Fade-Out (Bleibt fast gleich)
|
||||
// ---------------------------------------------------------
|
||||
QGraphicsOpacityEffect *eff = qobject_cast<QGraphicsOpacityEffect*>(widget->graphicsEffect());
|
||||
if (eff) {
|
||||
QPropertyAnimation *animFade = new QPropertyAnimation(eff, "opacity");
|
||||
animFade->setDuration(duration);
|
||||
animFade->setStartValue(1.0);
|
||||
animFade->setEndValue(0.0);
|
||||
// Erst am Ende ausblenden (ExpoCurve), damit man den Flugbogen sieht
|
||||
animFade->setEasingCurve(QEasingCurve::InExpo);
|
||||
widgetGroup->addAnimation(animFade);
|
||||
}
|
||||
|
||||
masterGroup->addAnimation(widgetGroup);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Speicher aufräumen, wenn alles vorbei ist
|
||||
// Hinweis: Die Widgets bleiben danach unsichtbar (Opacity 0), existieren aber noch.
|
||||
connect(masterGroup, &QAbstractAnimation::finished, masterGroup, &QObject::deleteLater);
|
||||
|
||||
masterGroup->start();
|
||||
}
|
||||
65
bcdelightpmwidget.h
Normal file
65
bcdelightpmwidget.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BC_DELIGHTPMWIDGET_H
|
||||
#define BC_DELIGHTPMWIDGET_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
/**
|
||||
* @brief The BCDelightPMWidget class : Demonstration Graphischer
|
||||
* Effekte für unseren Produktmanager Simon.
|
||||
*/
|
||||
|
||||
class BCDelightPMWidget : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
BCDelightPMWidget( QWidget* parent );
|
||||
|
||||
public slots:
|
||||
|
||||
void onStartChaos();
|
||||
|
||||
protected:
|
||||
|
||||
void loadWidgetsFromResources();
|
||||
void createFlyingWidget(const QString& iconPath);
|
||||
|
||||
QWidget* _playGround{};
|
||||
// Liste der Widgets, die wir bewegen
|
||||
QList<QWidget*> _flyingWidgets;
|
||||
};
|
||||
|
||||
#endif // BC_DELIGHTPMWIDGET_H
|
||||
@@ -27,11 +27,13 @@
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
#include <bcdeviceview.h>
|
||||
#include <bcanimateddelegate.h>
|
||||
#include <bcvaluedelegate.h>
|
||||
|
||||
BCDeviceView::BCDeviceView(QWidget *parent)
|
||||
: QTableView(parent)
|
||||
@@ -42,50 +44,104 @@ BCDeviceView::BCDeviceView(QWidget *parent)
|
||||
//horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
// __fix! ziemlich wildes ge-pointere, hier
|
||||
_itemDelegate = new BCAnimatedDelegate( _valueModel.getValueList(), this);
|
||||
setItemDelegate( _itemDelegate );
|
||||
_itemDelegate = new BCValueDelegate( _valueModel.getValueList(), this);
|
||||
setItemDelegateForColumn( 1, _itemDelegate );
|
||||
setStyleSheet("padding-left: 8px;");
|
||||
|
||||
qDebug() << " --- View size I: " << this->size();
|
||||
// Verbindet den einfachen Klick direkt mit dem Editier-Befehl
|
||||
connect(this, &QAbstractItemView::clicked, this, [this](const QModelIndex &index) {
|
||||
edit(index);
|
||||
});
|
||||
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BCDeviceView::setDeviceID( BCDevice::ID deviceID )
|
||||
{
|
||||
qDebug() << " --- View size II: " << this->size();
|
||||
|
||||
_devideID = deviceID;
|
||||
}
|
||||
|
||||
BCDevice::ID BCDeviceView::getDeviceID() const
|
||||
BCDevice::ID BCDeviceView::deviceID() const
|
||||
{
|
||||
return _devideID;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gibt eine Referenz auf der ValueList zurück.
|
||||
*/
|
||||
|
||||
|
||||
const BCValueList& BCDeviceView::getValueListX()
|
||||
const BCValueList& BCDeviceView::getValueList()
|
||||
{
|
||||
return _valueModel.getValueList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Flag, ob diese View schonmal angezeigt wurde.
|
||||
*/
|
||||
|
||||
// __FIX ist das ok so?
|
||||
bool BCDeviceView::firstExpose()
|
||||
{
|
||||
bool stored = _firstExpose;
|
||||
_firstExpose = false;
|
||||
return stored;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SLOT, der aufgerufen wird, wenn die ValueList vom XML-Lader fertig geladen wurde.
|
||||
* Die DeviceView nimmt die ValueList dann in Besitz.
|
||||
*/
|
||||
void BCDeviceView::onValueListReady( BCDevice::ID deviceID, BCValueList valueList )
|
||||
{
|
||||
qDebug() << " --- onValueListReady: " << deviceID << ": " << valueList.size();
|
||||
if(_devideID == deviceID)
|
||||
{
|
||||
_valueModel.takeValueList( valueList );
|
||||
/*
|
||||
const BCValueList& list = _valueModel.getValueList();
|
||||
int rows = _valueModel.rowCount();
|
||||
for (int r = 0; r < rows; ++r)
|
||||
{
|
||||
BCValuePtr bcValue = list[r];
|
||||
if( !bcValue->isReadOnly() )
|
||||
{
|
||||
QModelIndex index = _valueModel.index(r, 1);
|
||||
openPersistentEditor(index);
|
||||
}
|
||||
}
|
||||
*/
|
||||
} // if id
|
||||
|
||||
}
|
||||
|
||||
void BCDeviceView::onValueUpdated(int index, BCValue::State state, const QString& newVisibleValue )
|
||||
|
||||
/**
|
||||
* @brief SLOT, der aufgerufen wird, wenn ein Value geändert wurde. Gibt dem ItemDelegate Bescheid.
|
||||
*/
|
||||
|
||||
void BCDeviceView::updateValue(int index,BCValue::Flags newState, uint32_t rawValue )
|
||||
{
|
||||
_valueModel.onValueUpdated( index, state, newVisibleValue);
|
||||
_valueModel.updateValue( index, newState, rawValue );
|
||||
_itemDelegate->onHighlightRow( index );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Die Spalte mit dem Label soll immer bei 60% der Gesamtbreite liegen.
|
||||
* @param event
|
||||
*/
|
||||
|
||||
void BCDeviceView::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
// Zuerst die Basisklasse aufrufen (Wichtig für Layouts!)
|
||||
QWidget::resizeEvent(event);
|
||||
|
||||
// Berechnung: 40% der aktuellen Breite
|
||||
// Tipp: viewport()->width() ist genauer als width(), da es Scrollbars rausrechnet!
|
||||
int totalWidth = viewport()->width();
|
||||
int col0Width = static_cast<int>(totalWidth * 0.60);
|
||||
|
||||
// Setzen der Breite
|
||||
horizontalHeader()->resizeSection(0, col0Width);
|
||||
}
|
||||
|
||||
@@ -30,15 +30,15 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCDEVICEVIEW_H
|
||||
#define BCDEVICEVIEW_H
|
||||
#ifndef BC_DEVICEVIEW_H
|
||||
#define BC_DEVICEVIEW_H
|
||||
|
||||
#include <QTableView>
|
||||
|
||||
#include <bcvaluemodel.h>
|
||||
|
||||
|
||||
class BCAnimatedDelegate;
|
||||
class BCValueDelegate;
|
||||
|
||||
class BCDeviceView : public QTableView
|
||||
{
|
||||
@@ -48,26 +48,28 @@ public:
|
||||
|
||||
explicit BCDeviceView(QWidget *parent = nullptr);
|
||||
|
||||
|
||||
void setDeviceID( BCDevice::ID deviceID );
|
||||
BCDevice::ID getDeviceID() const;
|
||||
BCDevice::ID deviceID() const;
|
||||
|
||||
const BCValueList& getValueListX();
|
||||
//BCValueModel &getValueModel();
|
||||
const BCValueList& getValueList();
|
||||
|
||||
bool hasContent();
|
||||
bool firstExpose();
|
||||
void updateValue(int index, BCValue::Flags newState, uint32_t rawValue );
|
||||
|
||||
public slots:
|
||||
|
||||
void onValueListReady( BCDevice::ID deviceID, BCValueList valueList );
|
||||
void onValueUpdated( int index, BCValue::State state, const QString& newVisibleValue="" );
|
||||
|
||||
protected:
|
||||
|
||||
BCDevice::ID _devideID{BCDevice::ID::Invalid};
|
||||
BCValueModel _valueModel;
|
||||
BCAnimatedDelegate* _itemDelegate{};
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
bool _firstExpose{true};
|
||||
BCDevice::ID _devideID{BCDevice::ID::Invalid};
|
||||
BCValueModel _valueModel;
|
||||
BCValueDelegate* _itemDelegate{};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // BCDEVICEVIEW_H
|
||||
#endif // BC_DEVICEVIEW_H
|
||||
|
||||
@@ -74,7 +74,9 @@ TransmitResult BCDriverDummy::readRawByte( uint32_t deviceID, uint8_t registerID
|
||||
{
|
||||
Q_UNUSED(deviceID)
|
||||
Q_UNUSED(registerID)
|
||||
qDebug() << " --- Dummy: readRawByte:DriverState: " << getDriverState();
|
||||
// Tätigkeit simulieren
|
||||
//bc::delay_millis(200);
|
||||
bc::delay_millis(50);
|
||||
uint8_t myRandomByte = static_cast<uint8_t>(QRandomGenerator::global()->bounded(256));
|
||||
return myRandomByte;
|
||||
}
|
||||
@@ -88,7 +90,7 @@ TransmitResult BCDriverDummy::writeRawByte( uint32_t deviceID, uint8_t registerI
|
||||
{
|
||||
Q_UNUSED(deviceID)
|
||||
Q_UNUSED(registerID)
|
||||
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
|
||||
Q_UNUSED(value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCDRIVER_H
|
||||
#define BCDRIVER_H
|
||||
#ifndef BC_DRIVER_H
|
||||
#define BC_DRIVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <expected>
|
||||
@@ -119,4 +119,4 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#endif // BCDRIVER_H
|
||||
#endif // BC_DRIVER_H
|
||||
|
||||
122
bcdriverstatewidget.cpp
Normal file
122
bcdriverstatewidget.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <bcdriverstatewidget.h>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Hilfswidget: Zeigt den DriverState als Icon an.
|
||||
*/
|
||||
|
||||
BCDriverStateWidget::BCDriverStateWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(10, 2, 10, 2);
|
||||
//layout->setSpacing(8);
|
||||
|
||||
_led = new QLabel(this);
|
||||
_led->setFixedSize(12, 12);
|
||||
|
||||
layout->addWidget(_led);
|
||||
|
||||
// Startzustand
|
||||
onDriverStateChanged(BCDriver::DriverState::NotPresent, "Kein Treiber geladen.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void BCDriverStateWidget::onDriverStateChanged(BCDriver::DriverState state, const QString& customMessage)
|
||||
{
|
||||
Q_UNUSED(customMessage)
|
||||
_state = state;
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
|
||||
void BCDriverStateWidget::updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString toolTipText;
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case BCDriver::DriverState::NotPresent:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
toolTipText = "Kein Treiber geladen.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
toolTipText = "Fehler beim Laden des Treibers.";
|
||||
break;
|
||||
|
||||
// hier: dll vorhanden, Treiber geladen
|
||||
case BCDriver::DriverState::Loaded:
|
||||
case BCDriver::DriverState::Initialized:
|
||||
case BCDriver::DriverState::Opened:
|
||||
// ORANGE
|
||||
ledStyle = "background-color: #FF8C00; border: 1px solid #A80000;";
|
||||
toolTipText = "Kein Gerät verbunden.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;";
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief minimale click event
|
||||
*/
|
||||
|
||||
void BCDriverStateWidget::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
emit clicked();
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
@@ -30,51 +30,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCGUIHELPERS_H
|
||||
#define BCGUIHELPERS_H
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include <bcdriver.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Einfaches Buttonwidget, um zwischen Dark- und Lightmode
|
||||
* zu wechseln
|
||||
*/
|
||||
|
||||
class BCThemeSwitchButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCThemeSwitchButton(QWidget *parent = nullptr);
|
||||
void setDarkMode( bool isDark );
|
||||
|
||||
signals:
|
||||
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
|
||||
void toggleMode();
|
||||
|
||||
private:
|
||||
|
||||
void updateIcon();
|
||||
|
||||
bool _isDarkMode{false};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
#ifndef BC_DRIVERSTATEWIDGET_H
|
||||
#define BC_DRIVERSTATEWIDGET_H
|
||||
|
||||
|
||||
/**
|
||||
@@ -82,6 +39,12 @@ private:
|
||||
* Drivers anzuzeigen.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
|
||||
#include <bcdriver.h>
|
||||
class BCDriverStateWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -110,4 +73,4 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
#endif // BCGUIHELPERS_H
|
||||
#endif // BC_DRIVERSTATEWIDGET_H
|
||||
@@ -151,7 +151,6 @@ BCDriver::DriverStateResult BCDriverTinyCan::loadDriver()
|
||||
return _driverState;
|
||||
};
|
||||
|
||||
|
||||
// #1. erstmal komplett zurücksetzen
|
||||
resetDriver();
|
||||
// #2. Treiber laden, initialisieren und
|
||||
@@ -177,27 +176,18 @@ BCDriver::DriverStateResult BCDriverTinyCan::loadDriver()
|
||||
BCDriver::DriverStateResult BCDriverTinyCan::setConsoleSlaveMode()
|
||||
{
|
||||
|
||||
// Wir versuchen ein Test-Byte zu lesen, hier: einfach die Hardware
|
||||
// Revision der Console.
|
||||
|
||||
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
|
||||
uint8_t slaveFlag = static_cast<uint8_t> (BC::ID::Cons_Status_Slave);
|
||||
|
||||
qDebug() << "XXX BCDriverTinyCan::Driver Init: putting Console in slave mode ... ";
|
||||
|
||||
unsigned int retry = cTimeOuts;
|
||||
TransmitResult isSlave = 0;
|
||||
// Already slave?
|
||||
isSlave = readRawByte( console, slaveFlag );
|
||||
if( isSlave.has_value() )
|
||||
{
|
||||
qDebug() << "Console responded: " << isSlave.value();
|
||||
if( isSlave.value() == 1 )
|
||||
{
|
||||
qDebug() << "Console already in slave mode. good!";
|
||||
return DriverState::DeviceReady;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "BCDriverTinyCan::BCDriverTinyCan::XXX Driver Init: putting Console in slave mode ... ";
|
||||
|
||||
unsigned int retry = cTimeOuts;
|
||||
if( isSlave.has_value() && isSlave.value() == 1 )
|
||||
goto happyEnd;
|
||||
|
||||
do
|
||||
{
|
||||
@@ -208,11 +198,17 @@ BCDriver::DriverStateResult BCDriverTinyCan::setConsoleSlaveMode()
|
||||
} while( retry-- && !(*isSlave) );
|
||||
|
||||
bc::delay_millis( 500 ); // give the Console some time to settle
|
||||
//if( !isSlave )
|
||||
//emit statusHint( QString("putting Console in slave mode ") + (isSlave ? "done" : "failed") );
|
||||
|
||||
if( isSlave.has_value() && isSlave.value() == 1 )
|
||||
goto happyEnd;
|
||||
|
||||
// ist das jetzt irgendwie schlimm, wenn wir keine slave Console haben
|
||||
return isSlave ? DriverState::DeviceReady : DriverState::Opened;
|
||||
return DriverState::Opened;
|
||||
|
||||
happyEnd:
|
||||
|
||||
_driverState = DriverState::DeviceReady;
|
||||
return DriverState::DeviceReady;
|
||||
|
||||
}
|
||||
|
||||
@@ -237,75 +233,14 @@ void BCDriverTinyCan::resetDriver()
|
||||
TransmitResult BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) const
|
||||
{
|
||||
|
||||
qDebug() << " --- CAN Read Byte: Device: "<< deviceID << " register: " << registerID << " TRY! ";
|
||||
|
||||
struct TCanMsg msg;
|
||||
int err, retry = 20;
|
||||
int timeout = 80;
|
||||
|
||||
unsigned char receipient = (unsigned char) deviceID;
|
||||
unsigned char reg = (unsigned char) registerID;
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = receipient;
|
||||
msg.MsgLen = 2;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = reg;
|
||||
|
||||
CanTransmit(0, &msg, 1);
|
||||
|
||||
while(timeout-- && CanTransmitGetCount(0))
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if (timeout == -1)
|
||||
qDebug() << "error: could not send value to node ";
|
||||
|
||||
retry:
|
||||
|
||||
timeout = 80;
|
||||
while(timeout-- && !CanReceiveGetCount(0))
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if (timeout == -1)
|
||||
{
|
||||
qDebug() << "error: no response from node";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((err = CanReceive(0, &msg, 1)) > 0)
|
||||
{
|
||||
qDebug() << " retry: " << retry << " BIB:" << BC::ID::ID_Bib << " msg.Id: " << msg.Id << " msg.MsgLen: " << msg.MsgLen << " msg.MsgData[1]: " << msg.MsgData[1] << " reg: " << reg;
|
||||
if (--retry && (msg.Id != (uint32_t)BC::ID::ID_Bib|| msg.MsgLen != 4 || msg.MsgData[1] != reg))
|
||||
goto retry;
|
||||
|
||||
if (!retry)
|
||||
{
|
||||
qDebug() << "XXX error: no response from node: " << err;
|
||||
return 0;
|
||||
}
|
||||
qDebug() << " --- CAN Read Byte: Device: "<< deviceID << " register: " << registerID << " BYTE: " << (uint32_t) msg.MsgData[3];
|
||||
return (unsigned int) msg.MsgData[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Error:" <<err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
//TransmitResult
|
||||
qDebug() << " --- BCDriverTinyCan::readRawByte DriverState: " << getDriverState();
|
||||
|
||||
if( _driverState <DriverState::Opened )
|
||||
return std::unexpected(QString("readRawValue error: driver not loaded." ) );
|
||||
return std::unexpected(QString("readRawValue error: Treiber nicht geladen." ) );
|
||||
|
||||
unsigned char receipient = (unsigned char ) deviceID;
|
||||
::TCanMsg msg;
|
||||
|
||||
// msg verpacken
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = receipient;//deviceID;
|
||||
msg.Id = deviceID;
|
||||
msg.MsgLen = 2;
|
||||
msg.MsgData[0] = 0x00;
|
||||
msg.MsgData[1] = registerID;
|
||||
@@ -313,16 +248,15 @@ retry:
|
||||
// msg verschicken
|
||||
::CanTransmit( 0, &msg, 1 );
|
||||
|
||||
int retries = cRetries; // 5?
|
||||
// cTimeOuts (== 20) mal cTIMEOUT_MS (== 10 ms ) Versuche ...
|
||||
int timeOuts = cTimeOuts; // 20 ?
|
||||
int retries = cRetries; // 5
|
||||
int timeOuts = cTimeOuts; // 20
|
||||
|
||||
// ... warten bis der Sendepuffer leer ist
|
||||
while( timeOuts-- && ::CanTransmitGetCount( 0 ) )
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if( timeOuts == -1 )
|
||||
return std::unexpected(QString("readRawValue error: could not send value" ));
|
||||
return std::unexpected(QString("readRawValue error: Sendefehler" ));
|
||||
|
||||
retry:
|
||||
|
||||
@@ -332,47 +266,35 @@ retry:
|
||||
while( timeOuts-- && !::CanReceiveGetCount( 0 ) )
|
||||
bc::delay_millis( cTIMEOUT_MS );
|
||||
|
||||
if( timeOuts == -1 )
|
||||
return std::unexpected(QString("getValue error: no response from node" ));
|
||||
if (timeOuts == -1)
|
||||
return std::unexpected(QString("readRawValue error: (Node)Timeout" ));
|
||||
|
||||
// message empfangen
|
||||
int err = ::CanReceive( 0, &msg, 1 );
|
||||
//qDebug() << "HÄÄ ?" << err << "reg: "<< registerID <<" timeOuts: " << timeOuts;
|
||||
|
||||
if( err < 0 )
|
||||
//throw BCException( "getValue error: could not receive value" );
|
||||
qDebug( "getValue error: could not receive value" );
|
||||
return std::unexpected(QString("CAN response errror: Timeout"));
|
||||
|
||||
//qDebug() << "HÄÄ 2" <<msg.Id;
|
||||
//qDebug() << "HÄÄ 2" <<msg.MsgLen;
|
||||
//qDebug() << "HÄÄ 2" <<msg.MsgData[1];
|
||||
|
||||
//if( err > 0 )
|
||||
if( --retries && ( msg.Id != BIB || msg.MsgLen != 4 || msg.MsgData[1] != registerID ) )
|
||||
if( --retries && ( msg.Id != (uint32_t)BC::ID::ID_Bib || msg.MsgLen != 4 || msg.MsgData[1] != registerID ) )
|
||||
goto retry;
|
||||
|
||||
if( !timeOuts )
|
||||
return std::unexpected(QString("CAN response errror: timeout" ));
|
||||
return std::unexpected(QString("CAN response errror: Timeout" ));
|
||||
|
||||
qDebug() << " --- CAN Read Byte: " << (uint32_t) msg.MsgData[3] << " Device:: "<< deviceID << " register: " << registerID;
|
||||
return (uint32_t) msg.MsgData[3];
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
// void BCDriverTinyCan::setValue( unsigned char receipient, unsigned char reg, unsigned char value )
|
||||
TransmitResult BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID, uint8_t value ) const
|
||||
{
|
||||
|
||||
if( _driverState <DriverState::Opened )
|
||||
return std::unexpected(QString("readRawValue error: driver not loaded." ) );
|
||||
|
||||
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
|
||||
|
||||
::TCanMsg msg;
|
||||
int timeout_count = cTIMEOUT_COUNT;
|
||||
|
||||
|
||||
msg.MsgFlags = 0L;
|
||||
msg.Id = deviceID;
|
||||
msg.MsgLen = 4;
|
||||
@@ -389,6 +311,6 @@ TransmitResult BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registe
|
||||
if( timeout_count == -1 )
|
||||
return std::unexpected(QString("error: could not send value to %1" ).arg( deviceID ) );
|
||||
|
||||
return uint32_t(1); // als 'true'
|
||||
return uint32_t(0); // kein Fehler
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCDRIVERTINYCAN_H
|
||||
#define BCDRIVERTINYCAN_H
|
||||
#ifndef BC_DRIVERTINYCAN_H
|
||||
#define BC_DRIVERTINYCAN_H
|
||||
|
||||
#include <bcdriver.h>
|
||||
|
||||
@@ -60,4 +60,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#endif // BCDRIVERTINYCAN_H
|
||||
#endif // BC_DRIVERTINYCAN_H
|
||||
|
||||
248
bcguihelpers.cpp
248
bcguihelpers.cpp
@@ -1,248 +0,0 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <bcguihelpers.h>
|
||||
|
||||
|
||||
BCThemeSwitchButton::BCThemeSwitchButton(QWidget *parent )
|
||||
: QPushButton(parent)
|
||||
{
|
||||
// Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
setFixedSize(24, 24); // Kleiner Footprint im StatusBar
|
||||
|
||||
// CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt
|
||||
// Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind
|
||||
/*
|
||||
setStyleSheet(R"(
|
||||
QPushButton {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 11pt;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
|
||||
border-radius: 24px;
|
||||
}
|
||||
)");
|
||||
*/
|
||||
// Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
||||
updateIcon();
|
||||
|
||||
connect(this, &QPushButton::clicked, this, &BCThemeSwitchButton::toggle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Setzt den DarkMode
|
||||
*/
|
||||
|
||||
void BCThemeSwitchButton::setDarkMode( bool isDark )
|
||||
{
|
||||
_isDarkMode = !isDark;
|
||||
toggleMode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Schaltet den akutellen Mode um.
|
||||
*/
|
||||
|
||||
void BCThemeSwitchButton::toggleMode()
|
||||
{
|
||||
_isDarkMode = !_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(_isDarkMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Icon & Tooltip anpassen
|
||||
*/
|
||||
|
||||
void BCThemeSwitchButton::updateIcon()
|
||||
{
|
||||
// Logik:
|
||||
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
||||
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
||||
setText(_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(_isDarkMode ? "Zum LightMode wechseln" : "Zum DarkMode wechseln");
|
||||
}
|
||||
|
||||
|
||||
/// -----------------------------------------------------------------------------------
|
||||
/// -----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* @brief Hilfswidget: Zeigt den DriverState als Icon an.
|
||||
*/
|
||||
|
||||
BCDriverStateWidget::BCDriverStateWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(10, 2, 10, 2);
|
||||
//layout->setSpacing(8);
|
||||
|
||||
_led = new QLabel(this);
|
||||
_led->setFixedSize(12, 12);
|
||||
|
||||
layout->addWidget(_led);
|
||||
|
||||
// Startzustand
|
||||
onDriverStateChanged(BCDriver::DriverState::NotPresent, "Not Present");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Hauptfunktion zum Setzen des Status
|
||||
// 'customMessage' ist optional. Wenn leer, wird ein Standardtext genommen.
|
||||
void BCDriverStateWidget::onDriverStateChanged(BCDriver::DriverState state, const QString& customMessage)
|
||||
{
|
||||
_state = state;
|
||||
qDebug() << " --- StateWidget: " << state << " - " << customMessage;
|
||||
|
||||
updateStyle();
|
||||
}
|
||||
|
||||
/*
|
||||
void BCDriverStateWidget::updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString labelColor;
|
||||
QString toolTipText;
|
||||
|
||||
switch (_state)
|
||||
{
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;#FF5F1F; #FF8C00;<- das isses #FF6700";
|
||||
labelColor = "#FFFFFF"; // Weiß (Hervorgehoben)
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
labelColor = "#FF99A4"; // Ein helleres Rot für Text, damit es auf Dunkel lesbar ist
|
||||
toolTipText = "Kritischer Fehler bei der Verbindung!";
|
||||
break;
|
||||
|
||||
default:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
labelColor = "#9E9E9E"; // Ausgegrauter Text
|
||||
toolTipText = "System ist offline.";
|
||||
break;
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
|
||||
// Textfarbe setzen
|
||||
_label->setStyleSheet(QString("color: %1; font-weight: %2;")
|
||||
.arg(labelColor)
|
||||
.arg(_state == BCDriver::DriverState::DeviceReady ? "bold" : "normal"));
|
||||
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
*/
|
||||
|
||||
void BCDriverStateWidget::updateStyle()
|
||||
{
|
||||
QString ledStyle;
|
||||
QString toolTipText;
|
||||
/*
|
||||
NotPresent,
|
||||
Error,
|
||||
Loaded,
|
||||
Initialized,
|
||||
Opened, // bis hierher: dll vorhanden, Treiber geladen
|
||||
DeviceReady
|
||||
*/
|
||||
switch (_state)
|
||||
{
|
||||
case BCDriver::DriverState::NotPresent:
|
||||
// FLUENT GRAY (Neutral)
|
||||
// Wir machen es dunkelgrau mit hellem Rand -> "Ausgeschaltet"-Look
|
||||
ledStyle = "background-color: #3B3B3B; border: 1px solid #606060;";
|
||||
toolTipText = "Treiber nicht geladen.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::Error:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #C42B1C; border: 1px solid #A80000;";
|
||||
toolTipText = "Fehler beim Laden des Treibers.";
|
||||
break;
|
||||
|
||||
// hier: dll vorhanden, Treiber geladen
|
||||
case BCDriver::DriverState::Loaded:
|
||||
case BCDriver::DriverState::Initialized:
|
||||
case BCDriver::DriverState::Opened:
|
||||
// FLUENT RED (Critical)
|
||||
ledStyle = "background-color: #FF8C00; border: 1px solid #A80000;";
|
||||
toolTipText = "Fehler beim Laden des Treibers.";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
// FLUENT GREEN (Success)
|
||||
ledStyle = "background-color: #107C10; border: 1px solid #0E600E;";
|
||||
toolTipText = "Verbindung erfolgreich hergestellt.";
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Styles anwenden (immer rund machen)
|
||||
_led->setStyleSheet(ledStyle + "border-radius: 6px;");
|
||||
|
||||
/*
|
||||
// Textfarbe setzen
|
||||
_setStyleSheet(QString("color: %1; font-weight: %2;")
|
||||
.arg(labelColor)
|
||||
.arg(_state == BCDriver::DriverState::DeviceReady ? "bold" : "normal"));
|
||||
*/
|
||||
setToolTip(toolTipText);
|
||||
}
|
||||
|
||||
void BCDriverStateWidget::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
emit clicked();
|
||||
}
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
|
||||
210
bcmainwindow.cpp
210
bcmainwindow.cpp
@@ -29,14 +29,16 @@
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "qassert.h"
|
||||
#include <bcthemebutton.h>
|
||||
#include <bcdriverstatewidget.h>
|
||||
#include <bcmainwindow.h>
|
||||
#include <bcanimateddelegate.h>
|
||||
#include <bcvaluedelegate.h>
|
||||
#include <ui_bcmainwindow.h>
|
||||
#include <bcguihelpers.h>
|
||||
|
||||
/**
|
||||
* @brief Das Mainwindow erzeugen
|
||||
@@ -50,10 +52,12 @@ BCMainWindow::BCMainWindow(QWidget *parent)
|
||||
qRegisterMetaType<BCValue>("BCValue");
|
||||
qRegisterMetaType<QList<BCValue>>("BCValueList");
|
||||
|
||||
setupUi(this);
|
||||
#if defined(Q_OS_LINUX)
|
||||
// Für Touch screen: Window FRam weglassen
|
||||
//setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
|
||||
#endif
|
||||
|
||||
// den pimp-my-ride-button schalten wir vorerst aus.
|
||||
_pimpButton->hide();
|
||||
setupUi(this);
|
||||
|
||||
// Wir schreiben den 'initMainWindow()' Aufruf mit Hilfe des
|
||||
// timers in die Event-Queue, damit er erst ausgeführt wird,
|
||||
@@ -83,7 +87,6 @@ BCMainWindow::~BCMainWindow()
|
||||
|
||||
void BCMainWindow::initMainWindow()
|
||||
{
|
||||
|
||||
// Lambda um die buttons mit ihren Actions zu verbinden
|
||||
auto configureAction = [&]( QToolButton* button, QAction* action, BCDevice::ID deviceID )
|
||||
{
|
||||
@@ -91,78 +94,78 @@ void BCMainWindow::initMainWindow()
|
||||
button->setDefaultAction( action);
|
||||
// new way: die DeviceID muss aber explizit vom Lambda eingefanden werden.
|
||||
connect( action, &QAction::triggered, this, [this,deviceID]()
|
||||
{
|
||||
onShowDevicePanel( deviceID );
|
||||
});
|
||||
{
|
||||
onShowDevicePanel( deviceID );
|
||||
});
|
||||
|
||||
if( _devicePanels.contains(deviceID) )
|
||||
{
|
||||
BCDeviceView* currentPanel = _devicePanels[deviceID];
|
||||
// ... und ihre device ID
|
||||
currentPanel->setDeviceID( deviceID );
|
||||
// Wenn ein Device (entspricht einem Datenmodel) fertig eingelesen wurde,
|
||||
// wird es weitergereicht.
|
||||
// Problem: alle Panels bekommen alle Datenmodelle angeboten.
|
||||
connect( &_dataManager, &BCXmlLoader::valueListReady, currentPanel, &BCDeviceView::onValueListReady );
|
||||
}
|
||||
{
|
||||
BCDeviceView* currentPanel = _devicePanels[deviceID];
|
||||
// ... und ihre device ID
|
||||
currentPanel->setDeviceID( deviceID );
|
||||
// Wenn ein Device (entspricht einem Datenmodel) fertig eingelesen wurde,
|
||||
// wird es weitergereicht.
|
||||
// Problem: alle Panels bekommen alle Datenmodelle angeboten.
|
||||
connect( &_dataManager, &BCXmlLoader::valueListReady, currentPanel, &BCDeviceView::onValueListReady );
|
||||
|
||||
connect( currentPanel->model(), SIGNAL(makeSimonHappy()), this, SLOT(onStartAnimation() ) );
|
||||
}
|
||||
};
|
||||
|
||||
// Wir wollen die Devices den Views zuordnen können
|
||||
_devicePanels[BCDevice::ID::Console] = _consolePanel;
|
||||
_devicePanels[BCDevice::ID::Battery] = _batteryPanel;
|
||||
_devicePanels[BCDevice::ID::Motor] = _motorPanel;
|
||||
//_devicePanels[BCDevice::ID::Pimp] = _pimpPanel;
|
||||
|
||||
// Die actions an die Buttons binden
|
||||
// Die actions an die Buttons binden
|
||||
configureAction(_motorButton, _motorAction, BCDevice::ID::Motor );
|
||||
configureAction(_consoleButton, _consoleAction, BCDevice::ID::Console );
|
||||
configureAction(_batteryButton, _batteryAction, BCDevice::ID::Battery );
|
||||
//configureAction(_pimpButton, _pimpAction, BCDevice::ID::Pimp );
|
||||
|
||||
|
||||
/*
|
||||
bool m_isDarkMode = false;
|
||||
QString icon = m_isDarkMode ? "☀️" : "🌙";
|
||||
fitzeButton->setText(icon);
|
||||
|
||||
QString style = QString(
|
||||
"QPushButton {"
|
||||
" background-color: %1;"
|
||||
" border: 1px solid %2;"
|
||||
" border-radius: 6px;"
|
||||
" font-size: 12pt;"
|
||||
" padding: 0px;"
|
||||
"}"
|
||||
"QPushButton:hover {"
|
||||
" background-color: %3;"
|
||||
"}"
|
||||
).arg(m_isDarkMode ? "#2B2B2B" : "#FFFFFF")
|
||||
.arg(m_isDarkMode ? "#3F3F3F" : "#E1DFDD")
|
||||
.arg(m_isDarkMode ? "#3A3A3A" : "#F9F9F9");
|
||||
|
||||
fitzeButton->setStyleSheet(style);
|
||||
*/
|
||||
|
||||
initStatusBar();
|
||||
|
||||
// besser: model::emit dataChanged
|
||||
// also: emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, ValueRole});
|
||||
connect( _connectButton, &QToolButton::clicked, &_transmitter, &BCTransmitter::onToggleDriverConnection );
|
||||
connect( _syncButton, &QToolButton::clicked, this, &BCMainWindow::onSyncDeviceView );
|
||||
connect( &_transmitter, &BCTransmitter::valueUpdated, this, &BCMainWindow::onValueUpdated );
|
||||
_connectButton->setDefaultAction( _connectAction);
|
||||
_syncButton->setDefaultAction( _syncAction);
|
||||
|
||||
connect(this, &BCMainWindow::requestValueUpdate, &_transmitter, &BCTransmitter::onEnqueueValue);
|
||||
connect(&_worker, &QThread::finished, &_transmitter, &QObject::deleteLater);
|
||||
connect( _connectAction, &QAction::triggered, &_transmitter, &BCTransmitter::onToggleDriverConnection );
|
||||
connect( _syncAction, &QAction::triggered, this, &BCMainWindow::onSyncDeviceView );
|
||||
connect( _exitButton, &QToolButton::clicked, qApp, &QCoreApplication::quit );
|
||||
|
||||
connect( &_transmitter, &BCTransmitter::valueUpdated, this, &BCMainWindow::onValueUpdated );
|
||||
connect( this, &BCMainWindow::requestValueUpdate, &_transmitter, &BCTransmitter::onUpdateValue);
|
||||
connect( &_worker, &QThread::finished, &_transmitter, &QObject::deleteLater);
|
||||
connect( &_transmitter, &BCTransmitter::driverStateChanged, this, &BCMainWindow::onDriverStateChanged );
|
||||
connect( &_transmitter, &BCTransmitter::endOfProcessing, this, &BCMainWindow::onEndOfProcessing );
|
||||
connect( this, &BCMainWindow::endOfTransmission, &_transmitter, &BCTransmitter::onEndOfTransmission );
|
||||
|
||||
// transmitter starten
|
||||
_transmitter.moveToThread(&_worker);
|
||||
_worker.start();
|
||||
|
||||
// die Daten des eBikes laden
|
||||
_dataManager.loadXmlBikeData(":/bikeinfo.xml"_L1);
|
||||
//_consoleAction->trigger();
|
||||
_batteryAction->trigger();
|
||||
try
|
||||
{
|
||||
// die Daten des eBikes laden
|
||||
_dataManager.loadXmlBikeData(":/bikeinfo.xml"_L1);
|
||||
}
|
||||
catch( BCException& exception )
|
||||
{
|
||||
QMessageBox::critical( this, "Ladefehler", exception.what() );
|
||||
}
|
||||
|
||||
// Konsolendaten als erstes anzeigen
|
||||
_consoleAction->trigger();
|
||||
//_batteryAction->trigger();
|
||||
|
||||
/*
|
||||
// Dummy sync beim starten
|
||||
QTimer::singleShot(1000, this, [this]()
|
||||
{
|
||||
onSyncDeviceView();
|
||||
});
|
||||
*/
|
||||
|
||||
// not least
|
||||
_delightWidget = new BCDelightPMWidget(this);
|
||||
|
||||
}
|
||||
|
||||
@@ -178,28 +181,31 @@ connectIcon.addFile(":/icons/plug_connected.svg", QSize(), QIcon::Normal, QIc
|
||||
|
||||
void BCMainWindow::initStatusBar()
|
||||
{
|
||||
QStatusBar *statBar = statusBar();
|
||||
|
||||
BCDriverStateWidget* conState = new BCDriverStateWidget(this);
|
||||
connect( &_transmitter, &BCTransmitter::driverStateChanged, conState, &BCDriverStateWidget::onDriverStateChanged );
|
||||
connect( conState, &BCDriverStateWidget::clicked, _connectAction, &QAction::trigger );
|
||||
|
||||
statBar->addPermanentWidget(conState);
|
||||
_statusBar->addPermanentWidget(conState);
|
||||
conState->installEventFilter(this);
|
||||
|
||||
BCThemeSwitchButton* themeBtn = new BCThemeSwitchButton(this);
|
||||
statBar->addPermanentWidget(themeBtn);
|
||||
connect(themeBtn, &BCThemeSwitchButton::themeChanged, this, [this](bool isDark)
|
||||
BCThemeButton* themeBtn = new BCThemeButton(this);
|
||||
_statusBar->addPermanentWidget(themeBtn);
|
||||
connect(themeBtn, &BCThemeButton::themeChanged, this, [this](bool isDark)
|
||||
{
|
||||
QString message = isDark ? "Dark Mode Activated" : "Light Mode Activated";
|
||||
statusBar()->showMessage( message, 3000);
|
||||
setApplicationStyleSheet( isDark ? ":/claude_dark_mode.qss"_L1 : ":/claude_light_mode.qss"_L1 );
|
||||
QString message = isDark ? "using DarkMode." : "using LightMode.";
|
||||
onShowMessage( message );
|
||||
setApplicationStyleSheet( isDark ? cDarkModeStyle : cLightModeStyle );
|
||||
|
||||
});
|
||||
|
||||
// Wir starten im light mode
|
||||
//themeBtn->setDarkMode( false );
|
||||
|
||||
statBar->showMessage("Ready");
|
||||
onShowMessage("Ready. (Using dummy driver)");
|
||||
|
||||
setApplicationStyleSheet(cLightModeStyle);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -233,6 +239,7 @@ bool BCMainWindow::setApplicationStyleSheet( QAnyStringView path )
|
||||
return false;
|
||||
}
|
||||
qWarning() << "Konnte Stylesheet nicht laden:" << styleFile.errorString();
|
||||
//qApp->setStyleSheet(" ");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -247,59 +254,73 @@ void BCMainWindow::setHeaderLabel( const QString& headerText)
|
||||
_headerLabel->setText( " BionxControl: " + headerText );
|
||||
}
|
||||
|
||||
|
||||
void BCMainWindow::onShowMessage( const QString& message, int timeOut )
|
||||
{
|
||||
_statusbar->showMessage( message, timeOut );
|
||||
_statusBar->showMessage( message, timeOut );
|
||||
}
|
||||
|
||||
void BCMainWindow::autoConnect()
|
||||
|
||||
void BCMainWindow::onStartAnimation()
|
||||
{
|
||||
// __fix!
|
||||
// if( !connect)
|
||||
// fallBack
|
||||
_delightWidget->onStartChaos();
|
||||
}
|
||||
|
||||
|
||||
void BCMainWindow::onDriverStateChanged( BCDriver::DriverState state, const QString& message )
|
||||
{
|
||||
qDebug() << " --- on DriverStatusChanged: " << state << ":" << message;
|
||||
_statusbar->showMessage( message, 8000 );
|
||||
Q_UNUSED(state)
|
||||
onShowMessage( message, 8000 );
|
||||
}
|
||||
|
||||
void BCMainWindow::onShowDevicePanel( BCDevice::ID deviceID )
|
||||
{
|
||||
qDebug() << " --- onShowDevicePanel:" << deviceID;
|
||||
if( _devicePanels.contains( deviceID ) )
|
||||
{
|
||||
BCDeviceView* nxtPanel = _devicePanels[deviceID];
|
||||
if( nxtPanel != _currentPanel )
|
||||
{
|
||||
_currentPanel = nxtPanel;
|
||||
qDebug() << " --- Firz: " << _currentPanel->property( BCKeyHeaderLabel );
|
||||
setHeaderLabel( _currentPanel->property( BCKeyHeaderLabel ).toString() );
|
||||
_stackedWidget->setCurrentWidget( nxtPanel );
|
||||
|
||||
setHeaderLabel( _currentPanel->property( cBCKeyHeaderLabel ).toString() );
|
||||
_stackedWidget->setCurrentWidget( _currentPanel );
|
||||
if( _currentPanel->firstExpose() )
|
||||
{
|
||||
// Dummy sync beim starten
|
||||
QTimer::singleShot(1000, this, [this]()
|
||||
{
|
||||
onSyncDeviceView();
|
||||
});
|
||||
}
|
||||
// knopf auch abschalten?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BCMainWindow::onConnectButtonToggled(bool checked )
|
||||
{
|
||||
//_dataManager.setDriverConnectionState( checked );
|
||||
}
|
||||
/**
|
||||
* @brief SLOT, wird aufgerufen, wenn der Treiber eine frischen Wert abgeholt hat.
|
||||
*/
|
||||
|
||||
void BCMainWindow::onValueUpdated(BCDevice::ID deviceID, int index, BCValue::State state, const QString& newValue )
|
||||
void BCMainWindow::onValueUpdated(BCDevice::ID deviceID, int index, BCValue::Flags newState, uint32_t rawValue )
|
||||
{
|
||||
qDebug() << "Reply: from: " << deviceID << " at: " << index << "finished. Success:" << (uint8_t)state << " on:" << newValue;
|
||||
if( _devicePanels.contains( deviceID ) )
|
||||
{
|
||||
BCDeviceView& panel = *_devicePanels[deviceID];
|
||||
panel.onValueUpdated( index, state, newValue );
|
||||
panel.updateValue( index, newState, rawValue );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief SLOT, wird aufgerufen, wenn der Treiber die Datenübertrgeung beendet hat.
|
||||
*/
|
||||
|
||||
void BCMainWindow::onEndOfProcessing()
|
||||
{
|
||||
_syncButton->setEnabled( true );
|
||||
onShowMessage( "Synchronization complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SLOT, der aufgerufen wird, um das akutelle Device (Battery, Motor, ... )
|
||||
* zu synchronisieren, d.h. die aktuellen Werte über den CAN-Bus abzufragen.
|
||||
@@ -307,27 +328,28 @@ void BCMainWindow::onValueUpdated(BCDevice::ID deviceID, int index, BCValue::Sta
|
||||
|
||||
void BCMainWindow::onSyncDeviceView()
|
||||
{
|
||||
|
||||
Q_ASSERT_X(_currentPanel, "onSyncDeviceView()", "_currentpanel ist null!");
|
||||
const BCValueList& currentList =_currentPanel->getValueList();
|
||||
|
||||
qDebug() << " ---Syncing";
|
||||
// wir schalten den Sync-Button hier ab,
|
||||
// wenn der Autrag bearbeitet wurde, wird der
|
||||
// Button wieder eingeschaltet.
|
||||
_syncButton->setEnabled( false );
|
||||
|
||||
const BCValueList& currentList =_currentPanel->getValueListX();
|
||||
|
||||
// alle einzeln? echt jetzt?
|
||||
QString devName = _currentPanel->property( cBCKeyHeaderLabel ).toString();
|
||||
onShowMessage( "Reading: " + devName );
|
||||
|
||||
for( const BCValuePtr& value : currentList )
|
||||
{
|
||||
qDebug() << " --- begin sync of value: " << QThread::currentThreadId() << " : " << value->label;
|
||||
// wir setzen auf 'lesen'
|
||||
value->state.setFlag( BCValue::State::ReadMe );
|
||||
value->setFlag( BCValue::Flag::ReadMe );
|
||||
|
||||
// statt '_transmitter.onEnqueueValue( value )' müssen wir hier
|
||||
// statt '_transmitter.onUpdateValue( value )' müssen wir hier
|
||||
// über emit requestValueUpdate() zur Thread sysnchronisation
|
||||
// entkoppeln,
|
||||
|
||||
emit requestValueUpdate( value);
|
||||
|
||||
}
|
||||
|
||||
emit endOfTransmission();
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCMAINWINDOW_H
|
||||
#define BCMAINWINDOW_H
|
||||
#ifndef BC_MAINWINDOW_H
|
||||
#define BC_MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QThread>
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <ui_bcmainwindow.h>
|
||||
#include <bcxmlloader.h>
|
||||
#include <bctransmitter.h>
|
||||
#include <bcdelightpmwidget.h>
|
||||
|
||||
class BCDeviceView;
|
||||
|
||||
@@ -57,26 +58,27 @@ public slots:
|
||||
|
||||
//void onValueListReady( BCDevice::ID deviceID );
|
||||
void onShowDevicePanel( BCDevice::ID deviceID );
|
||||
void onConnectButtonToggled(bool active );
|
||||
void onDriverStateChanged( BCDriver::DriverState state, const QString& message="" );
|
||||
|
||||
// Slots für Rückmeldungen vom Transmitter
|
||||
void onValueUpdated( BCDevice::ID deviceID, int index, BCValue::State state, const QString& newValue="" );
|
||||
void onValueUpdated( BCDevice::ID deviceID, int index, BCValue::Flags newState, uint32_t rawValue );
|
||||
void onEndOfProcessing();
|
||||
void onSyncDeviceView();
|
||||
|
||||
void onShowMessage( const QString& message, int timeOut=3000);
|
||||
void onShowMessage( const QString& message, int timeOut=4000);
|
||||
void onStartAnimation();
|
||||
|
||||
signals:
|
||||
|
||||
// Internes Signal, um Daten an den Worker Thread zu senden
|
||||
void requestValueUpdate( BCValuePtrConst value);
|
||||
void endOfTransmission();
|
||||
|
||||
protected:
|
||||
|
||||
bool setApplicationStyleSheet( QAnyStringView path );
|
||||
void initMainWindow();
|
||||
void initStatusBar();
|
||||
void autoConnect();
|
||||
|
||||
//bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
@@ -86,15 +88,17 @@ protected:
|
||||
// und dem Device, das sie darstellen.
|
||||
|
||||
using BCDeviceViews = QHash<BCDevice::ID, BCDeviceView*>;
|
||||
BCDeviceViews _devicePanels;
|
||||
BCDeviceView* _currentPanel{};
|
||||
BCDeviceViews _devicePanels;
|
||||
BCDeviceView* _currentPanel{};
|
||||
BCDelightPMWidget* _delightWidget{};
|
||||
QThread _worker;
|
||||
BCTransmitter _transmitter;
|
||||
|
||||
QThread _worker;
|
||||
BCTransmitter _transmitter;
|
||||
|
||||
static constexpr const char* BCKeyHeaderLabel = "BCHeaderLabel";
|
||||
static constexpr const char* cBCKeyHeaderLabel = "BCHeaderLabel";
|
||||
static constexpr const char* cDarkModeStyle = ":bc_dark.qss";
|
||||
static constexpr const char* cLightModeStyle = ":bc_light.qss";
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // BCMAINWINDOW_H
|
||||
#endif // BC_MAINWINDOW_H
|
||||
|
||||
215
bcmainwindow.ui
215
bcmainwindow.ui
@@ -71,9 +71,15 @@
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">_buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
@@ -93,9 +99,15 @@
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">_buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
@@ -115,31 +127,18 @@
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_pimpButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">_buttonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -157,17 +156,73 @@
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_syncButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sync</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_connectButton">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QToolButton" name="_exitButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Quit application.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Quit</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<normaloff>:/exit_red.png</normaloff>:/exit_red.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
@@ -190,7 +245,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="BCDeviceView" name="_consolePanel">
|
||||
<property name="frameShape">
|
||||
@@ -202,6 +257,9 @@
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -231,6 +289,9 @@
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -260,6 +321,12 @@
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -279,62 +346,17 @@
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="BCDeviceView" name="_pimpPanel">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::PenStyle::NoPen</enum>
|
||||
</property>
|
||||
<property name="BCHeaderLabel" stdset="0">
|
||||
<string>Pimp my Ride ...</string>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="_statusbar">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: #DADADA</string>
|
||||
</property>
|
||||
</widget>
|
||||
<action name="_pimpAction">
|
||||
<widget class="QStatusBar" name="_statusBar"/>
|
||||
<action name="_motorAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:restart.png</normaloff>:restart.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>pimp</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Pimp my Ride</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_motorAction">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:bionx_motor.png</normaloff>:bionx_motor.png</iconset>
|
||||
@@ -343,10 +365,13 @@
|
||||
<string>motor</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show motor settings</string>
|
||||
<string>Show and edit motor settings.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_batteryAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:bionx_akku.png</normaloff>:bionx_akku.png</iconset>
|
||||
@@ -355,10 +380,13 @@
|
||||
<string>battery</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show battery settings</string>
|
||||
<string>Show and edit battery settings.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_consoleAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:bionx_console.png</normaloff>:bionx_console.png</iconset>
|
||||
@@ -367,31 +395,37 @@
|
||||
<string>console</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show console settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_exitAction">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:exit.png</normaloff>:exit.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Exit</string>
|
||||
<string>Show and edit console settings.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_connectAction">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<normaloff>:/connected.png</normaloff>:/connected.png</iconset>
|
||||
<normaloff>:/connect.png</normaloff>:/connect.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>connect</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>connect to bike</string>
|
||||
<string>Load TinyCAN native driver.</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::TextHeuristicRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="_syncAction">
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<normaloff>:/sync.png</normaloff>:/sync.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>sync</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Synchronise with eBike settings.</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::TextHeuristicRole</enum>
|
||||
@@ -409,4 +443,7 @@
|
||||
<include location="bionxcontrol.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="_buttonGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
||||
80
bcthemebutton.cpp
Normal file
80
bcthemebutton.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <bcthemebutton.h>
|
||||
|
||||
|
||||
BCThemeButton::BCThemeButton(QWidget *parent )
|
||||
: QPushButton(parent)
|
||||
{
|
||||
// Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
||||
setFlat(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
setFixedSize( 24, 24 );
|
||||
updateIcon();
|
||||
|
||||
connect(this, &QPushButton::clicked, this, &BCThemeButton::toggleMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Setzt den DarkMode
|
||||
*/
|
||||
|
||||
void BCThemeButton::setDarkMode( bool isDark )
|
||||
{
|
||||
_isDarkMode = !isDark;
|
||||
toggleMode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Schaltet den akutellen Mode um.
|
||||
*/
|
||||
|
||||
void BCThemeButton::toggleMode()
|
||||
{
|
||||
_isDarkMode = !_isDarkMode;
|
||||
updateIcon();
|
||||
emit themeChanged(_isDarkMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Icon & Tooltip anpassen
|
||||
*/
|
||||
|
||||
void BCThemeButton::updateIcon()
|
||||
{
|
||||
setText(_isDarkMode ? "🌙" : "☀️");
|
||||
setToolTip(_isDarkMode ? "Use LightMode" : "Use DarkMode");
|
||||
}
|
||||
72
bcthemebutton.h
Normal file
72
bcthemebutton.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BC_THEMESWITCHBUTTON_H
|
||||
#define BC_THEMESWITCHBUTTON_H
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include <bcdriver.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Einfaches Buttonwidget, um zwischen Dark- und Lightmode
|
||||
* zu wechseln
|
||||
*/
|
||||
|
||||
class BCThemeButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCThemeButton(QWidget *parent = nullptr);
|
||||
void setDarkMode( bool isDark );
|
||||
|
||||
signals:
|
||||
|
||||
void themeChanged(bool isDark);
|
||||
|
||||
private slots:
|
||||
|
||||
void toggleMode();
|
||||
|
||||
private:
|
||||
|
||||
void updateIcon();
|
||||
|
||||
bool _isDarkMode{false};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // BC_THEMESWITCHBUTTON_H
|
||||
234
bctoggleswitch.cpp
Normal file
234
bctoggleswitch.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "bctoggleswitch.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QEasingCurve>
|
||||
#include <QEnterEvent>
|
||||
#include <QEvent>
|
||||
|
||||
BCToggleSwitch::BCToggleSwitch(QWidget *parent)
|
||||
: QAbstractButton(parent)
|
||||
, m_position(0.0f)
|
||||
{
|
||||
setCheckable(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
|
||||
// Widget ist jetzt mit setGeometry / Layouts skalierbar
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
|
||||
// Animation initialisieren
|
||||
m_animation = new QPropertyAnimation(this, "position", this);
|
||||
m_animation->setDuration(200);
|
||||
m_animation->setEasingCurve(QEasingCurve::OutQuad);
|
||||
|
||||
// Signal verknüpfen
|
||||
connect(this, &QAbstractButton::toggled, this, [this](bool checked)
|
||||
{
|
||||
m_animation->stop();
|
||||
m_animation->setStartValue(m_position);
|
||||
m_animation->setEndValue(checked ? 1.0f : 0.0f);
|
||||
m_animation->start();
|
||||
});
|
||||
}
|
||||
|
||||
float BCToggleSwitch::position() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
void BCToggleSwitch::setPosition(float pos)
|
||||
{
|
||||
m_position = pos;
|
||||
update(); // Trigger Repaint
|
||||
}
|
||||
|
||||
QSize BCToggleSwitch::sizeHint() const
|
||||
{
|
||||
return QSize(44, 22);
|
||||
}
|
||||
|
||||
QSize BCToggleSwitch::minimumSizeHint() const
|
||||
{
|
||||
return QSize(30, 16);
|
||||
}
|
||||
|
||||
void BCToggleSwitch::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QRect ownRect = rect();
|
||||
|
||||
// Standard-Hintergrundfarbe des aktuellen Qt-Themes
|
||||
p.fillRect(ownRect, palette().window());
|
||||
|
||||
// Auf deaktivierten Zustand prüfen und die statische Methode aufrufen
|
||||
if (!isEnabled()) {
|
||||
paintToggleIndicator(&p, ownRect, isChecked(), m_position, palette());
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Farben aus der aktuellen Palette ---
|
||||
QColor onColor = palette().color(QPalette::Highlight);
|
||||
QColor offBorderColor = palette().color(QPalette::Mid);
|
||||
QColor offKnobColor = palette().color(QPalette::Dark);
|
||||
QColor knobOnColor = palette().color(QPalette::HighlightedText);
|
||||
|
||||
// Proportionale Werte aus der Widget-Höhe ableiten
|
||||
qreal h = ownRect.height();
|
||||
qreal radius = h / 2.0;
|
||||
qreal penW = qMax(1.0, h / 14.0); // Strichstärke skaliert mit
|
||||
qreal padding = qMax(2.0, h * 0.14); // Innenabstand skaliert mit
|
||||
|
||||
// 1. Hintergrund (Track) zeichnen
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
if (isChecked() || m_position > 0.5f)
|
||||
{
|
||||
// AN-Zustand: Hintergrund gefüllt
|
||||
p.setBrush(onColor);
|
||||
p.drawRoundedRect(ownRect, radius, radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
// AUS-Zustand: Nur Rahmen
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
// Hover-Status prüfen
|
||||
if (underMouse())
|
||||
p.setPen(QPen(offBorderColor.darker(120), penW));
|
||||
else
|
||||
p.setPen(QPen(offBorderColor, penW));
|
||||
|
||||
// Rechteck etwas verkleinern, damit der Rahmen nicht abgeschnitten wird
|
||||
qreal inset = penW / 2.0;
|
||||
p.drawRoundedRect(QRectF(ownRect).adjusted(inset, inset, -inset, -inset),
|
||||
radius - inset, radius - inset);
|
||||
}
|
||||
|
||||
// 2. Knopf (Thumb) zeichnen
|
||||
qreal knobDiameter = h - (2 * padding);
|
||||
|
||||
// Interpolation der Position
|
||||
qreal startX = padding;
|
||||
qreal endX = ownRect.width() - knobDiameter - padding;
|
||||
qreal currentX = startX + (m_position * (endX - startX));
|
||||
|
||||
QRectF knobRect(currentX, padding, knobDiameter, knobDiameter);
|
||||
|
||||
if (isChecked() || m_position > 0.5f)
|
||||
{
|
||||
p.setBrush(knobOnColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (underMouse())
|
||||
p.setBrush(offKnobColor.darker(110));
|
||||
else
|
||||
p.setBrush(offKnobColor);
|
||||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawEllipse(knobRect);
|
||||
}
|
||||
|
||||
void BCToggleSwitch::paintToggleIndicator(QPainter* p, const QRect& rect, bool isChecked, float position, const QPalette& palette)
|
||||
{
|
||||
// --- Farben für den deaktivierten Zustand aus der Palette ---
|
||||
QColor disabledBorderColor = palette.color(QPalette::Disabled, QPalette::Mid);
|
||||
QColor disabledKnobColor = palette.color(QPalette::Disabled, QPalette::Dark);
|
||||
QColor disabledOnColor = palette.color(QPalette::Disabled, QPalette::Highlight);
|
||||
QColor disabledKnobOnColor = palette.color(QPalette::Disabled, QPalette::HighlightedText);
|
||||
|
||||
QRectF r(rect);
|
||||
qreal h = r.height();
|
||||
qreal radius = h / 2.0;
|
||||
qreal penW = qMax(1.0, h / 14.0);
|
||||
qreal padding = qMax(2.0, h * 0.14);
|
||||
|
||||
// 1. Hintergrund (Track) zeichnen
|
||||
p->setPen(Qt::NoPen);
|
||||
|
||||
if (isChecked || position > 0.5f)
|
||||
{
|
||||
// AN-Zustand (deaktiviert)
|
||||
p->setBrush(disabledOnColor);
|
||||
p->drawRoundedRect(r, radius, radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
// AUS-Zustand (deaktiviert)
|
||||
p->setBrush(Qt::NoBrush);
|
||||
p->setPen(QPen(disabledBorderColor, penW));
|
||||
qreal inset = penW / 2.0;
|
||||
p->drawRoundedRect(r.adjusted(inset, inset, -inset, -inset),
|
||||
radius - inset, radius - inset);
|
||||
}
|
||||
|
||||
// 2. Knopf (Thumb) zeichnen
|
||||
qreal knobDiameter = h - (2 * padding);
|
||||
|
||||
// X- und Y-Offsets des übergebenen Rects berücksichtigen!
|
||||
qreal startX = r.x() + padding;
|
||||
qreal endX = r.x() + r.width() - knobDiameter - padding;
|
||||
qreal currentX = startX + (position * (endX - startX));
|
||||
|
||||
QRectF knobRect(currentX, r.y() + padding, knobDiameter, knobDiameter);
|
||||
|
||||
p->setPen(Qt::NoPen);
|
||||
|
||||
if (isChecked || position > 0.5f)
|
||||
{
|
||||
p->setBrush(disabledKnobOnColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->setBrush(disabledKnobColor);
|
||||
}
|
||||
|
||||
p->drawEllipse(knobRect);
|
||||
}
|
||||
|
||||
void BCToggleSwitch::enterEvent(QEnterEvent *event)
|
||||
{
|
||||
update(); // Für Hover-Effekt neu zeichnen
|
||||
QAbstractButton::enterEvent(event);
|
||||
}
|
||||
|
||||
void BCToggleSwitch::leaveEvent(QEvent *event)
|
||||
{
|
||||
update(); // Hover entfernen
|
||||
QAbstractButton::leaveEvent(event);
|
||||
}
|
||||
41
bctoggleswitch.h
Normal file
41
bctoggleswitch.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef BC_TOGGLESWITCH_H
|
||||
#define BC_TOGGLESWITCH_H
|
||||
|
||||
#include <QAbstractButton>
|
||||
|
||||
|
||||
class QPropertyAnimation;
|
||||
|
||||
class BCToggleSwitch : public QAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
// Property für die Animation (0.0 bis 1.0)
|
||||
Q_PROPERTY(float position READ position WRITE setPosition)
|
||||
|
||||
public:
|
||||
|
||||
explicit BCToggleSwitch(QWidget *parent = nullptr);
|
||||
|
||||
// Getter & Setter für die Animations-Property
|
||||
float position() const;
|
||||
void setPosition(float pos);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
// Statische Methode zum Zeichnen des passiven/deaktivierten Zustands
|
||||
static void paintToggleIndicator(QPainter* p, const QRect& rect, bool isChecked, float position, const QPalette& palette);
|
||||
|
||||
protected:
|
||||
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void enterEvent(QEnterEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
private:
|
||||
|
||||
float m_position; // 0.0 = Aus, 1.0 = An
|
||||
QPropertyAnimation* m_animation;
|
||||
};
|
||||
|
||||
#endif // BC_TOGGLESWITCH_H
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <bctransmitter.h>
|
||||
|
||||
@@ -40,7 +41,7 @@
|
||||
*/
|
||||
|
||||
BCTransmitter::BCTransmitter(QObject *parent)
|
||||
: QObject(parent), _isBusy(false)
|
||||
: QObject(parent)//, _isBusy(false)
|
||||
{
|
||||
//_canDriver = new BCDriverTinyCan{this};
|
||||
_canDriver = &_dummyDriver;
|
||||
@@ -55,27 +56,23 @@ BCTransmitter::BCTransmitter(QObject *parent)
|
||||
|
||||
void BCTransmitter::onToggleDriverConnection( bool connect )
|
||||
{
|
||||
qDebug() << " --- onToggleDriverConnection: " << connect;
|
||||
// FIX! Ende der current op abwarten!
|
||||
if( connect )
|
||||
emit driverStateChanged(BCDriver::DriverState::NotPresent, "Native Treiber wird geladen.");
|
||||
|
||||
/*
|
||||
// kill all pending stuff
|
||||
//QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
|
||||
BCDriver::DriverState state = connect ? BCDriver::DriverState::DeviceReady : BCDriver::DriverState::NotPresent;
|
||||
const QString& message = connect ? "Trying to connect" : " FAILED";
|
||||
emit driverStateChanged(state, message);
|
||||
return;
|
||||
*/
|
||||
|
||||
// Hier sind wir noch in GUI Thread
|
||||
QMutexLocker locker(&_mutex);
|
||||
// weitere operation stoppen
|
||||
_isBusy = true;
|
||||
connect ? connectCanDriver() : disconnectCanDriver();
|
||||
_isBusy = false;
|
||||
}
|
||||
|
||||
|
||||
void BCTransmitter::onStartNativeDriver()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BCTransmitter::connectCanDriver()
|
||||
{
|
||||
// hier gehts nur um den echten Treiber
|
||||
@@ -85,137 +82,111 @@ void BCTransmitter::connectCanDriver()
|
||||
if( _tinyCanDriver.getDriverState() != BCDriver::DriverState::DeviceReady )
|
||||
result = _tinyCanDriver.loadAndStartDriver();
|
||||
|
||||
QString message("FitzeFatze!");
|
||||
// hat geklappt
|
||||
if( _tinyCanDriver.getDriverState() >= BCDriver::DriverState::Opened )
|
||||
{
|
||||
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
|
||||
uint8_t hwRev = static_cast<uint8_t> (BC::ID::Cons_Rev_Hw);
|
||||
|
||||
TransmitResult hwVersion = _tinyCanDriver.readRawByte( console, hwRev);
|
||||
if( hwVersion.has_value() )
|
||||
QString message("Treiber geladen (nicht verbunden)");
|
||||
|
||||
// Der result-Wert im ERfolgsfall ist der driver state.
|
||||
if(result.has_value() )
|
||||
{
|
||||
switch( result.value() )
|
||||
{
|
||||
message = " ---- HAIL to the king!";
|
||||
qDebug() << message;
|
||||
// swap driver
|
||||
_canDriver = &_tinyCanDriver;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Console not responding";
|
||||
case BCDriver::DriverState::Opened:
|
||||
|
||||
message = "Treiber geladen (Device antwortet nicht)";
|
||||
break;
|
||||
|
||||
case BCDriver::DriverState::DeviceReady:
|
||||
|
||||
message = "Treiber geladen und Device verbunden.";
|
||||
// swap driver
|
||||
_canDriver = &_tinyCanDriver;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
else // Fehlerfall, wir holen die Fehlermeldung
|
||||
{
|
||||
message = result.error();
|
||||
}
|
||||
|
||||
emit driverStateChanged( _tinyCanDriver.getDriverState(), message );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Native-Treiber zurücksetzen, Dummy-Treiber wieder aktivieren.
|
||||
*/
|
||||
|
||||
void BCTransmitter::disconnectCanDriver()
|
||||
{
|
||||
_tinyCanDriver.resetDriver();
|
||||
_canDriver = &_dummyDriver;
|
||||
emit driverStateChanged( _tinyCanDriver.getDriverState(), "Disconnected" );
|
||||
emit driverStateChanged( _tinyCanDriver.getDriverState(), "Disconnected, Dummy Treiber aktiviert." );
|
||||
}
|
||||
|
||||
|
||||
void BCTransmitter::onEnqueueValue( BCValuePtrConst value)
|
||||
void BCTransmitter::onUpdateValue( BCValuePtrConst valuePtr)
|
||||
{
|
||||
|
||||
// wir stellen hier auf die arte Tour sicher, das onEnqueueValue
|
||||
// wir stellen hier auf die harte Tour sicher, das onUpdateValue
|
||||
// nicht aus dem Parent-Thread direkt sondern über die EventQueue aufgerufen wurde.
|
||||
|
||||
Q_ASSERT(QThread::currentThread() == this->thread());
|
||||
|
||||
// Hier sind wir noch in GUI Thread
|
||||
//QMutexLocker locker(&_mutex);
|
||||
_valueQueue.enqueue( value );
|
||||
// Wir arbeiten hier ohne besondere Threadsynchronisation, mutexed o.ä: Die
|
||||
// entkoppelung und serialisierung passiert bereits durch die Qt-Eventqueue.
|
||||
// Das klappt aber nur in der hier gewählten Konstellation mit einer Parent-Thread
|
||||
// und einem Worker.
|
||||
|
||||
// wir wollen nicht den ganzen Value verschicken, erstrecht
|
||||
// wollen wir nicht den Value in verschiedenen Threads gleichzeitig
|
||||
// in die Hand nehmen, also hantieren wir nur mit den Inidizes.
|
||||
// Kosmetik
|
||||
const BCValue& value = *(valuePtr.get());
|
||||
|
||||
// Trigger processing im Event-Loop des Worker Threads
|
||||
// invokeMethod mit QueuedConnection entkoppelt den Aufruf,
|
||||
// damit onEnqueueValue sofort zurückkehrt (non-blocking für den Aufrufer).
|
||||
uint32_t devID = static_cast<uint32_t>(value.deviceID());
|
||||
uint8_t regID = static_cast<uint8_t> (value.registerID());
|
||||
|
||||
//QMetaObject::invokeMethod(this, "onProcessValue", Qt::QueuedConnection);
|
||||
onProcessValue();
|
||||
}
|
||||
// Für den Fehlerfall: Wir senden den alten Wert einfach zurück
|
||||
uint32_t newValue = value.rawValue();
|
||||
BCValue::Flag newState = BCValue::Flag::Failed;
|
||||
|
||||
void BCTransmitter::onProcessValue()
|
||||
{
|
||||
|
||||
//if (_isBusy)
|
||||
// return;
|
||||
|
||||
_isBusy = true;
|
||||
|
||||
while (true)
|
||||
if(value.testFlag( BCValue::Flag::WriteMe ) )
|
||||
{
|
||||
BCValuePtrConst valuePtr{};
|
||||
{
|
||||
//QMutexLocker locker(&_mutex);
|
||||
if (_valueQueue.isEmpty())
|
||||
{
|
||||
_isBusy = false;
|
||||
break; // Schleife verlassen, warten auf neue Events
|
||||
}
|
||||
valuePtr =_valueQueue.dequeue();
|
||||
} // Mutex wird hier freigegeben! WICHTIG: Execute ohne Lock!
|
||||
|
||||
// Kosmetik
|
||||
const BCValue& value = *(valuePtr.get());
|
||||
|
||||
qDebug() << "------- DE.-.QUEUE: " << QThread::currentThreadId() << ": " << value.label;
|
||||
|
||||
// Value ist 'under construction'
|
||||
//emit valueUpdated( value.deviceID, value.indexRow, BCValue::State::Locked );
|
||||
|
||||
|
||||
uint32_t devID = static_cast<uint32_t>(value.deviceID);
|
||||
uint8_t regID = static_cast<uint8_t> (value.registerID);
|
||||
|
||||
QString newVisibleValue;
|
||||
BCValue::State newState = BCValue::State::NoState;
|
||||
|
||||
if(value.state.testFlag( BCValue::State::WriteMe ) )
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
// oder sollen wir hier beides erlauben ? readFlag & writeFlag ?
|
||||
// Was kommt dann zuerst? Schreiben und lesen als verify ?
|
||||
|
||||
else if( value.state.testFlag( BCValue::State::ReadMe ) )
|
||||
{
|
||||
// wir sind hier im anderen thread! nicht einfach so reinschreiben, nur lesen
|
||||
TransmitResult result = value.isWord ? readWordValue( devID, regID ) : readByteValue( devID, regID );
|
||||
if( result.has_value() )
|
||||
{
|
||||
newVisibleValue = value.formatValue( result.value() );
|
||||
newState = BCValue::State::InSync;
|
||||
}
|
||||
else
|
||||
{
|
||||
newState = BCValue::State::Failed;
|
||||
}
|
||||
}
|
||||
|
||||
emit valueUpdated( value.deviceID, value.indexRow, newState, newVisibleValue );
|
||||
|
||||
// __fix
|
||||
//bc::processEventsFor(150);
|
||||
bc::delay_millis(150);
|
||||
|
||||
}
|
||||
// oder sollen wir hier beides erlauben ? readFlag & writeFlag ?
|
||||
// Was kommt dann zuerst? Schreiben und lesen als verify ?
|
||||
|
||||
else if( value.testFlag( BCValue::Flag::ReadMe ) )
|
||||
{
|
||||
// wir sind hier im anderen thread! nicht einfach so reinschreiben, nur lesen
|
||||
TransmitResult result = value.isWord() ? readWordValue( devID, regID ) : readByteValue( devID, regID );
|
||||
if( result.has_value() )
|
||||
{
|
||||
newState = BCValue::Flag::InSync;
|
||||
newValue = result.value();
|
||||
}
|
||||
}
|
||||
|
||||
emit valueUpdated( value.deviceID(), value.indexRow(), newState, newValue );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wenn dieser SLOT in der Event-Queue erreicht wird, dedeutet dies, das die
|
||||
* Übertrgung vom Mainwindow abgeschlossen wurde. Wir schicken zur Bestätigung das
|
||||
* Signal 'endOfProcessing' (Welches dann den 'Sync' - Button wieder einschaltet.
|
||||
*/
|
||||
|
||||
void BCTransmitter::onEndOfTransmission()
|
||||
{
|
||||
emit endOfProcessing();
|
||||
}
|
||||
|
||||
|
||||
TransmitResult BCTransmitter::readByteValue( uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
//qDebug() << " --- YES: Read ByteValue: " << registerID;
|
||||
// Wir lesen nur ein Byte und gut.
|
||||
return _canDriver->readRawByte( deviceID, registerID );
|
||||
}
|
||||
@@ -223,8 +194,6 @@ TransmitResult BCTransmitter::readByteValue( uint32_t deviceID, uint8_t register
|
||||
|
||||
TransmitResult BCTransmitter::readWordValue( uint32_t deviceID, uint8_t registerID )
|
||||
{
|
||||
//qDebug() << " --- YES: Read WordValue: " << registerID;
|
||||
|
||||
uint32_t result{};
|
||||
// hi byte Leseversuch.
|
||||
TransmitResult value = _canDriver->readRawByte( deviceID, registerID );
|
||||
|
||||
@@ -30,13 +30,12 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCTRANSMITTER_H
|
||||
#define BCTRANSMITTER_H
|
||||
#ifndef BC_TRANSMITTER_H
|
||||
#define BC_TRANSMITTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QMutex>
|
||||
#include <atomic>
|
||||
|
||||
#include <bcvalue.h>
|
||||
#include <bcdrivertinycan.h>
|
||||
@@ -63,13 +62,13 @@ public:
|
||||
public slots:
|
||||
|
||||
void onToggleDriverConnection( bool connect );
|
||||
void onEnqueueValue(BCValuePtrConst value );
|
||||
void onProcessValue();
|
||||
void onStartNativeDriver();
|
||||
void onUpdateValue(BCValuePtrConst valuePtr );
|
||||
void onEndOfTransmission();
|
||||
|
||||
signals:
|
||||
|
||||
void valueUpdated(BCDevice::ID deviceID, int index, BCValue::State state, const QString& newValue="" );
|
||||
void endOfProcessing();
|
||||
void valueUpdated(BCDevice::ID deviceID, int index, BCValue::Flag state, uint32_t rawValue );
|
||||
void driverStateChanged( BCDriver::DriverState state, const QString& message="" );
|
||||
|
||||
private:
|
||||
@@ -80,13 +79,6 @@ private:
|
||||
TransmitResult readByteValue( uint32_t deviceID, uint8_t registerID );
|
||||
TransmitResult readWordValue( uint32_t deviceID, uint8_t registerID );
|
||||
|
||||
using BCDataQueue = QQueue<BCValuePtrConst>;
|
||||
|
||||
BCDataQueue _valueQueue;
|
||||
QMutex _mutex;
|
||||
std::atomic<bool> _isBusy{ false };
|
||||
|
||||
// __fix!
|
||||
BCDriver* _canDriver{};
|
||||
BCDriverTinyCan _tinyCanDriver{};
|
||||
BCDriverDummy _dummyDriver{};
|
||||
@@ -94,4 +86,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif // BCTRANSMITTER_H
|
||||
#endif // BC_TRANSMITTER_H
|
||||
|
||||
245
bcvalue.cpp
245
bcvalue.cpp
@@ -31,6 +31,7 @@
|
||||
|
||||
|
||||
#include <QMetaEnum>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <bcvalue.h>
|
||||
|
||||
@@ -39,28 +40,252 @@
|
||||
|
||||
|
||||
BCValue::BCValue( BCDevice::ID deviceID_, BC::ID registerID_)
|
||||
: deviceID{deviceID_}, registerID{registerID_}
|
||||
: _deviceID{deviceID_}, _registerID{registerID_}
|
||||
{
|
||||
visibleValue = "--";
|
||||
|
||||
}
|
||||
|
||||
QString BCValue::formatValue( uint32_t value ) const
|
||||
QString BCValue::formatValue() const
|
||||
{
|
||||
if( factor == 1 )
|
||||
return QString::number( value );
|
||||
if( _factor == 1 )
|
||||
return QString::number( _rawValue );
|
||||
|
||||
double result = value * factor;
|
||||
double result =_rawValue * _factor;
|
||||
return QString::number(result, 'f', 2);
|
||||
}
|
||||
|
||||
bool BCValue::isWord() const
|
||||
{
|
||||
return _valueFlags.testFlag(BCValue::Flag::IsWord);
|
||||
}
|
||||
|
||||
bool BCValue::isReadOnly() const
|
||||
{
|
||||
return _valueFlags.testFlag(BCValue::Flag::ReadOnly);
|
||||
}
|
||||
|
||||
bool BCValue::isBoolean() const
|
||||
{
|
||||
return valueType() == BCValue::ValueType::Bool;
|
||||
}
|
||||
|
||||
bool BCValue::isChecked() const
|
||||
{
|
||||
return isBoolean() && rawValue() == 1;
|
||||
}
|
||||
|
||||
bool BCValue::testFlag( BCValue::Flag flag ) const
|
||||
{
|
||||
return _valueFlags.testFlag( flag );
|
||||
}
|
||||
|
||||
|
||||
void BCValue::setFlag( BCValue::Flag flag, bool state) const
|
||||
{
|
||||
_valueFlags.setFlag( flag, state );
|
||||
}
|
||||
|
||||
|
||||
BCDevice::ID BCValue::deviceID() const noexcept
|
||||
{
|
||||
return _deviceID;
|
||||
}
|
||||
|
||||
BC::ID BCValue::registerID() const noexcept
|
||||
{
|
||||
return _registerID;
|
||||
}
|
||||
|
||||
uint32_t BCValue::rawValue() const noexcept
|
||||
{
|
||||
return _rawValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Speichert einen via CAN-Bus gelesenen Wert in
|
||||
* der BCValue Struktur.
|
||||
*/
|
||||
|
||||
void BCValue::setRawValue(uint32_t newRawValue) const
|
||||
{
|
||||
// die per Zufallsgenerator erzeugten Werte des Dummy-Treibers
|
||||
// können beliebigen Unsinn enthalten, also müssen wir sie
|
||||
// auch skalieren.
|
||||
|
||||
if( _valueType == ValueType::Bool )
|
||||
{
|
||||
_rawValue = newRawValue > 0 ? 1 : 0;
|
||||
return;
|
||||
}
|
||||
|
||||
double value = newRawValue * _factor;
|
||||
|
||||
if( _optMin.has_value() && _optMax.has_value() )
|
||||
{
|
||||
|
||||
double min = _optMin.value();
|
||||
double max = _optMax.value();
|
||||
|
||||
value = (int) qBound( min,value, max);
|
||||
}
|
||||
|
||||
_rawValue = value / _factor;
|
||||
}
|
||||
|
||||
|
||||
BCValue::ValueType BCValue::valueType() const noexcept
|
||||
{
|
||||
return _valueType;
|
||||
}
|
||||
|
||||
|
||||
int BCValue::indexRow() const noexcept
|
||||
{
|
||||
return _indexRow;
|
||||
}
|
||||
|
||||
void BCValue::setIndexRow(int newIndexRow)
|
||||
{
|
||||
_indexRow = newIndexRow;
|
||||
}
|
||||
|
||||
QString BCValue::label() const
|
||||
{
|
||||
return _label;
|
||||
}
|
||||
|
||||
QString BCValue::unitLabel() const
|
||||
{
|
||||
return _unitLabel;
|
||||
}
|
||||
|
||||
void BCValue::setFromDouble( double value )
|
||||
{
|
||||
//if( _isReadOnly)
|
||||
switch(_valueType)
|
||||
{
|
||||
|
||||
// wir betrachten plain
|
||||
|
||||
case ValueType::Bool :
|
||||
_rawValue = value > 0 ? 1 : 0;
|
||||
break;
|
||||
|
||||
case ValueType::Plain :
|
||||
case ValueType::Number:
|
||||
case ValueType::Float:
|
||||
|
||||
if( _optMin.has_value() && _optMax.has_value() )
|
||||
{
|
||||
|
||||
double min = _optMin.value();
|
||||
double max = _optMax.value();
|
||||
|
||||
value = qBound( min,value,max);
|
||||
}
|
||||
_rawValue = value / _factor;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
double BCValue::calcMinMaxRatio() const
|
||||
{
|
||||
|
||||
double ratio = 1;
|
||||
|
||||
if( _optMin.has_value() && _optMax.has_value() )
|
||||
{
|
||||
|
||||
double min = _optMin.value();
|
||||
double max = _optMax.value();
|
||||
|
||||
double range = max - min;
|
||||
|
||||
// Safety: Division durch Null verhindern (wenn min == max)
|
||||
if (std::abs(range) < 1e-9)
|
||||
return ratio;
|
||||
|
||||
double value = _rawValue * _factor;
|
||||
// Die eigentliche Formel
|
||||
ratio = ((value - min) / range);
|
||||
}
|
||||
return ratio;
|
||||
}
|
||||
|
||||
|
||||
bool BCValue::hasValuesForSlider(ValueRange& valueRange) const
|
||||
{
|
||||
valueRange.value = valueRange.min = valueRange.max = 0;
|
||||
|
||||
// min & max sind vorraussetzung für den slider
|
||||
if( !_optMin.has_value() || !_optMax.has_value() )
|
||||
return false;
|
||||
|
||||
// wir erwarten hier, das value zwischen min
|
||||
// und max liegt weil wir das schon bei setRawValue
|
||||
// überprüft haben.
|
||||
|
||||
valueRange.value = _rawValue * _factor;
|
||||
valueRange.min = _optMin.value();
|
||||
valueRange.max = _optMax.value();
|
||||
valueRange.ratio = calcMinMaxRatio();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BCValue::dumpValue() const
|
||||
{
|
||||
|
||||
qDebug() << "DeviceID: " << deviceID << " Register: " << registerID << " state:" " << state << " << " label: " << label;
|
||||
qDebug() << "visibleValue: " << visibleValue << " min: " << min << " max: " << max << " factor: " << factor << " ValueType: " << (char)valueType << " ";
|
||||
qDebug() << "indexRow: " << indexRow << " isWord: " << isWord;
|
||||
qDebug() << "DeviceID: " << _deviceID << " Register: " << _registerID << " state:" " << state << " << " label: " << _label;
|
||||
qDebug() << "formattedValue: " << formatValue() << " min: " << _optMin << " max: " << _optMax << " factor: " << _factor << " ValueType: " << (char)_valueType << " ";
|
||||
qDebug() << "indexRow: " << _indexRow << " isWord: " << isWord() << " isRO: " << isReadOnly();
|
||||
qDebug();
|
||||
|
||||
}
|
||||
|
||||
/// ----
|
||||
QString BCValue::toString() const
|
||||
{
|
||||
QString result;
|
||||
QTextStream stream(&result);
|
||||
|
||||
stream << *this;
|
||||
|
||||
/*
|
||||
qDebug() << "DeviceID: " << _deviceID << " Register: " << _registerID << " state:" " << state << " << " label: " << _label;
|
||||
qDebug() << "formattedValue: " << formatValue() << " min: " << _optMin << " max: " << _optMax << " factor: " << _factor << " ValueType: " << (char)_valueType << " ";
|
||||
qDebug() << "indexRow: " << _indexRow << " isWord: " << isWord() << " isRO: " << isReadOnly();
|
||||
qDebug();
|
||||
*/
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Generischer Operator für ALLE Q_GADGETs
|
||||
inline QTextStream& operator<<(QTextStream& out, const BCValue& obj)
|
||||
{
|
||||
const QMetaObject* meta = &obj.staticMetaObject;
|
||||
|
||||
out << meta->className() << " { ";
|
||||
|
||||
// Iteriere über alle Properties (Reflection)
|
||||
for (int i = 0; i < meta->propertyCount(); ++i) {
|
||||
QMetaProperty prop = meta->property(i);
|
||||
const char* propName = prop.name();
|
||||
QVariant val = prop.readOnGadget(&obj);
|
||||
|
||||
out << propName << ": " << val.toString();
|
||||
|
||||
if (i < meta->propertyCount() - 1) out << ", ";
|
||||
}
|
||||
out << " }";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
124
bcvalue.h
124
bcvalue.h
@@ -6,7 +6,7 @@
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
mhsMEMBER _canMEMBER _drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
@@ -30,18 +30,14 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCVALUE_H
|
||||
#define BCVALUE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#ifndef BC_VALUEMEMBER_H
|
||||
#define BC_VALUEMEMBER_H
|
||||
|
||||
#include <expected>
|
||||
#include <bc.h>
|
||||
|
||||
|
||||
#include <bc.h>
|
||||
|
||||
/*
|
||||
Werte haben verschiedene Längen (1,2 und 4 Byte) und werder auf unterschiedliche Art und Weise
|
||||
ausgelesen und geschrieben (Siehe BCValueTypeWord). Sie können also Wert-Typen zugeordnet werden. Ein Werttyp
|
||||
@@ -60,11 +56,14 @@ using OptDouble = std::optional<double>;
|
||||
|
||||
// Enthält den gelesenen Wert oder einen Fehlerstring
|
||||
using TransmitResult = std::expected<uint32_t,QString>;
|
||||
// Funktionsobject, um Werte aus der Transmitterschicht zu holden
|
||||
//using ReadValueFunc = std::function<TransmitResult( const BCAbstractTransmitter& transmitter, uint32_t deviceID, uint8_t registerID )>;
|
||||
// Funktionsobject, um Werte aus der Transmitterschicht zu holen
|
||||
//using ReadValueFunc = std::function<TransmitResult( const BCAbstractTransmitter& transmitter, uint32MEMBER _t deviceID, uint8MEMBER _t registerID )>;
|
||||
|
||||
class BCValue
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
friend class BCXmlLoader;
|
||||
|
||||
public:
|
||||
|
||||
@@ -72,60 +71,105 @@ public:
|
||||
// später der Editor
|
||||
enum class ValueType : uint8_t
|
||||
{
|
||||
Plain,
|
||||
Plain, // nur lesen, sowas wie SerialNo
|
||||
Bool,
|
||||
Number,
|
||||
Float
|
||||
};
|
||||
|
||||
enum class State : uint8_t
|
||||
enum class Flag : uint8_t
|
||||
{
|
||||
NoState = 0x00,
|
||||
NoFlag = 0x00,
|
||||
ReadMe = 0x01,
|
||||
WriteMe = 0x02,
|
||||
ReadOnly = 0x04,
|
||||
Locked = 0x08,
|
||||
Failed = 0x10,
|
||||
InSync = 0x20,
|
||||
OK = 0x40
|
||||
OK = 0x40,
|
||||
IsWord = 0x80
|
||||
};
|
||||
Q_DECLARE_FLAGS(States, State )
|
||||
Q_DECLARE_FLAGS(Flags, Flag )
|
||||
Q_FLAG(Flags)
|
||||
|
||||
BCValue( BCDevice::ID deviceID_, BC::ID registerID_ );
|
||||
//Q_PROPERTY(Flags valueFlags MEMBER _valueFlags )
|
||||
Q_PROPERTY(BCDevice::ID deviceID MEMBER _deviceID READ deviceID )
|
||||
Q_PROPERTY(BC::ID registerID MEMBER _registerID READ registerID )
|
||||
Q_PROPERTY(ValueType valueType MEMBER _valueType READ valueType )
|
||||
Q_PROPERTY(int indexRow MEMBER _indexRow READ indexRow)
|
||||
Q_PROPERTY(QString label MEMBER _label READ label )
|
||||
Q_PROPERTY(uint32_t rawValue MEMBER _rawValue READ rawValue )
|
||||
Q_PROPERTY(QString unitLabel MEMBER _unitLabel READ unitLabel )
|
||||
Q_PROPERTY(double factor MEMBER _factor )
|
||||
//QMEMBER _PROPERTY(OptDouble MEMBER _optMin)
|
||||
//QMEMBER _PROPERTY(OptDouble MEMBER _optMax)
|
||||
|
||||
QString formatValue( uint32_t value ) const;
|
||||
void dumpValue() const;
|
||||
struct ValueRange
|
||||
{
|
||||
int value{0};
|
||||
int min{0};
|
||||
int max{0};
|
||||
double ratio{1};
|
||||
};
|
||||
|
||||
BCValue( BCDevice::ID deviceID, BC::ID registerID );
|
||||
|
||||
QString formatValue() const;
|
||||
double calcMinMaxRatio() const;
|
||||
void dumpValue() const;
|
||||
bool isWord() const;
|
||||
bool isReadOnly() const;
|
||||
bool isBoolean() const;
|
||||
bool isChecked() const;
|
||||
|
||||
bool testFlag( Flag flag ) const;
|
||||
void setFlag( Flag flag, bool state=true ) const;
|
||||
|
||||
BCDevice::ID deviceID() const noexcept;
|
||||
BC::ID registerID() const noexcept;
|
||||
|
||||
uint32_t rawValue() const noexcept;
|
||||
void setRawValue(uint32_t newRawValue) const;
|
||||
void setFromDouble( double value );
|
||||
|
||||
ValueType valueType() const noexcept;
|
||||
int indexRow() const noexcept;
|
||||
|
||||
void setIndexRow(int newIndexRow);
|
||||
QString label() const;
|
||||
QString unitLabel() const;
|
||||
|
||||
bool hasValuesForSlider( ValueRange& valueRange ) const;
|
||||
|
||||
QString toString() const;
|
||||
|
||||
protected:
|
||||
|
||||
mutable Flags _valueFlags{BCValue::Flag::NoFlag};
|
||||
BCDevice::ID _deviceID{BCDevice::ID::Invalid};
|
||||
BC::ID _registerID{BC::ID::Invalid};
|
||||
ValueType _valueType{ValueType::Plain};
|
||||
int _indexRow{-1};
|
||||
QString _label;
|
||||
mutable uint32_t _rawValue{};
|
||||
QString _unitLabel;
|
||||
double _factor{1};
|
||||
OptDouble _optMin;
|
||||
OptDouble _optMax;
|
||||
|
||||
mutable States state{BCValue::State::ReadOnly};
|
||||
BCDevice::ID deviceID{BCDevice::ID::Invalid};
|
||||
BC::ID registerID{BC::ID::Invalid};
|
||||
ValueType valueType{ValueType::Plain};
|
||||
int indexRow{-1};
|
||||
QString label;
|
||||
mutable QString visibleValue;
|
||||
bool isWord{false};
|
||||
QString unitLabel;
|
||||
double factor{1};
|
||||
OptDouble min;
|
||||
OptDouble max;
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BCValue::States)
|
||||
|
||||
|
||||
|
||||
//Q_DECLARE_METATYPE(const BCValue&)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(BCValue::Flags)
|
||||
Q_DECLARE_METATYPE(BCValue::Flags)
|
||||
|
||||
using BCValuePtr = std::shared_ptr<BCValue>;
|
||||
using BCValuePtrConst = std::shared_ptr<const BCValue>;
|
||||
|
||||
//using BCValueList = QList<BCValue>;
|
||||
using BCValueList = QList<BCValuePtr>;
|
||||
|
||||
Q_DECLARE_METATYPE(const BCValuePtr)
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE(BCValueList)
|
||||
|
||||
|
||||
// Generischer Operator für ALLE GADGETs
|
||||
inline QTextStream& operator<<(QTextStream& out, const BCValue& obj);
|
||||
|
||||
#endif // BCVALUE_H
|
||||
|
||||
379
bcvaluedelegate.cpp
Normal file
379
bcvaluedelegate.cpp
Normal file
@@ -0,0 +1,379 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <QSlider>
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QVariantAnimation>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QPainter>
|
||||
|
||||
#include <bcdeviceview.h>
|
||||
#include <bcvaluedelegate.h>
|
||||
#include <bcvalueslider.h>
|
||||
#include <bctoggleswitch.h>
|
||||
|
||||
BCValueDelegate::BCValueDelegate(const BCValueList& valueList, BCDeviceView* view)
|
||||
: QStyledItemDelegate{view}, _valueList{valueList}, _view{view}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
QWidget* BCValueDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const
|
||||
{
|
||||
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
const BCValue& bcValue = *(_valueList[ index.row() ].get());
|
||||
|
||||
BCValue::ValueRange params;
|
||||
bool hasData = bcValue.hasValuesForSlider( params );
|
||||
|
||||
qDebug() << " --- Create Editor: " << bcValue.label() << " value: " << params.value << " min: " << params.min << " max: " << params.max << " ratio:" << bcValue.calcMinMaxRatio()*100.0 << '%';
|
||||
|
||||
if( bcValue.isBoolean() )
|
||||
{
|
||||
auto* toggleSwitch = new BCToggleSwitch{parent};
|
||||
toggleSwitch->setChecked(bcValue.isChecked() );
|
||||
|
||||
// Signal für sofortige Updates
|
||||
connect(toggleSwitch, &BCToggleSwitch::toggled, this, [this, toggleSwitch](bool checked)
|
||||
{
|
||||
qDebug() << "--- toggled: " << checked;
|
||||
// Commit data sofort bei Änderung
|
||||
emit const_cast<BCValueDelegate*>(this)->commitData(toggleSwitch);
|
||||
});
|
||||
|
||||
return toggleSwitch;
|
||||
}
|
||||
|
||||
|
||||
if( !hasData )
|
||||
return nullptr;
|
||||
|
||||
auto* valueSlider = new BCValueSlider{parent};
|
||||
valueSlider->setValueAndRange( params );
|
||||
// Signal für sofortige Updates
|
||||
connect(valueSlider, &BCValueSlider::valueChanged, this, [this, valueSlider]()
|
||||
{
|
||||
// Commit data sofort bei Änderung
|
||||
emit const_cast<BCValueDelegate*>(this)->commitData(valueSlider);
|
||||
});
|
||||
return valueSlider;
|
||||
}
|
||||
|
||||
void BCValueDelegate::setEditorData(QWidget *editor, const QModelIndex& index) const
|
||||
{
|
||||
Q_UNUSED(editor)
|
||||
Q_UNUSED(index)
|
||||
|
||||
// tue nix.
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BCValueDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
|
||||
const BCValue& bcValue = *(_valueList[ index.row()].get());
|
||||
QRect editorRect = bcValue.isBoolean() ? adjustEditorRect(option.rect, 0, 6, -130, -6) : adjustEditorRect(option.rect, 0, 0, 8, 0);
|
||||
editor->setGeometry(editorRect);
|
||||
}
|
||||
|
||||
|
||||
void BCValueDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const
|
||||
{
|
||||
if (index.column() != 1)
|
||||
return;
|
||||
|
||||
QVariant reValue;
|
||||
|
||||
const BCValue& bcValue = *(_valueList[index.row()].get());
|
||||
if (bcValue.isBoolean())
|
||||
{
|
||||
if (BCToggleSwitch* toggleSswitch = qobject_cast<BCToggleSwitch*>(editor))
|
||||
reValue = toggleSswitch->isChecked() ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BCValueSlider* slider = qobject_cast<BCValueSlider*>(editor))
|
||||
reValue = slider->value();
|
||||
}
|
||||
|
||||
model->setData(index, reValue, Qt::EditRole);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BCValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
int row = index.row();
|
||||
if( index.column() != 1 || row<0 || row >= _valueList.size() )
|
||||
return;
|
||||
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
|
||||
const BCValue& bcValue = *(_valueList[ index.row()].get());
|
||||
|
||||
if( bcValue.isBoolean() )
|
||||
{
|
||||
paintBooleanValue( painter, opt, bcValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Standard-Zeichnen (Text, Hintergrund, Selection) durchführen
|
||||
QStyledItemDelegate::paint(painter, opt, index);
|
||||
}
|
||||
|
||||
if( !bcValue.isReadOnly() )
|
||||
{
|
||||
// Wir zeichnen boolean Values an toggle switches
|
||||
if (bcValue.isBoolean())
|
||||
{
|
||||
//paintPlainToggleSwitch(painter, opt, bcValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
paintPlainSliderIndicator(painter, opt.rect, bcValue.calcMinMaxRatio());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(_rowOpacities.contains(row))
|
||||
paintHighlightRow(painter, opt,index.row());
|
||||
|
||||
}
|
||||
|
||||
void BCValueDelegate::paintBooleanValue( QPainter *painter, const QStyleOptionViewItem& option, const BCValue& bcValue ) const
|
||||
{
|
||||
|
||||
QRect textRect = option.rect.adjusted( 2,0,0,0);
|
||||
|
||||
// 3. Den tatsächlichen Wert aus dem Model auslesen
|
||||
QString text = bcValue.rawValue() == 1 ? BCTags::Yes : BCTags::No;
|
||||
|
||||
// 3. Die korrekte Textfarbe ermitteln (extrem wichtig für die UX!)
|
||||
// Wenn die Zeile markiert ist (Selected), muss der Text meist weiß sein,
|
||||
// ansonsten schwarz (oder je nach System-Theme).
|
||||
QPalette::ColorRole textRole = (option.state & QStyle::State_Selected)
|
||||
? QPalette::HighlightedText
|
||||
: QPalette::Text;
|
||||
|
||||
// 4. Den Text nativ durch den Style zeichnen lassen
|
||||
QApplication::style()->drawItemText(
|
||||
painter,
|
||||
textRect,
|
||||
Qt::AlignLeft | Qt::AlignVCenter, // Ausrichtung innerhalb von textRect
|
||||
option.palette, // Farbpalette der View übernehmen
|
||||
option.state & QStyle::State_Enabled, // Prüfen, ob die Zelle klickbar/aktiv ist
|
||||
text, // Der zu zeichnende String
|
||||
textRole // Die ermittelte Farb-Rolle
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
QRect BCValueDelegate::adjustEditorRect( const QRect& rect, int x1, int y1, int x2, int y2 ) const
|
||||
{
|
||||
return rect.adjusted
|
||||
(
|
||||
rect.width() - cTextBlockOffset + x1, // Von rechts: cTextBlockOffset (==130) px (Breite der Progress Bar)
|
||||
y1, // Oben: kein Offset
|
||||
x2, // Rechts: 8px Padding
|
||||
y2 // Unten: kein Offset
|
||||
);
|
||||
}
|
||||
|
||||
// option.rect.adjusted(option.rect.width() - cTextBlockOffset,4,0,0);
|
||||
|
||||
/**
|
||||
* @brief Zeichnet der 'Sliderindicator', also den Anteil des Gesamtwerts als Fortschrittsbalken
|
||||
*/
|
||||
|
||||
void BCValueDelegate::paintPlainSliderIndicator(QPainter* painter, const QRect& rect, double ratio )const
|
||||
{
|
||||
QRect sliderRect = adjustEditorRect( rect, 0, 0, -35, 0 );
|
||||
// Kleinen Slider-Indikator zeichnen
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QRect barRect = sliderRect;
|
||||
|
||||
int yOffset = sliderRect.height()/2;
|
||||
barRect.setY( rect.y() + yOffset - 3 );
|
||||
barRect.setHeight( 6);
|
||||
|
||||
// Mini Progress Bar: der Gesamtbereich
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(QColor(0xE0E0E0));
|
||||
painter->drawRoundedRect(barRect, 4, 4);
|
||||
|
||||
// Mini Progress Bar: der Wertebereich
|
||||
barRect.setWidth( ratio * barRect.width() );
|
||||
painter->setBrush(QColor(0x0078D4));
|
||||
painter->drawRoundedRect(barRect, 4, 4);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void BCValueDelegate::paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, int row) const
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
qreal opacity =_rowOpacities.value(row);
|
||||
painter->setOpacity(opacity);
|
||||
// Margin von 2px
|
||||
const int m = 3;
|
||||
QRect itemRect = option.rect.adjusted(m,m,-m,-m);
|
||||
|
||||
// Border (2px solid #2196F3)
|
||||
// oranger rahmen
|
||||
QPen borderPen( QColor(0xFF8C00), 1);
|
||||
painter->setPen(borderPen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
// highlight background
|
||||
//QColor highlightColor = option.palette.highlight().color();
|
||||
//highlightColor.setAlphaF(0.3); // 0.0 bis 1.0 (float ist oft lesbarer)
|
||||
//painter->fillRect(option.rect, highlightColor);
|
||||
|
||||
painter->drawRoundedRect(itemRect, 2, 2);
|
||||
|
||||
painter->restore();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BCValueDelegate::paintPlainToggleSwitch(QPainter* painter, const QStyleOptionViewItem& option, const BCValue& bcValue) const
|
||||
{
|
||||
BCToggleSwitch::paintToggleIndicator(painter, option.rect, bcValue.isChecked(), 20, option.widget->palette());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Startet die Animation für die übergebene Zeile
|
||||
* @param row
|
||||
*/
|
||||
|
||||
void BCValueDelegate::onHighlightRow(int row)
|
||||
{
|
||||
// Alte Animation für diese Zeile stoppen falls vorhanden
|
||||
if (_rowAnimations.contains(row))
|
||||
{
|
||||
_rowAnimations[row]->stop();
|
||||
_rowAnimations[row]->deleteLater();
|
||||
}
|
||||
|
||||
// QVariantAnimation ist flexibler als QPropertyAnimation
|
||||
auto* anim = new QVariantAnimation(this);
|
||||
anim->setDuration(800);
|
||||
anim->setStartValue(0.0);
|
||||
anim->setEndValue(1.0);
|
||||
|
||||
// Custom Easing für Fade-in/out Effekt
|
||||
anim->setEasingCurve(QEasingCurve::OutQuad);
|
||||
|
||||
connect(anim, &QVariantAnimation::valueChanged, this, [this, row](const QVariant& value)
|
||||
{
|
||||
qreal progress = value.toReal();
|
||||
qreal opacity;
|
||||
|
||||
// Schnelles Fade-in (20%), langsames Fade-out (80%)
|
||||
if (progress < 0.2) {
|
||||
opacity = progress * 5.0; // 0->1 in 20%
|
||||
}
|
||||
else
|
||||
{
|
||||
opacity = 1.0 - ((progress - 0.2) / 0.8); // 1->0 in 80%
|
||||
}
|
||||
|
||||
_rowOpacities[row] = opacity;
|
||||
updateRow(row);
|
||||
});
|
||||
|
||||
connect(anim, &QVariantAnimation::finished, this, [this, row, anim]()
|
||||
{
|
||||
_rowOpacities.remove(row);
|
||||
_rowAnimations.remove(row);
|
||||
updateRow(row);
|
||||
anim->deleteLater();
|
||||
});
|
||||
|
||||
_rowAnimations[row] = anim;
|
||||
anim->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stopt alle gerade laufenden Animationen
|
||||
*/
|
||||
|
||||
void BCValueDelegate::clearAllHighlights()
|
||||
{
|
||||
for(auto* anim : std::as_const(_rowAnimations))
|
||||
{
|
||||
anim->stop();
|
||||
anim->deleteLater();
|
||||
}
|
||||
_rowAnimations.clear();
|
||||
_rowOpacities.clear();
|
||||
|
||||
if (_view)
|
||||
_view->viewport()->update();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Zeichnet die übegebene Zeile neu.
|
||||
* @param row
|
||||
*/
|
||||
|
||||
void BCValueDelegate::updateRow(int row)
|
||||
{
|
||||
if (_view && _view->model() && row >= 0)
|
||||
{
|
||||
QModelIndex idx = _view->model()->index(row,1);
|
||||
QRect rect = _view->visualRect(idx);
|
||||
if (!rect.isEmpty())
|
||||
_view->viewport()->update(rect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCANIMATEDDELEGATE_H
|
||||
#define BCANIMATEDDELEGATE_H
|
||||
#ifndef BC_VALUEDELEGATE_H
|
||||
#define BC_VALUEDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
@@ -39,73 +39,53 @@
|
||||
|
||||
class QPropertyAnimation;
|
||||
class QVariantAnimation;
|
||||
class QTableView;
|
||||
class BCDeviceView;
|
||||
|
||||
|
||||
class BCAnimatedDelegate : public QStyledItemDelegate
|
||||
class BCValueDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCAnimatedDelegate(const BCValueList& valueList, QTableView* view );
|
||||
|
||||
// QString displayText(const QVariant& dataValue, const QLocale& locale) const override;
|
||||
explicit BCValueDelegate(const BCValueList& valueList, BCDeviceView* view );
|
||||
|
||||
// Zuständig für den Edit-Modus (Doppelklick)
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const override;
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex& index) const override;
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
|
||||
|
||||
/*
|
||||
qreal highlightOpacity() const
|
||||
{
|
||||
return _opacity;
|
||||
}
|
||||
|
||||
void setHighlightOpacity(qreal opacity)
|
||||
{
|
||||
_opacity = opacity;
|
||||
//qDebug() << " --- opa: " << opacity;
|
||||
// __fix! unsinn!
|
||||
emit viewUpdateNeeded();
|
||||
}
|
||||
*/
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
|
||||
void clearAllHighlights();
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
void onHighlightRow(int row);
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
//void viewUpdateNeeded();
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
void updateRow(int row);
|
||||
void paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
void paintHighlightRow(QPainter* painter, const QStyleOptionViewItem& option, int row) const;
|
||||
void paintPlainToggleSwitch(QPainter* painter, const QStyleOptionViewItem& option, const BCValue& bcValue) const;
|
||||
void paintPlainSliderIndicator(QPainter* painter, const QRect& rect, double ratio ) const;
|
||||
void paintBooleanValue( QPainter *painter, const QStyleOptionViewItem& option, const BCValue& bcValue ) const;
|
||||
|
||||
QRect adjustEditorRect(const QRect& rect, int x1, int y1, int x2, int y2) const;
|
||||
|
||||
const BCValueList& _valueList;
|
||||
QTableView* _view{};
|
||||
|
||||
//int _highlightedRow{-1};
|
||||
//qreal _opacity{1.0};
|
||||
BCDeviceView* _view{};
|
||||
|
||||
QPropertyAnimation* _animation{};
|
||||
|
||||
private:
|
||||
QHash<int, qreal> _rowOpacities;
|
||||
QHash<int, QVariantAnimation*> _rowAnimations;
|
||||
|
||||
QHash<int, qreal> m_rowOpacities;
|
||||
QHash<int, QVariantAnimation*> m_rowAnimations;
|
||||
static constexpr int cTextBlockOffset = 160;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // BCANIMATEDDELEGATE_H
|
||||
#endif // BC_VALUEDELEGATE_H
|
||||
@@ -45,8 +45,6 @@ BCValueModel::BCValueModel(QObject *parent)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gibt die interne Werteliste als const ref zurück
|
||||
* @return Die WerteListe
|
||||
@@ -81,27 +79,18 @@ void BCValueModel::takeValueList(BCValueList& newValueList)
|
||||
* @param newValue Der neue sichtbare Zahlenwert, formatiert als QString, optionall
|
||||
*/
|
||||
|
||||
void BCValueModel::onValueUpdated( int row, BCValue::State state, const QString& newVisisbleValue )
|
||||
void BCValueModel::updateValue(int row, BCValue::Flags newState, uint32_t rawValue )
|
||||
{
|
||||
if( row > -1 && row < _valueList.size() )
|
||||
{
|
||||
BCValue& value = *(_valueList[row].get());
|
||||
const BCValue& value = *(_valueList[row].get());
|
||||
|
||||
// Obacht hier!
|
||||
//value.valueFlags = state;
|
||||
value.setRawValue( rawValue );
|
||||
|
||||
QModelIndex idx = index(row,1);
|
||||
|
||||
//qDebug();
|
||||
//qDebug() << " --- OLD:"<< newVisisbleValue;
|
||||
//value.dumpValue();
|
||||
|
||||
value.state = state;
|
||||
|
||||
if( !newVisisbleValue.isEmpty() && newVisisbleValue != value.visibleValue )
|
||||
{
|
||||
value.visibleValue = newVisisbleValue;
|
||||
}
|
||||
|
||||
//qDebug() << " --- NEW: " << newVisisbleValue;
|
||||
//value.dumpValue();
|
||||
|
||||
// wir schicken auf jeden fall einen update request
|
||||
emit dataChanged(idx, idx, {Qt::DisplayRole, Qt::EditRole});
|
||||
}
|
||||
@@ -136,8 +125,6 @@ int BCValueModel::columnCount(const QModelIndex& parent) const
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gibt die Model-Daten zurück.
|
||||
*/
|
||||
@@ -156,65 +143,59 @@ QVariant BCValueModel::data(const QModelIndex& index, int role) const
|
||||
const BCValue& value = *(_valueList.at( row ).get());
|
||||
|
||||
if( col == 0 )
|
||||
return value.label;
|
||||
return value.label();
|
||||
|
||||
if( col == 1)
|
||||
{
|
||||
if( role == Qt::DisplayRole )
|
||||
return QString("%1 %2").arg( value.visibleValue, value.unitLabel);
|
||||
return QString("%1 %2").arg( value.formatValue(), value.unitLabel());
|
||||
|
||||
return value.visibleValue;
|
||||
return value.formatValue();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
||||
|
||||
/*
|
||||
Das Model Gibt hier, unabhängig von der DataRole, immer das
|
||||
* gesamte BCValue Object zurück. Die Umsetzung von Status- und Typeinfromationen in GUI-Elemente
|
||||
* findet nicht hier, sondern im BCDelagate statt.
|
||||
|
||||
// falsch! wie geben hier doch ordentlich die einzelwerte zurück
|
||||
|
||||
// Bonus: Rechtsbündig für Zahlen
|
||||
if (role == Qt::TextAlignmentRole && (index.column() == 0 || index.column() == 2)) {
|
||||
return Qt::AlignRight | Qt::AlignVCenter;
|
||||
}
|
||||
|
||||
//return QVariant::fromValue( entry );
|
||||
|
||||
return QVariant();
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
Qt::ItemFlags BCValueModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
|
||||
Qt::ItemFlags flag = Qt::NoItemFlags | Qt::ItemNeverHasChildren;// | Qt::ItemIsSelectable;
|
||||
// die label spalte lässt sich nicht editieren
|
||||
if (!index.isValid() || index.column() == 0 )
|
||||
return flag;
|
||||
int row = index.row();
|
||||
if( row>-1 && row<_valueList.size() )
|
||||
{
|
||||
const BCValue& bcValue = *_valueList[row].get();
|
||||
//qDebug() << " --- flags: " << bcValue.label() << " Ro: " << bcValue.isReadOnly() << " Bool: " << bcValue.isBoolean();
|
||||
flag = bcValue.isReadOnly() ? flag : flag|Qt::ItemIsEditable|Qt::ItemIsEnabled;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
bool BCValueModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
bool BCValueModel::setData(const QModelIndex& index, const QVariant& variant, int role)
|
||||
{
|
||||
|
||||
// __fix!
|
||||
|
||||
if (index.isValid() && role == Qt::EditRole)
|
||||
{
|
||||
BCValuePtr item = _valueList[index.row()];
|
||||
|
||||
qDebug() << " --- SetData: at: " << index.row() << " --- set: " << variant.toString();
|
||||
|
||||
BCValuePtr value = _valueList[index.row()];
|
||||
|
||||
// Wir erwarten hier nur den Value-Teil (vom Slider/Editor)
|
||||
// Checken ob Int oder Double
|
||||
if (value.canConvert<double>())
|
||||
if (variant.canConvert<int>())
|
||||
{
|
||||
item->visibleValue = value.toString();
|
||||
if( variant.toInt() == 42)
|
||||
{
|
||||
emit makeSimonHappy();
|
||||
}
|
||||
// QUARK!
|
||||
value->setRawValue( variant.toInt() );
|
||||
}
|
||||
|
||||
_valueList[index.row()] = item;
|
||||
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef BCVALUEMODEL_H
|
||||
#define BCVALUEMODEL_H
|
||||
#ifndef BC_VALUEMODEL_H
|
||||
#define BC_VALUEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <bcvalue.h>
|
||||
@@ -59,16 +59,16 @@ public:
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
//QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Nötig für Editierbarkeit
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
|
||||
public slots:
|
||||
void updateValue(int row, BCValue::Flags newState, uint32_t rawValue );
|
||||
|
||||
void onValueUpdated(int index, BCValue::State state, const QString& newVisisbleValue="" );
|
||||
signals:
|
||||
|
||||
void makeSimonHappy();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -77,4 +77,4 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
#endif // BCVALUEMODEL_H
|
||||
#endif // BC_VALUEMODEL_H
|
||||
|
||||
85
bcvalueslider.cpp
Normal file
85
bcvalueslider.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/***************************************************************************
|
||||
|
||||
BionxControl
|
||||
© 2025 -2026 christoph holzheuer
|
||||
christoph.holzheuer@gmail.com
|
||||
|
||||
Using:
|
||||
|
||||
mhs_can_drv.c
|
||||
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
||||
Klaus Demlehner, klaus@mhs-elektronik.de
|
||||
@see www.mhs-elektronik.de
|
||||
|
||||
Based on Bionx data type descriptions from:
|
||||
|
||||
BigXionFlasher USB V 0.2.4 rev. 97
|
||||
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
||||
@see www.bigxionflasher.org
|
||||
|
||||
Bionx Bike Info
|
||||
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
||||
@see www.ts-soft.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
@see https://github.com/bikemike/bionx-bikeinfo
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include <bcvalueslider.h>
|
||||
|
||||
|
||||
BCValueSlider::BCValueSlider( QWidget *parent )
|
||||
: QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
// wir wollen ja modern sein
|
||||
//_sliderStyle = std::make_unique<BCValueSliderStyle>();
|
||||
//_slider->setStyle(_sliderStyle.get());
|
||||
setAutoFillBackground(true);
|
||||
|
||||
QSizePolicy sp = _commitButton->sizePolicy();
|
||||
sp.setRetainSizeWhenHidden(true); // <--- Das ist der magische Schalter
|
||||
_commitButton->setSizePolicy(sp);
|
||||
|
||||
// Wenn Slider bewegt wird -> Signal nach außen senden
|
||||
connect(_slider, &QSlider::valueChanged, this, [this](int val)
|
||||
{
|
||||
emit valueChanged(val);
|
||||
});
|
||||
|
||||
// Wenn Reset gedrückt wird -> Slider auf 0 (löst auch valueChanged aus)
|
||||
connect(_commitButton, &QPushButton::clicked, this, [this]()
|
||||
{
|
||||
emit valueCommited( value() );
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
int BCValueSlider::value() const
|
||||
{
|
||||
return _slider->value();
|
||||
}
|
||||
|
||||
void BCValueSlider::setValueAndRange( const BCValue::ValueRange& params )
|
||||
{
|
||||
_slider->setRange( params.min, params.max);
|
||||
// Block Signals verhindern Endlosschleifen, falls das Model
|
||||
// das Widget während des Updates neu setzt (passiert manchmal bei Live-Updates).
|
||||
if (params.value != _slider->value())
|
||||
{
|
||||
bool blocked = _slider->blockSignals(true);
|
||||
_slider->setValue(params.value);
|
||||
_slider->blockSignals(blocked);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
38
bcvalueslider.h
Normal file
38
bcvalueslider.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef BC_VALUESLIDER_H
|
||||
#define BC_VALUESLIDER_H
|
||||
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTableView>
|
||||
#include <QSlider>
|
||||
#include <QPainter>
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include <bcvalue.h>
|
||||
#include <ui_bcvalueslider.h>
|
||||
|
||||
class QSlider;
|
||||
class QPushButton;
|
||||
class BCValue;
|
||||
|
||||
|
||||
class BCValueSlider : public QWidget, private Ui_BCValueSlider
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BCValueSlider(QWidget *parent = nullptr);
|
||||
|
||||
int value() const;
|
||||
void setValueAndRange( const BCValue::ValueRange& params );
|
||||
|
||||
signals:
|
||||
|
||||
void valueChanged(int value);
|
||||
void valueCommited(int value);
|
||||
|
||||
};
|
||||
|
||||
#endif // BC_VALUESLIDER_H
|
||||
95
bcvalueslider.ui
Normal file
95
bcvalueslider.ui
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BCValueSlider</class>
|
||||
<widget class="QWidget" name="BCValueSlider">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>111</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetMinimumSize</enum>
|
||||
</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="QSlider" name="_slider">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="_commitButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777212</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="bionxcontrol.qrc">
|
||||
<normaloff>:/update.png</normaloff>:/update.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonStyle::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="bionxcontrol.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
156
bcxmlloader.cpp
156
bcxmlloader.cpp
@@ -51,37 +51,30 @@ BCXmlLoader::BCXmlLoader(QObject *parent)
|
||||
|
||||
void BCXmlLoader::loadXmlBikeData( const QString& fileName )
|
||||
{
|
||||
/*
|
||||
auto printAttrs = [](const QXmlStreamReader& xml)
|
||||
{
|
||||
QStringList parts;
|
||||
for (const auto &attr : xml.attributes()) {
|
||||
for (const auto &attr : xml.attributes())
|
||||
{
|
||||
parts << attr.name().toString() + "=\"" + attr.value().toString() + "\"";
|
||||
}
|
||||
qDebug().noquote() << parts.join(" ");
|
||||
};
|
||||
/*
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "XML öffnen", "", "XML Files (*.xml)");
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
*/
|
||||
|
||||
QMetaEnum bcDeviceEnum{QMetaEnum::fromType<BCDevice::ID>()};
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
// __fix throw
|
||||
QMessageBox::warning(nullptr, "Fehler", "Datei konnte nicht geöffnet werden.");
|
||||
return;
|
||||
}
|
||||
throw BCException( "Fehler", "Datei konnte nicht geöffnet werden.");
|
||||
|
||||
_xml.setDevice(&file);
|
||||
|
||||
if (_xml.readNextStartElement())
|
||||
{
|
||||
if (_xml.name() != "Bike"_L1 )
|
||||
// fix throw
|
||||
_xml.raiseError(QObject::tr("The file is not an 'Bike' file."));
|
||||
throw BCException( "Fehler", "Falsches Datenformat.");
|
||||
}
|
||||
// ??
|
||||
Q_ASSERT(_xml.isStartElement() && _xml.name() == "Bike"_L1);
|
||||
@@ -92,53 +85,43 @@ void BCXmlLoader::loadXmlBikeData( const QString& fileName )
|
||||
if (token == QXmlStreamReader::StartElement)
|
||||
{
|
||||
QString deviceType = _xml.attributes().value("Type"_L1).toString();
|
||||
printAttrs (_xml);
|
||||
// Wir wollen die Device-ID aus dem XML Tag ermitteln
|
||||
const char* deviceKey = _xml.attributes().value("Type"_L1).toLatin1().constData();
|
||||
bool ok;
|
||||
if( deviceType.isEmpty() )
|
||||
continue;
|
||||
|
||||
QByteArray byteArray = deviceType.toUtf8();
|
||||
const char* deviceKey = byteArray.constData();
|
||||
bool ok=false;
|
||||
auto optDeviceID = bcDeviceEnum.keyToValue(deviceKey,&ok);
|
||||
//_currentDeviceID = BCDevice::ID( deviceID.value_or( BCDevice::ID::Invalid ) );
|
||||
//if( optDeviceID.has_value())
|
||||
if(ok)
|
||||
{
|
||||
qDebug() << " --- Device: " << _xml.name() << ": " << deviceType << " : " << optDeviceID;
|
||||
//BCDevice::ID currentDeviceID = BCDevice::ID( optDeviceID.value() );
|
||||
BCDevice::ID currentDeviceID = BCDevice::ID( optDeviceID );
|
||||
loadXmlBikeDeviceData(currentDeviceID);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (xml.hasError())
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Parsing Fehler", xml.errorString());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->setDevices(parsedValues);
|
||||
}
|
||||
*/
|
||||
|
||||
// create & add new model to the model map
|
||||
|
||||
if(!ok)
|
||||
throw BCException( "Fehler", QString("Devicetype %1 existiert nicht.").arg(deviceType) );
|
||||
//BCDevice::ID currentDeviceID = BCDevice::ID( optDeviceID.value() );
|
||||
BCDevice::ID currentDeviceID = BCDevice::ID( optDeviceID );
|
||||
loadXmlBikeDeviceData(currentDeviceID);
|
||||
} // if startElement
|
||||
} // end while
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Lädt deie Daten des BionX eBikes
|
||||
* @param deviceID
|
||||
*/
|
||||
|
||||
void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
{
|
||||
auto printAttrs = [](const QXmlStreamReader& xml)
|
||||
{
|
||||
QStringList parts;
|
||||
for (const auto &attr : xml.attributes()) {
|
||||
for (const auto &attr : xml.attributes())
|
||||
parts << attr.name().toString() + "=\"" + attr.value().toString() + "\"";
|
||||
}
|
||||
qDebug().noquote() << parts.join(" ");
|
||||
};
|
||||
|
||||
printAttrs (_xml);
|
||||
Q_ASSERT(_xml.isStartElement() && _xml.name() == "Device"_L1);
|
||||
qDebug() << " XXX ---------------";
|
||||
Q_ASSERT(_xml.isStartElement() && _xml.name() == BCTags::Device );
|
||||
|
||||
// temporäre Wertliste für neues Device
|
||||
BCValueList currentValues;
|
||||
@@ -147,8 +130,6 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
{
|
||||
if( _xml.attributes().hasAttribute(BCTags::ID) )
|
||||
{
|
||||
//qDebug() << " --- found: " << _xml.name() << " : " << _xml.attributes().value(BCTags::ID);
|
||||
|
||||
// füllen des Parameter packs
|
||||
BCValueParams params
|
||||
{
|
||||
@@ -159,6 +140,7 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
.Min = _xml.attributes().value(BCTags::Min).toString(),
|
||||
.Max = _xml.attributes().value(BCTags::Max).toString(),
|
||||
.IsWord = _xml.attributes().value(BCTags::IsWord).toString(),
|
||||
.ReadOnly = _xml.attributes().value(BCTags::ReadOnly).toString(),
|
||||
.ValueType = _xml.attributes().value(BCTags::ValueType).toString(),
|
||||
};
|
||||
|
||||
@@ -167,7 +149,7 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
if(newValue)
|
||||
{
|
||||
// wir merken uns gleich den index in der Werteliste
|
||||
(*newValue)->indexRow = currentValues.size();
|
||||
(*newValue)->setIndexRow( currentValues.size() );
|
||||
currentValues.push_back( *newValue );
|
||||
}
|
||||
|
||||
@@ -182,6 +164,11 @@ void BCXmlLoader::loadXmlBikeDeviceData(BCDevice::ID deviceID)
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Erzeugt einen BCValue für die DeviceID aus dem gegebenen parameter pack
|
||||
*/
|
||||
|
||||
std::optional<BCValuePtr> BCXmlLoader::makeValue( BCDevice::ID deviceID, const BCValueParams& params )
|
||||
{
|
||||
|
||||
@@ -193,66 +180,57 @@ std::optional<BCValuePtr> BCXmlLoader::makeValue( BCDevice::ID deviceID, const B
|
||||
{ "Float", BCValue::ValueType::Float }
|
||||
};
|
||||
|
||||
auto setIfExists = [&]<typename T>( QStringView source, T& target )
|
||||
auto setIfExists = [&]<typename T>( T& target, QStringView source )
|
||||
{
|
||||
if( !source.isEmpty() )
|
||||
{
|
||||
bool ok;
|
||||
double testVal = source.toDouble(&ok);
|
||||
if (ok)
|
||||
target = testVal;
|
||||
}
|
||||
{
|
||||
bool ok;
|
||||
double testVal = source.toDouble(&ok);
|
||||
if (ok)
|
||||
target = testVal;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Wir brauchen:
|
||||
- einen gültige ID String um die enum ID herauszufinden.
|
||||
- einen gültige UnitType String um den ValueType herauszufinden.
|
||||
|
||||
*/
|
||||
// Wir brauchen:
|
||||
// - einen gültige ID String um die enum ID herauszufinden.
|
||||
// - einen gültige UnitType String um den ValueType herauszufinden.
|
||||
|
||||
// geht nicht auf qt6.8 von debian trixie
|
||||
//std::optional<quint64> IDVal = s_bcValueEnum.keyToValue64( params.ID.toLatin1().constData() );
|
||||
bool ok;
|
||||
static QMetaEnum s_bcValueEnum{QMetaEnum::fromType<BC::ID>()};
|
||||
int IDVal = s_bcValueEnum.keyToValue( params.ID.toLatin1().constData(), &ok );
|
||||
qDebug() << " --- should create: " << params.Label;
|
||||
QByteArray byteArray = params.ID.toUtf8();
|
||||
int IDVal = s_bcValueEnum.keyToValue( params.ID.toUtf8().constData(), &ok );
|
||||
//if( IDVal.has_value() )
|
||||
if( ok )
|
||||
{
|
||||
BCValuePtr newValuePtr = std::make_shared<BCValue>( deviceID, static_cast<BC::ID>(IDVal) );
|
||||
BCValue& newValue = *newValuePtr.get();
|
||||
if( !ok )
|
||||
throw BCException( "Fehler", QString("Devicetype %1 existiert nicht.").arg(params.ID) );
|
||||
|
||||
setIfExists( params.Factor, newValue.factor );
|
||||
setIfExists( params.Min, newValue.min );
|
||||
setIfExists( params.Max, newValue.max );
|
||||
setIfExists( params.IsWord, newValue.isWord );
|
||||
BCValuePtr newValuePtr = std::make_shared<BCValue>( deviceID, static_cast<BC::ID>(IDVal) );
|
||||
BCValue& newValue = *newValuePtr.get();
|
||||
|
||||
newValue.label = params.Label;
|
||||
newValue.unitLabel = params.UnitLabel;
|
||||
// ValueType
|
||||
if( !s_valueTypes.contains( params.ValueType ) )
|
||||
throw BCException( "Fehler", QString("ValueType %1 existiert nicht.").arg(params.ValueType) );
|
||||
|
||||
if( s_valueTypes.contains( params.ValueType ) )
|
||||
newValue.valueType = s_valueTypes[params.ValueType];
|
||||
newValue._valueType = s_valueTypes[params.ValueType];
|
||||
|
||||
/*
|
||||
QString ID;
|
||||
QString Label;
|
||||
QString UnitLabel;
|
||||
QString Factor;
|
||||
QString Min;
|
||||
QString Max;
|
||||
QString IsWord;
|
||||
QString ValueType;
|
||||
*/
|
||||
newValue._label = params.Label;
|
||||
newValue._unitLabel = params.UnitLabel;
|
||||
|
||||
qDebug() << " --- created: " << params.Label;
|
||||
newValue.dumpValue();
|
||||
setIfExists( newValue._factor, params.Factor );
|
||||
setIfExists( newValue._optMin, params.Min );
|
||||
setIfExists( newValue._optMax, params.Max );
|
||||
|
||||
return std::optional<BCValuePtr>( newValuePtr );
|
||||
}
|
||||
if( params.IsWord == "true")
|
||||
newValue._valueFlags.setFlag( BCValue::Flag::IsWord, true );
|
||||
|
||||
if( params.ReadOnly == "true")
|
||||
newValue._valueFlags.setFlag( BCValue::Flag::ReadOnly, true );
|
||||
|
||||
//newValue.dumpValue();
|
||||
|
||||
return std::optional<BCValuePtr>( newValuePtr );
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ protected:
|
||||
QString Min;
|
||||
QString Max;
|
||||
QString IsWord;
|
||||
QString ReadOnly;
|
||||
QString ValueType;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +1,34 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file alias="bikeinfo.xml">resources/bikeinfo.xml</file>
|
||||
<file alias="bionxcontrol.qss">resources/bionxcontrol.qss</file>
|
||||
<file alias="claude_dark_mode.qss">resources/claude_dark_mode.qss</file>
|
||||
<file alias="claude_light_mode.qss">resources/claude_light_mode.qss</file>
|
||||
<file alias="bc_light.qss">resources/bc_light.qss</file>
|
||||
<file alias="bionx_akku.png">resources/bionx_akku.png</file>
|
||||
<file alias="bionx_console.png">resources/bionx_console.png</file>
|
||||
<file alias="bionx_motor.png">resources/bionx_motor.png</file>
|
||||
<file alias="exit.png">resources/exit.png</file>
|
||||
<file alias="important.png">resources/important.png</file>
|
||||
<file alias="restart.png">resources/restart.png</file>
|
||||
<file alias="splash.png">resources/splash.png</file>
|
||||
<file alias="connect.png">resources/connect.png</file>
|
||||
<file alias="connected.png">resources/connected.png</file>
|
||||
<file alias="disconnected.png">resources/disconnected.png</file>
|
||||
<file>resources/connect_white.svg</file>
|
||||
<file>resources/sync_green.svg</file>
|
||||
<file>resources/sync_yellow.svg</file>
|
||||
<file alias="exit.png">resources/exit.png</file>
|
||||
<file alias="exit_red.png">resources/exit_red.png</file>
|
||||
<file alias="sync_green.png">resources/sync_green.png</file>
|
||||
<file alias="sync_yellow.png">resources/sync_yellow.png</file>
|
||||
<file alias="sync.png">resources/sync.png</file>
|
||||
<file alias="bc_dark.qss">resources/bc_dark.qss</file>
|
||||
<file>resources/smile/face-angel.png</file>
|
||||
<file>resources/smile/face-angry.png</file>
|
||||
<file>resources/smile/face-cool.png</file>
|
||||
<file>resources/smile/face-crying.png</file>
|
||||
<file>resources/smile/face-embarrassed.png</file>
|
||||
<file>resources/smile/face-glasses.png</file>
|
||||
<file>resources/smile/face-kiss.png</file>
|
||||
<file>resources/smile/face-laugh.png</file>
|
||||
<file>resources/smile/face-monkey.png</file>
|
||||
<file>resources/smile/face-plain.png</file>
|
||||
<file>resources/smile/face-raspberry.png</file>
|
||||
<file>resources/smile/face-sad.png</file>
|
||||
<file>resources/smile/face-sick.png</file>
|
||||
<file>resources/smile/face-smile.png</file>
|
||||
<file>resources/smile/face-smile-big.png</file>
|
||||
<file>resources/smile/face-smirk.png</file>
|
||||
<file>resources/smile/face-surprise.png</file>
|
||||
<file alias="update.png">resources/update.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
40
build_and_deploy.sh
Executable file
40
build_and_deploy.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Bricht das Skript ab, falls ein Befehl (z. B. der Build) fehlschlägt
|
||||
set -e
|
||||
|
||||
# --- Variablen (Bitte anpassen!) ---
|
||||
IMAGE_NAME="qt-cross-rpi"
|
||||
# Trage hier den genauen Namen deines fertig kompilierten Executables ein:
|
||||
BINARY_NAME="BionxControl"
|
||||
TARGET_USER="chris"
|
||||
TARGET_IP="192.168.0.106"
|
||||
TARGET_DIR="/home/chris/projects/BionxControl"
|
||||
# Den Namen der Toolchain aus deiner Vorlage oder der zuvor erstellten Datei
|
||||
TOOLCHAIN_FILE="armhf-toolchain.cmake"
|
||||
|
||||
echo "=== 1. Baue das Docker-Image ==="
|
||||
docker build -t ${IMAGE_NAME} .
|
||||
|
||||
echo "=== 2. Kompiliere das Projekt im Container ==="
|
||||
# Wir führen die Build-Befehle direkt im Container aus, anstatt interaktiv zu starten.
|
||||
# Das -it flag wurde entfernt, da wir es als Skript ausführen.
|
||||
docker run --rm -v "$(pwd):/workspace" ${IMAGE_NAME} bash -c "
|
||||
echo 'Bereinige altes Build-Verzeichnis...'
|
||||
rm -rf dockerbuild
|
||||
|
||||
mkdir dockerbuild
|
||||
cd dockerbuild
|
||||
|
||||
echo 'Führe CMake aus...'
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../${TOOLCHAIN_FILE} -G Ninja ..
|
||||
|
||||
echo 'Starte Build (Ninja)...'
|
||||
ninja
|
||||
"
|
||||
|
||||
echo "=== 3. Deploy auf den Raspberry Pi via scp ==="
|
||||
# Kopiert das neu gebaute Binary auf die Zielmaschine
|
||||
scp "dockerbuild/${BINARY_NAME}" "${TARGET_USER}@${TARGET_IP}:${TARGET_DIR}"
|
||||
|
||||
echo "=== Deployment erfolgreich abgeschlossen! ==="
|
||||
Binary file not shown.
@@ -27,6 +27,43 @@ sudo apt purge modemmanager
|
||||
|
||||
// ---
|
||||
|
||||
sudo apt install \
|
||||
qt6-declarative-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
qt6-l10n-tools \
|
||||
qt6-scxml-dev \
|
||||
qt6-serialport-dev \
|
||||
qt6-serialbus-dev \
|
||||
qt6-connectivity-dev \
|
||||
qt6-sensors-dev \
|
||||
qt6-websockets-dev \
|
||||
qt6-webchannel-dev \
|
||||
qt6-svg-dev \
|
||||
qt6-multimedia-dev \
|
||||
qt6-charts-dev \
|
||||
qt6-wayland \
|
||||
qml6-module-qtquick-controls \
|
||||
qml6-module-qtquick-layouts \
|
||||
qml6-module-qtquick-templates \
|
||||
qml6-module-qtquick-window \
|
||||
qml6-module-qtqml-workerscript \
|
||||
qml6-module-qtcharts \
|
||||
qml6-module-qt-labs-platform \
|
||||
libqt6sql6-mysql libqt6sql6-psql libqt6sql6-sqlite \
|
||||
libqt6opengl6-dev
|
||||
|
||||
sudo apt update
|
||||
sudo apt install \
|
||||
qtcreator \
|
||||
qtcreator-doc \
|
||||
cmake \
|
||||
ninja-build \
|
||||
gdb \
|
||||
clang \
|
||||
clang-format
|
||||
|
||||
|
||||
https://github.com/MHS-Elektronik/OBD-Display
|
||||
|
||||
sudo chgrp pi /opt
|
||||
@@ -36,21 +73,5 @@ https://github.com/MHS-Elektronik/OBD-Display
|
||||
tar -xzvf tiny_can_raspberry_790.tar.gz
|
||||
rm tiny_can_raspberry_790.tar.gz
|
||||
|
||||
sudo apt install fonts-open-sans
|
||||
|
||||
|
||||
RANT
|
||||
|
||||
--- STRUKTUR
|
||||
|
||||
Denglish -> Comments, Bezeichnungen 'aligned', 'given'
|
||||
Weltsprache, mag ja sein,
|
||||
|
||||
Schlimmer: Doku & Bücher -> c++, qt, OO nicht verstanden
|
||||
|
||||
includes_ pfade hartcodiert statt im Makefile -> Kunstfehler
|
||||
Projecte willkürlich verstreut
|
||||
|
||||
Respektlose Schlampigkeit: copy & paste: es werden sogar die Artefakte des MKS mitkopiert ->
|
||||
---
|
||||
|
||||
---
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,30 +0,0 @@
|
||||
|
||||
|
||||
Sehr geehrte Frau Spaag,
|
||||
|
||||
Aktuell bin ich als Softwareentwickler im Bereich C++/Qt fest angestellt, suche jedoch
|
||||
nach neuen Entwicklungsmöglichkeiten.
|
||||
|
||||
Ihre Stellenanzeige hat mich sofort angesprochen, denn das beschriebene Anforderungsprofil
|
||||
harmonisiert sehr gut mit meiner derzeitigen Tätigkeit im Bereich Datenvisualisierung und
|
||||
|
||||
blub
|
||||
|
||||
Ich freu mich wie woschd und verbeibe mit freundlichen Grüßen
|
||||
|
||||
Christoph Holzheuer
|
||||
|
||||
|
||||
// ----------
|
||||
|
||||
znode<T> ist eine header-only Klasse in modern c++ für generische Baumstrukturen
|
||||
In der derzeitigen Ausführung dient sie mit Hilfe des pugixml Parser zur Verwaltung
|
||||
von XML Daten innerhalb des xtree-Projekts.
|
||||
|
||||
Die Knoten sind std::c++, die Verwaltung der Attribs ist drangeebrt und somit variable.
|
||||
|
||||
Besonderheit ist die Übergabe das String types als template parameter: In Xtree instanzierung durch QString,
|
||||
andere durch std::string bzw. std::w_string ohne Dependencies zur Qt-Lib eingehen zu müssen.
|
||||
bridge-code
|
||||
|
||||
// ----------
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 46 KiB |
Binary file not shown.
Binary file not shown.
@@ -1,63 +0,0 @@
|
||||
Challenges
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
BionxControl
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
xtree
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
znode
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
libPigPio
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
supportware
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
raDIYo
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
miniCash.connect
|
||||
|
||||
Aufgabe:
|
||||
|
||||
Ansatz:
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
@@ -22,11 +22,11 @@
|
||||
/***************************************************************/
|
||||
#define CAN_FEATURE_LOM 0x0001 // Silent Mode (LOM = Listen only Mode)
|
||||
#define CAN_FEATURE_ARD 0x0002 // Automatic Retransmission disable
|
||||
#define CAN_FEATURE_TX_ACK 0x0004 // TX ACK (Gesendete Nachrichten best<EFBFBD>tigen)
|
||||
#define CAN_FEATURE_TX_ACK 0x0004 // TX ACK (Gesendete Nachrichten bestätigen)
|
||||
#define CAN_FEATURE_ERROR_MSGS 0x0008 // Error Messages Support
|
||||
#define CAN_FEATURE_FD_HARDWARE 0x0010 // CAN-FD Hardware
|
||||
#define CAN_FEATURE_FIFO_OV_MODE 0x0020 // FIFO OV Mode (Auto Clear, OV CAN Messages)
|
||||
#define CAN_FEATURE_ECU_FLASH 0x0040 // Hardware beschleunigung f<EFBFBD>r ISO-TP ECU-Flash programmierung
|
||||
#define CAN_FEATURE_ECU_FLASH 0x0040 // Hardware beschleunigung für ISO-TP ECU-Flash programmierung
|
||||
#define CAN_FEATURE_CAN_TEST 0x4000 // Tiny-CAN Tester Firmware
|
||||
#define CAN_FEATURE_HW_TIMESTAMP 0x8000 // Hardware Time Stamp
|
||||
|
||||
@@ -165,32 +165,32 @@
|
||||
struct TModulFeatures
|
||||
{
|
||||
uint32_t CanClock; // Clock-Frequenz des CAN-Controllers, muss nicht mit
|
||||
// der Clock-Frequenz des Mikrocontrollers <EFBFBD>bereinstimmen
|
||||
uint32_t Flags; // Unterst<EFBFBD>tzte Features des Moduls:
|
||||
// der Clock-Frequenz des Mikrocontrollers übereinstimmen
|
||||
uint32_t Flags; // Unterstützte Features des Moduls:
|
||||
// Bit Define-Makro
|
||||
// 0x0001 CAN_FEATURE_LOM -> Silent Mode (LOM = Listen only Mode)
|
||||
// 0x0002 CAN_FEATURE_ARD -> Automatic Retransmission disable
|
||||
// 0x0004 CAN_FEATURE_TX_ACK -> TX ACK (Gesendete Nachrichten best<EFBFBD>tigen)
|
||||
// 0x0004 CAN_FEATURE_TX_ACK -> TX ACK (Gesendete Nachrichten bestätigen)
|
||||
// 0x0008 CAN_FEATURE_ERROR_MSGS -> Error Messages Support
|
||||
// 0x0010 CAN_FEATURE_FD_HARDWARE -> CAN-FD Hardware
|
||||
// 0x0020 CAN_FEATURE_FIFO_OV_MODE -> FIFO OV Mode (Auto Clear, OV CAN Messages)
|
||||
// 0x0040 CAN_FEATURE_ECU_FLASH -> Hardware beschleunigung f<EFBFBD>r ISO-TP ECU-Flash programmierung
|
||||
// 0x0040 CAN_FEATURE_ECU_FLASH -> Hardware beschleunigung für ISO-TP ECU-Flash programmierung
|
||||
// 0x4000 CAN_FEATURE_CAN_TEST -> Tiny-CAN Tester Firmware
|
||||
// 0x8000 CAN_FEATURE_HW_TIMESTAMP -> Hardware Time Stamp
|
||||
uint32_t CanChannelsCount; // Anzahl der CAN Schnittstellen, reserviert f<EFBFBD>r
|
||||
// zuk<EFBFBD>nftige Module mit mehr als einer Schnittstelle
|
||||
uint32_t HwRxFilterCount; // Anzahl der zur Verf<EFBFBD>gung stehenden Receive-Filter
|
||||
uint32_t HwTxPufferCount; // Anzahl der zur Verf<EFBFBD>gung stehenden Transmit Puffer mit Timer
|
||||
uint32_t CanChannelsCount; // Anzahl der CAN Schnittstellen, reserviert für
|
||||
// zukünftige Module mit mehr als einer Schnittstelle
|
||||
uint32_t HwRxFilterCount; // Anzahl der zur Verfügung stehenden Receive-Filter
|
||||
uint32_t HwTxPufferCount; // Anzahl der zur Verfügung stehenden Transmit Puffer mit Timer
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanDevicesList
|
||||
{
|
||||
uint32_t TCanIdx; // Ist das Device ge<EFBFBD>ffnet ist der Wert auf dem Device-Index
|
||||
uint32_t TCanIdx; // Ist das Device geöffnet ist der Wert auf dem Device-Index
|
||||
// gesetzt, ansonsten ist der Wert auf "INDEX_INVALID" gesetzt.
|
||||
uint32_t HwId; // Ein 32 Bit Schl<EFBFBD>ssel der die Hardware eindeutig Identifiziert.
|
||||
// Manche Module m<EFBFBD>ssen erst ge<EFBFBD>ffnet werden damit dieser Wert
|
||||
uint32_t HwId; // Ein 32 Bit Schlüssel der die Hardware eindeutig Identifiziert.
|
||||
// Manche Module müssen erst geöffnet werden damit dieser Wert
|
||||
// gesetzt wird
|
||||
char DeviceName[255]; // Nur Linux: entspricht den Device Namen des USB-Devices,
|
||||
// z.B. /dev/ttyUSB0
|
||||
@@ -199,7 +199,7 @@ struct TCanDevicesList
|
||||
// muss in den USB-Controller programmiert sein,
|
||||
// was zur Zeit nur bei den Modulen Tiny-CAN II-XL,
|
||||
// IV-XL u. M1 der Fall ist.
|
||||
struct TModulFeatures ModulFeatures; // Unterst<EFBFBD>tzte Features des Moduls, nur g<EFBFBD>ltig
|
||||
struct TModulFeatures ModulFeatures; // Unterstützte Features des Moduls, nur gültig
|
||||
// wenn HwId > 0
|
||||
};
|
||||
#pragma pack(pop)
|
||||
@@ -207,28 +207,28 @@ struct TCanDevicesList
|
||||
#pragma pack(push, 1)
|
||||
struct TCanDeviceInfo
|
||||
{
|
||||
uint32_t HwId; // Ein 32 Bit Schl<EFBFBD>ssel der die Hardware eindeutig Identifiziert.
|
||||
uint32_t HwId; // Ein 32 Bit Schlüssel der die Hardware eindeutig Identifiziert.
|
||||
uint32_t FirmwareVersion; // Version der Firmware des Tiny-CAN Moduls
|
||||
uint32_t FirmwareInfo; // Informationen zum Stand der Firmware Version
|
||||
// 0 = Unbekannt
|
||||
// 1 = Firmware veraltet, Device kann nicht ge<EFBFBD>ffnet werden
|
||||
// 2 = Firmware veraltet, Funktionsumfang eingeschr<EFBFBD>nkt
|
||||
// 3 = Firmware veraltet, keine Einschr<EFBFBD>nkungen
|
||||
// 1 = Firmware veraltet, Device kann nicht geöffnet werden
|
||||
// 2 = Firmware veraltet, Funktionsumfang eingeschränkt
|
||||
// 3 = Firmware veraltet, keine Einschränkungen
|
||||
// 4 = Firmware auf Stand
|
||||
// 5 = Firmware neuer als Erwartet
|
||||
char SerialNumber[16]; // Seriennummer des Moduls
|
||||
char Description[64]; // Modul Bezeichnung, z.B. "Tiny-CAN IV-XL"
|
||||
struct TModulFeatures ModulFeatures; // Unterst<EFBFBD>tzte Features des Moduls
|
||||
struct TModulFeatures ModulFeatures; // Unterstützte Features des Moduls
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct TCanInfoVar // <*> ge<EFBFBD>ndert von TInfoVar in TCanInfoVar
|
||||
struct TCanInfoVar // <*> geändert von TInfoVar in TCanInfoVar
|
||||
{
|
||||
uint32_t Key; // Variablen Schl<EFBFBD>ssel
|
||||
uint32_t Key; // Variablen Schlüssel
|
||||
uint32_t Type; // Variablen Type
|
||||
uint32_t Size; // (Max)Gr<EFBFBD><EFBFBD>e der Variable in Byte
|
||||
uint32_t Size; // (Max)Größe der Variable in Byte
|
||||
char Data[255]; // Wert der Variable
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
/* www.mhs-elektronik.de */
|
||||
/* Autor : Demlehner Klaus, info@mhs-elektronik.de */
|
||||
/*******************************************************************************/
|
||||
|
||||
#include "mhs_can_drv.c"
|
||||
|
||||
|
||||
|
||||
@@ -126,14 +126,14 @@ Byte 0
|
||||
|
||||
struct TCanFlagsBits
|
||||
{
|
||||
unsigned Len:4; // Len -> Datenl<EFBFBD>nge 0 - 8 Byte
|
||||
unsigned Len:4; // Len -> Datenlänge 0 - 8 Byte
|
||||
unsigned TxD:1; // TxD -> 1 = Tx CAN Nachricht, 0 = Rx CAN Nachricht
|
||||
// Eine Erfolgreich versendete Nachricht wird als Best<EFBFBD>tigung
|
||||
// ins Empfangsfifo zur<EFBFBD>ckgeschrieben
|
||||
// Nicht alle Module unterst<EFBFBD>tzen diese Funktion u. das
|
||||
// Eine Erfolgreich versendete Nachricht wird als Bestätigung
|
||||
// ins Empfangsfifo zurückgeschrieben
|
||||
// Nicht alle Module unterstützen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned Error:1; // Error -> 1 = CAN Bus Fehler Nachricht
|
||||
// Nicht alle Module unterst<EFBFBD>tzen diese Funktion u. das
|
||||
// Nicht alle Module unterstützen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned RTR:1; // Remote Transmition Request bit -> Kennzeichnet eine RTR Nachricht
|
||||
unsigned EFF:1; // Extended Frame Format bit -> 1 = 29 Bit Id's, 0 = 11 Bit Id's
|
||||
@@ -193,15 +193,15 @@ struct TCanMsg
|
||||
struct TCanFdFlagsBits
|
||||
{
|
||||
unsigned Source:8; // Quelle der Nachricht (Device)
|
||||
unsigned Len:8; // Len -> Datenl<EFBFBD>nge 0 - 64 Byte
|
||||
unsigned Len:8; // Len -> Datenlänge 0 - 64 Byte
|
||||
|
||||
unsigned TxD:1; // TxD -> 1 = Tx CAN Nachricht, 0 = Rx CAN Nachricht
|
||||
// Eine Erfolgreich versendete Nachricht wird als Best<EFBFBD>tigung
|
||||
// ins Empfangsfifo zur<EFBFBD>ckgeschrieben
|
||||
// Nicht alle Module unterst<EFBFBD>tzen diese Funktion u. das
|
||||
// Eine Erfolgreich versendete Nachricht wird als Bestätigung
|
||||
// ins Empfangsfifo zurückgeschrieben
|
||||
// Nicht alle Module unterstützen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned Error:1; // Error -> 1 = CAN Bus Fehler Nachricht
|
||||
// Nicht alle Module unterst<EFBFBD>tzen diese Funktion u. das
|
||||
// Nicht alle Module unterstützen diese Funktion u. das
|
||||
// Feature muss aktiveirt sein
|
||||
unsigned RTR:1; // Remote Transmition Request bit -> Kennzeichnet eine RTR Nachricht
|
||||
unsigned EFF:1; // Extended Frame Format bit -> 1 = 29 Bit Id's, 0 = 11 Bit Id's
|
||||
|
||||
37
main.cpp
37
main.cpp
@@ -31,6 +31,7 @@
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSysInfo>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
@@ -40,35 +41,25 @@
|
||||
#include <bcmainwindow.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QApplication app(argc, argv);
|
||||
/*
|
||||
app.setStyleSheet(R"(
|
||||
QWidget {
|
||||
background-color: #F3F3F3;
|
||||
font-family: 'Segoe UI Variable', 'Segoe UI', sans-serif;
|
||||
}
|
||||
)");
|
||||
*/
|
||||
/*
|
||||
app.setStyleSheet(R"(
|
||||
* {
|
||||
font-family: 'Calibri', 'Carlito', 'Arial', sans-serif;
|
||||
font-size: 12pt;
|
||||
})");
|
||||
|
||||
*/
|
||||
//QFont font("segoe UI", 12); // Name, Größe
|
||||
//QFont font("calibri", 12); // Name, Größe
|
||||
//app.setFont(font);
|
||||
BCMainWindow mainWindow;
|
||||
//mainWindow.resize(800, 480);
|
||||
|
||||
if (QSysInfo::machineHostName() == BCTags::Host )
|
||||
{
|
||||
mainWindow.setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
|
||||
mainWindow.showFullScreen();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normaler Fenster-Modus (z. B. für die Entwicklung auf dem Desktop)
|
||||
mainWindow.show();
|
||||
}
|
||||
|
||||
BCMainWindow w;
|
||||
w.show();
|
||||
|
||||
return app.exec();
|
||||
|
||||
|
||||
90
nodes/nodes/ntx.h
Normal file
90
nodes/nodes/ntx.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef NTX_H
|
||||
#define NTX_H
|
||||
|
||||
#include <variant>
|
||||
#include <string>
|
||||
#include <QString>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Basistypen für die Kernbibliothek
|
||||
* unser string typ, ohne den namespace
|
||||
*
|
||||
* Wir nehmen hier std::string, der immer UTF-8 kodiert ist.
|
||||
* std::wstring ist plattformabhängig und führt zu Problemen. (Windows UTF-16 vs. Linux UTF-32)
|
||||
* std::string_view für als mögliche Alternative zu const std::string&
|
||||
*/
|
||||
|
||||
using NtxString = std::string;
|
||||
using NtxStringView = std::string_view;
|
||||
using NtxStringList = std::vector<NtxString>;
|
||||
|
||||
/**
|
||||
* @file ntx.h
|
||||
* Enthält die grundlegenden Typdefinitionen und Hilfsfunktionen
|
||||
* für die Kernbibliothek, z.B. NtxClassTypeId, NtxVariant und String-Konvertierungen.
|
||||
* Alle anderen Header (z.B. ntxinode.h, ntxipayload.h) inkludieren dieses als Basis.
|
||||
*/
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
// Datentyp für die Typid einer Klasse von Knoten (_nicht_ eines einzelen Knotens)
|
||||
// Option A: Performant (Aktuell)
|
||||
using NtxClassTypeId = uint64_t;
|
||||
|
||||
// Option B: Flexibel / Lesbar (Zukunft?)
|
||||
// using NtxClassTypeId = std::string;
|
||||
|
||||
// Option C: Legacy / Embedded
|
||||
// using NtxClassTypeId = uint32_t;
|
||||
|
||||
// Generischer Zugriff über std::variant (wie eingangs besprochen)
|
||||
using NtxVariant = std::variant<std::monostate, bool, int, double, NtxString>;
|
||||
|
||||
inline bool isEmpty(const NtxVariant& v) {
|
||||
return std::holds_alternative<std::monostate>(v);
|
||||
}
|
||||
|
||||
template<class... Ts>
|
||||
struct overload : Ts... { using Ts::operator()...; };
|
||||
|
||||
inline NtxString variantToString(const NtxVariant& v)
|
||||
{
|
||||
return std::visit(overload
|
||||
{
|
||||
[](std::monostate) { return NtxString{}; },
|
||||
[](const NtxString& s) { return s; },
|
||||
[](bool b) { return NtxString{b ? "true" : "false"}; },
|
||||
[](auto num) { return std::to_string(num); } // Catch-all für int, double
|
||||
}, v);
|
||||
}
|
||||
|
||||
// Core (UTF-8) -> Qt (UTF-16)
|
||||
// Uses SSO (Small String Optimization) from Qt where possible.
|
||||
inline QString toQt(const NtxString& str)
|
||||
{
|
||||
return QString::fromUtf8(str.data(), static_cast<int>(str.size()));
|
||||
}
|
||||
|
||||
inline QString toQt(NtxStringView str)
|
||||
{
|
||||
return QString::fromUtf8(str.data(), static_cast<int>(str.size()));
|
||||
}
|
||||
|
||||
// Qt (UTF-16) -> Core (UTF-8)
|
||||
inline NtxString fromQt(const QString& qstr)
|
||||
{
|
||||
return qstr.toStdString(); // Qt converts this internally via toUtf8()
|
||||
}
|
||||
|
||||
inline QString toQString(const NtxVariant& variant)
|
||||
{
|
||||
return toQt(variantToString(variant));
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
|
||||
#endif // NTX_H
|
||||
|
||||
73
nodes/nodes/ntxcompostionnode.h
Normal file
73
nodes/nodes/ntxcompostionnode.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef NTX_HASANODE_H
|
||||
#define NTX_HASANODE_H
|
||||
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <ntxnodebase.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Implementierung via Komposition (Has-A).
|
||||
*
|
||||
* Hält die Payload als Member 'm_payload'.
|
||||
*/
|
||||
template<typename TPayload>
|
||||
class NtxHasANode : public NtxNodeBase
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Konstruktor forwarding an m_payload
|
||||
template<typename... Args>
|
||||
explicit NtxHasANode(Args&&... args)
|
||||
: NtxNodeBase{},
|
||||
m_payload{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// NtxINode Interface: Payload Forwarding
|
||||
// ========================================
|
||||
|
||||
size_t getValueCount() const override { return m_payload.getValueCount(); }
|
||||
void clearValues() override { m_payload.clearValues(); }
|
||||
|
||||
bool hasValue(const NtxString& key) const override { return m_payload.hasValue(key); }
|
||||
void setValue(const NtxString& key, const NtxVariant& value) override { m_payload.setValue(key, value); }
|
||||
NtxVariant getValue(const NtxString& key) const override { return m_payload.getValue(key); }
|
||||
void removeValue(const NtxString& key) override { m_payload.removeValue(key); }
|
||||
|
||||
bool hasValue(size_t index) const override { return m_payload.hasValue(index); }
|
||||
void setValue(size_t index, const NtxVariant& value) override { m_payload.setValue(index, value); }
|
||||
NtxVariant getValue(size_t index) const override { return m_payload.getValue(index); }
|
||||
|
||||
// Deducing This Support (Raw Access)
|
||||
// TPayload muss doGetValues() oder Zugriff auf den Vektor unterstützen
|
||||
std::vector<NtxVariant>& doGetValues() override { return m_payload.doGetValues(); }
|
||||
const std::vector<NtxVariant>& doGetValues() const override { return m_payload.doGetValues(); }
|
||||
|
||||
void forEachAttribute(NtxPayloadVisitor visitor) const override
|
||||
{
|
||||
m_payload.forEachAttribute(visitor);
|
||||
}
|
||||
|
||||
NtxNodePtr clone() const override
|
||||
{
|
||||
auto newNode = std::make_shared<NtxHasANode<TPayload>>();
|
||||
newNode->m_payload = this->m_payload; // Copy Payload
|
||||
newNode->setClassTypeId(this->getClassTypeId());
|
||||
return newNode;
|
||||
}
|
||||
|
||||
protected:
|
||||
TPayload m_payload;
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_HASANODE_H
|
||||
115
nodes/nodes/ntxibasicnode.cpp
Normal file
115
nodes/nodes/ntxibasicnode.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <ntxibasicnode.h>
|
||||
#include <ntxnodefactory.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
// ========================================
|
||||
// NtxINode Interface: CType Aspekt
|
||||
// ========================================
|
||||
|
||||
const NtxClassTypeId NtxIBasicNode::getClassTypeId() const
|
||||
{
|
||||
return m_ctypeId;
|
||||
}
|
||||
|
||||
const NtxString& NtxIBasicNode::getClassTypeLabel() const
|
||||
{
|
||||
return NtxNodeFactory::lookupCTypeLabel(getClassTypeId());
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// NtxINode Interface: Tree Structure
|
||||
// ========================================
|
||||
|
||||
void NtxIBasicNode::setParent(NtxNodePtr parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
size_t NtxIBasicNode::getChildCount() const
|
||||
{
|
||||
return m_children.size();
|
||||
}
|
||||
|
||||
bool NtxIBasicNode::hasChildren() const
|
||||
{
|
||||
return !m_children.empty();
|
||||
}
|
||||
|
||||
void NtxIBasicNode::addChild(NtxNodePtr child)
|
||||
{
|
||||
if (child)
|
||||
{
|
||||
m_children.push_back(child);
|
||||
child->setParent(this->shared_from_this());
|
||||
}
|
||||
}
|
||||
|
||||
void NtxIBasicNode::insertChild(size_t index, NtxNodePtr child)
|
||||
{
|
||||
if (!child) return;
|
||||
|
||||
if (index >= m_children.size())
|
||||
m_children.push_back(child);
|
||||
else
|
||||
m_children.insert(m_children.begin() + index, child);
|
||||
|
||||
child->setParent(this->shared_from_this());
|
||||
}
|
||||
|
||||
bool NtxIBasicNode::removeChild(size_t index)
|
||||
{
|
||||
if (index >= m_children.size()) return false;
|
||||
|
||||
if (m_children[index])
|
||||
m_children[index]->setParent(nullptr);
|
||||
|
||||
m_children.erase(m_children.begin() + index);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t NtxIBasicNode::getChildIndex(const NtxNodePtr& child) const
|
||||
{
|
||||
for (size_t i = 0; i < m_children.size(); ++i)
|
||||
{
|
||||
if (m_children[i] == child) return i;
|
||||
}
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
|
||||
void NtxIBasicNode::clearChildren()
|
||||
{
|
||||
for (auto& child : m_children)
|
||||
{
|
||||
if (child) child->setParent(nullptr);
|
||||
}
|
||||
m_children.clear();
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Protected Hooks
|
||||
// ========================================
|
||||
|
||||
void NtxIBasicNode::setClassTypeLabel(const NtxString& idString)
|
||||
{
|
||||
setClassTypeId(NtxNodeFactory::generateCTypeId(idString));
|
||||
}
|
||||
|
||||
void NtxIBasicNode::setClassTypeId(NtxClassTypeId classTypeId)
|
||||
{
|
||||
m_ctypeId = classTypeId;
|
||||
}
|
||||
|
||||
NtxNodePtr NtxIBasicNode::doGetParent() const noexcept
|
||||
{
|
||||
return m_parent.lock();
|
||||
}
|
||||
|
||||
NtxNodePtr NtxIBasicNode::doGetChild(size_t index) const noexcept
|
||||
{
|
||||
if (index >= m_children.size()) return nullptr;
|
||||
return m_children[index];
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
66
nodes/nodes/ntxibasicnode.h
Normal file
66
nodes/nodes/ntxibasicnode.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef NTX_NODEBASE_H
|
||||
#define NTX_NODEBASE_H
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <ntxinode.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Abstrakte Basisklasse, die Baumstruktur und Typ-Information verwaltet.
|
||||
*
|
||||
* Implementiert alle Aspekte von NtxINode, die unabhängig von der Payload sind.
|
||||
*/
|
||||
class NtxIBasicNode : public NtxINode
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NtxIBasicNode() = default;
|
||||
~NtxIBasicNode() override = default;
|
||||
|
||||
// ========================================
|
||||
// NtxINode Interface: CType Aspekt
|
||||
// ========================================
|
||||
|
||||
const NtxClassTypeId getClassTypeId() const override;
|
||||
const NtxString& getClassTypeLabel() const override;
|
||||
|
||||
// ========================================
|
||||
// NtxINode Interface: Tree Structure
|
||||
// ========================================
|
||||
|
||||
void setParent(NtxNodePtr parent) override;
|
||||
|
||||
size_t getChildCount() const override;
|
||||
bool hasChildren() const override;
|
||||
|
||||
void addChild(NtxNodePtr child) override;
|
||||
void insertChild(size_t index, NtxNodePtr child) override;
|
||||
bool removeChild(size_t index) override;
|
||||
size_t getChildIndex(const NtxNodePtr& child) const override;
|
||||
void clearChildren() override;
|
||||
|
||||
protected:
|
||||
|
||||
// --- Implementierung virtueller Hooks ---
|
||||
|
||||
void setClassTypeLabel(const NtxString& idString) override;
|
||||
void setClassTypeId(NtxClassTypeId classTypeId) override;
|
||||
|
||||
NtxNodePtr doGetParent() const noexcept override;
|
||||
NtxNodePtr doGetChild(size_t index) const noexcept override;
|
||||
|
||||
protected:
|
||||
|
||||
NtxClassTypeId m_ctypeId{};
|
||||
NtxNodeWeakPtr m_parent;
|
||||
NtxNodeList m_children;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_NODEBASE_H
|
||||
37
nodes/nodes/ntxiclasstype.h
Normal file
37
nodes/nodes/ntxiclasstype.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef NTX_ICLASSTYPE_H
|
||||
#define NTX_ICLASSTYPE_H
|
||||
|
||||
#include <ntx.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Minimales Interface für den 'ClassType' Aspekt: Der CType entspricht
|
||||
* dem Element-namen eines Knotens im XML. Die ClassTypeId ist eine performante
|
||||
* Repräsentation (z.B. Hash) dieses Namens. Kann unterschiedliche Implementierungen haben,
|
||||
* z.B.: einfaches Hochzählen, Hash des Strings, den String selbst oder eine Meta-Klasse,
|
||||
* vgl. QObject.
|
||||
*/
|
||||
|
||||
class NtxIClassType
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual ~NtxIClassType() = default;
|
||||
|
||||
virtual const NtxClassTypeId getClassTypeId() const = 0;
|
||||
virtual const NtxString& getClassTypeLabel() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
// ✅ Protected - nur abgeleitete Klassen und Friends
|
||||
virtual void setClassTypeLabel(const NtxString& idString) = 0;
|
||||
virtual void setClassTypeId(NtxClassTypeId classTypeId) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_ICLASSTYPE_H
|
||||
143
nodes/nodes/ntxiclasstyperepo.cpp
Normal file
143
nodes/nodes/ntxiclasstyperepo.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
|
||||
|
||||
#include <ntxiclasstyperepo.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
// =========================================================
|
||||
// NtxCTypeHashRepo
|
||||
// =========================================================
|
||||
|
||||
NtxClassTypeId NtxCTypeHashRepo::generateId(const NtxString& label)
|
||||
{
|
||||
std::hash<NtxString> hasher;
|
||||
// Expliziter Cast falls NtxClassTypeId kleiner als size_t ist
|
||||
NtxClassTypeId id = static_cast<NtxClassTypeId>(hasher(label));
|
||||
|
||||
// Optimistischer Check (Read Lock)
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
if (m_idToLabel.find(id) != m_idToLabel.end())
|
||||
return id;
|
||||
}
|
||||
|
||||
// Registrieren (Write Lock)
|
||||
{
|
||||
std::unique_lock lock(m_mutex);
|
||||
m_idToLabel[id] = label;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
NtxClassTypeId NtxCTypeHashRepo::lookupId(const NtxString& label) const
|
||||
{
|
||||
std::hash<NtxString> hasher;
|
||||
NtxClassTypeId id = static_cast<NtxClassTypeId>(hasher(label));
|
||||
|
||||
if (isRegistered(id))
|
||||
return id;
|
||||
|
||||
return {}; // Default constructed ID (0)
|
||||
}
|
||||
|
||||
const NtxString& NtxCTypeHashRepo::lookupLabel(NtxClassTypeId id) const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
auto it = m_idToLabel.find(id);
|
||||
if (it != m_idToLabel.end())
|
||||
return it->second;
|
||||
|
||||
static const NtxString empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
bool NtxCTypeHashRepo::isRegistered(NtxClassTypeId id) const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
return m_idToLabel.find(id) != m_idToLabel.end();
|
||||
}
|
||||
|
||||
bool NtxCTypeHashRepo::isRegistered(const NtxString& label) const
|
||||
{
|
||||
std::hash<NtxString> hasher;
|
||||
return isRegistered(static_cast<NtxClassTypeId>(hasher(label)));
|
||||
}
|
||||
|
||||
size_t NtxCTypeHashRepo::getRegisteredCount() const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
return m_idToLabel.size();
|
||||
}
|
||||
|
||||
|
||||
// =========================================================
|
||||
// NtxCTypeCounterRepo
|
||||
// =========================================================
|
||||
|
||||
NtxCTypeCounterRepo::NtxCTypeCounterRepo()
|
||||
: m_nextId(1) // Start bei 1, 0 ist invalid
|
||||
{
|
||||
}
|
||||
|
||||
NtxClassTypeId NtxCTypeCounterRepo::generateId(const NtxString& label)
|
||||
{
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
auto it = m_labelToId.find(label);
|
||||
if (it != m_labelToId.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock lock(m_mutex);
|
||||
// Double check
|
||||
if (auto it = m_labelToId.find(label); it != m_labelToId.end())
|
||||
return it->second;
|
||||
|
||||
NtxClassTypeId newId = m_nextId++;
|
||||
m_idToLabel[newId] = label;
|
||||
m_labelToId[label] = newId;
|
||||
|
||||
return newId;
|
||||
}
|
||||
}
|
||||
|
||||
NtxClassTypeId NtxCTypeCounterRepo::lookupId(const NtxString& label) const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
auto it = m_labelToId.find(label);
|
||||
if (it != m_labelToId.end())
|
||||
return it->second;
|
||||
return {};
|
||||
}
|
||||
|
||||
const NtxString& NtxCTypeCounterRepo::lookupLabel(NtxClassTypeId id) const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
auto it = m_idToLabel.find(id);
|
||||
if (it != m_idToLabel.end())
|
||||
return it->second;
|
||||
|
||||
static const NtxString empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
bool NtxCTypeCounterRepo::isRegistered(NtxClassTypeId id) const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
return m_idToLabel.find(id) != m_idToLabel.end();
|
||||
}
|
||||
|
||||
bool NtxCTypeCounterRepo::isRegistered(const NtxString& label) const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
return m_labelToId.find(label) != m_labelToId.end();
|
||||
}
|
||||
|
||||
size_t NtxCTypeCounterRepo::getRegisteredCount() const
|
||||
{
|
||||
std::shared_lock lock(m_mutex);
|
||||
return m_idToLabel.size();
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
126
nodes/nodes/ntxiclasstyperepo.h
Normal file
126
nodes/nodes/ntxiclasstyperepo.h
Normal file
@@ -0,0 +1,126 @@
|
||||
#ifndef NTX_CTYPEREPOSITORY_H
|
||||
#define NTX_CTYPEREPOSITORY_H
|
||||
|
||||
#include <ntx.h>
|
||||
#include <unordered_map>
|
||||
#include <shared_mutex>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
/**
|
||||
* @brief Repository Interface für CType ID Management.
|
||||
* Entkoppelt die ID-Generierungsstrategie von der Knoten-Implementierung.
|
||||
*/
|
||||
class NtxIClassTypeRepo
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual ~NtxIClassTypeRepo() = default;
|
||||
|
||||
// Generiert oder holt eine ID für das Label
|
||||
virtual NtxClassTypeId generateId(const NtxString& label) = 0;
|
||||
|
||||
// Lookups (Thread-safe read)
|
||||
virtual NtxClassTypeId lookupId(const NtxString& label) const = 0;
|
||||
virtual const NtxString& lookupLabel(NtxClassTypeId id) const = 0;
|
||||
|
||||
// Checks
|
||||
virtual bool isRegistered(NtxClassTypeId id) const = 0;
|
||||
virtual bool isRegistered(const NtxString& label) const = 0;
|
||||
|
||||
// Diagnostics
|
||||
virtual size_t getRegisteredCount() const = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Hash-basierte Implementierung (std::hash).
|
||||
*/
|
||||
class NtxCTypeHashRepo : public NtxIClassTypeRepo
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NtxClassTypeId generateId(const NtxString& label) override;
|
||||
NtxClassTypeId lookupId(const NtxString& label) const override;
|
||||
const NtxString& lookupLabel(NtxClassTypeId id) const override;
|
||||
|
||||
bool isRegistered(NtxClassTypeId id) const override;
|
||||
bool isRegistered(const NtxString& label) const override;
|
||||
size_t getRegisteredCount() const override;
|
||||
|
||||
private:
|
||||
|
||||
std::unordered_map<NtxClassTypeId, NtxString> m_idToLabel;
|
||||
mutable std::shared_mutex m_mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Zähler-basierte Implementierung (1, 2, 3...).
|
||||
*/
|
||||
class NtxCTypeCounterRepo : public NtxIClassTypeRepo
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NtxCTypeCounterRepo();
|
||||
|
||||
NtxClassTypeId generateId(const NtxString& label) override;
|
||||
NtxClassTypeId lookupId(const NtxString& label) const override;
|
||||
const NtxString& lookupLabel(NtxClassTypeId id) const override;
|
||||
|
||||
bool isRegistered(NtxClassTypeId id) const override;
|
||||
bool isRegistered(const NtxString& label) const override;
|
||||
size_t getRegisteredCount() const override;
|
||||
|
||||
private:
|
||||
|
||||
std::unordered_map<NtxClassTypeId, NtxString> m_idToLabel;
|
||||
std::unordered_map<NtxString, NtxClassTypeId> m_labelToId;
|
||||
NtxClassTypeId m_nextId;
|
||||
mutable std::shared_mutex m_mutex;
|
||||
|
||||
|
||||
/*
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
#include <cstdint>
|
||||
|
||||
constexpr uint64_t fnv1a_64(std::string_view text) {
|
||||
uint64_t hash = 14695981039346656037ull; // 64-bit offset
|
||||
for (char c : text) {
|
||||
hash ^= static_cast<uint64_t>(c);
|
||||
hash *= 1099511628211ull; // 64-bit prime
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Ein Funktor (Funktionsobjekt), das die STL-Vorgaben für Hash-Funktionen erfüllt
|
||||
struct FastFnv1aHasher {
|
||||
std::size_t operator()(std::string_view sv) const {
|
||||
// (Nutzt hier die fnv1a_64 Funktion von oben)
|
||||
return fnv1a_64(sv);
|
||||
}
|
||||
};
|
||||
|
||||
// Deine Map:
|
||||
// Key: string_view (Zero-Copy)
|
||||
// Value: MyData
|
||||
// Hasher: Dein eigener, pfeilschneller FNV-1a (statt dem langsamen std::hash)
|
||||
std::unordered_map<std::string_view, MyData, FastFnv1aHasher> xmlElements;
|
||||
|
||||
OBACHT! Lifetime! Woher kommt die StringView ?
|
||||
|
||||
-> doch: string internisieren ! -> Aber was ist mit copy_over_net ?
|
||||
claude.ai: String Interning ist die richtige Wahl
|
||||
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_CTYPEREPOSITORY_H
|
||||
33
nodes/nodes/ntxinode.cpp
Normal file
33
nodes/nodes/ntxinode.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
|
||||
#include <ntxinode.h>
|
||||
#include <ntxnodeiterators.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/*
|
||||
NtxNodeIterator NtxINode::begin()
|
||||
{
|
||||
return NtxNodeIterator(this);
|
||||
}
|
||||
|
||||
NtxNodeIterator NtxINode::end()
|
||||
{
|
||||
return NtxNodeIterator();
|
||||
}
|
||||
|
||||
NtxCNodeIterator NtxINode::begin() const
|
||||
{
|
||||
return NtxCNodeIterator(this);
|
||||
}
|
||||
|
||||
NtxCNodeIterator NtxINode::end() const
|
||||
{
|
||||
return NtxCNodeIterator();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
176
nodes/nodes/ntxinode.h
Normal file
176
nodes/nodes/ntxinode.h
Normal file
@@ -0,0 +1,176 @@
|
||||
#ifndef NTX_INODE_H
|
||||
#define NTX_INODE_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <ranges> // for std::ranges::subrange
|
||||
#include <type_traits> // for std::conditional_t, std::is_const_v
|
||||
|
||||
#include <ntx.h>
|
||||
#include <ntxiclasstype.h>
|
||||
#include <ntxipayload.h>
|
||||
#include <ntxnodeiterators.h>
|
||||
|
||||
/**
|
||||
* @file ntxinode.h
|
||||
* NtxINode ist die zentrale Schnittstelle, die NtxIClassType und NtxIPayload vereint
|
||||
* und zusätzlich die Baumstruktur definiert.
|
||||
*/
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
class NtxINode;
|
||||
|
||||
template<typename T>
|
||||
struct NtxNodeDepthFirstIterator;
|
||||
|
||||
using NtxNodePtr = std::shared_ptr<NtxINode>;
|
||||
using NtxNodeCPtr = std::shared_ptr<const NtxINode>;
|
||||
using NtxNodeWeakPtr = std::weak_ptr<NtxINode>;
|
||||
using NtxNodeList = std::vector<NtxNodePtr>;
|
||||
|
||||
using NtxNodeIterator = NtxNodeDepthFirstIterator<NtxINode>;
|
||||
using NtxCNodeIterator = NtxNodeDepthFirstIterator<const NtxINode>;
|
||||
|
||||
/**
|
||||
* @brief Zentrales Interface für einen Knoten im Baum. Basiert auf NtxIClassType und NtxIPayload.
|
||||
* Gibt die Baumstruktur vor (Eltern, Kinder, Geschwister) und bietet Iteratoren für die Traversierung.
|
||||
* Die konkrete Implementierung erfolgt in NtxNode oder abgeleiteten Klassen.
|
||||
* Nutzlast- und ClassType-Aspekte können durch Mixins realisiert werden.
|
||||
*/
|
||||
|
||||
class NtxINode :
|
||||
|
||||
public NtxIClassType,
|
||||
public NtxIPayload,
|
||||
public std::enable_shared_from_this<NtxINode>
|
||||
|
||||
{
|
||||
friend class NtxNodeFactory;
|
||||
friend class NtxLinkNode;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~NtxINode() = default;
|
||||
|
||||
// --- Tree Structure ---
|
||||
virtual void setParent(NtxNodePtr parent) = 0;
|
||||
|
||||
// Vereinfacht durch Deducing this und if constexpr
|
||||
template <typename Self>
|
||||
auto getParent(this Self&& self)
|
||||
{
|
||||
auto ptr = self.doGetParent();
|
||||
if constexpr (std::is_const_v<std::remove_reference_t<Self>>)
|
||||
return std::const_pointer_cast<const NtxINode>(ptr);
|
||||
else
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
auto getChild(this Self&& self, size_t index)
|
||||
{
|
||||
auto ptr = self.doGetChild(index);
|
||||
if constexpr (std::is_const_v<std::remove_reference_t<Self>>)
|
||||
return std::const_pointer_cast<const NtxINode>(ptr);
|
||||
else
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
auto getSibling(this Self&& self)
|
||||
{
|
||||
auto parent = self.getParent();
|
||||
using ResultType = decltype(parent); // NtxNodePtr oder NtxNodeCPtr
|
||||
|
||||
if (!parent) return ResultType{};
|
||||
|
||||
const size_t childCount = parent->getChildCount();
|
||||
|
||||
for (size_t i = 0; i < childCount; ++i)
|
||||
{
|
||||
auto child = parent->getChild(i);
|
||||
// Hinweis: child.get() ist raw-pointer, &self ist Adresse des aktuellen Objekts
|
||||
if (child.get() == &self)
|
||||
{
|
||||
if (i + 1 < childCount)
|
||||
return parent->getChild(i + 1);
|
||||
else
|
||||
return ResultType{};
|
||||
}
|
||||
}
|
||||
return ResultType{};
|
||||
}
|
||||
|
||||
std::optional<size_t> ownPos() const
|
||||
{
|
||||
auto parent = doGetParent(); // Nutze internal (non-deducing) getter um const-cast zu vermeiden
|
||||
if (!parent) return std::nullopt;
|
||||
|
||||
const size_t childCount = parent->getChildCount();
|
||||
|
||||
for (size_t i = 0; i < childCount; ++i)
|
||||
{
|
||||
auto child = parent->getChild(i); // NtxNodePtr comparison
|
||||
if (child.get() == this)
|
||||
return i;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
virtual size_t getChildCount() const = 0;
|
||||
virtual bool hasChildren() const = 0;
|
||||
|
||||
virtual void addChild(NtxNodePtr child) = 0;
|
||||
virtual void insertChild(size_t index, NtxNodePtr child) = 0;
|
||||
virtual bool removeChild(size_t index) = 0;
|
||||
virtual size_t getChildIndex(const NtxNodePtr& child) const = 0;
|
||||
virtual void clearChildren() = 0;
|
||||
|
||||
virtual NtxNodePtr clone() const = 0;
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Unified Iterators via Deducing This
|
||||
// =======================================================================
|
||||
|
||||
// Ersetzt begin/end und cbegin/cend Logik
|
||||
template <typename Self>
|
||||
auto begin(this Self&& self)
|
||||
{
|
||||
using NodeType = std::remove_reference_t<Self>; // NtxINode oder const NtxINode
|
||||
// Konstruktor erwartet Pointer, &self ist sicher
|
||||
return NtxNodeDepthFirstIterator<NodeType>(&self);
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
auto end(this Self&& self)
|
||||
{
|
||||
using NodeType = std::remove_reference_t<Self>;
|
||||
return NtxNodeDepthFirstIterator<NodeType>();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// Ranges Support (C++23 Style)
|
||||
// =======================================================================
|
||||
|
||||
template <typename Self>
|
||||
auto descendants(this Self&& self)
|
||||
{
|
||||
return std::ranges::subrange(self.begin(), self.end());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual NtxNodePtr doGetParent() const = 0;
|
||||
virtual NtxNodePtr doGetChild(size_t index) const = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_INODE_H
|
||||
|
||||
98
nodes/nodes/ntxipayload.h
Normal file
98
nodes/nodes/ntxipayload.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#ifndef NTX_IPAYLOAD_H
|
||||
#define NTX_IPAYLOAD_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <variant> // for std::get_if
|
||||
#include <functional> // for std::function
|
||||
#include <type_traits> // for std::remove_reference_t
|
||||
|
||||
#include <ntx.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
class NtxIPayload;
|
||||
|
||||
using NtxPayloadVisitor = std::function<void(const NtxString&, const NtxVariant&)> const;
|
||||
using NtxPayloadPtr = std::shared_ptr<NtxIPayload>;
|
||||
|
||||
// --- Payload Iterator-Typen (analog zu NtxMaptor<NtxVariant>) ---
|
||||
using NtxPayloadIterator = std::vector<NtxVariant>::iterator;
|
||||
using NtxPayloadCIterator = std::vector<NtxVariant>::const_iterator;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Minimales Interface für 'Nutzlast' Aspekt. Kann beliebige Key-Value Paare speichern,
|
||||
* wobei die Werte über NtxVariant typisiert sind. Implementierungen können intern
|
||||
* z.B. std::unordered_map verwenden, einen 'Maptor' oder auf eine Meta-Klasse verweisen
|
||||
* Das Interface bietet auch typsichere Zugriffsmethoden über Templates, die auf std::variant basieren.
|
||||
*/
|
||||
|
||||
class NtxIPayload
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual ~NtxIPayload() = default;
|
||||
|
||||
virtual size_t getPropertyCount() const = 0;
|
||||
virtual void clearProperties() = 0;
|
||||
|
||||
// --- NtxIPayload Interface: Key-basiert ---
|
||||
virtual bool hasProperty(const NtxString& key) const = 0;
|
||||
virtual void setProperty(const NtxString& key, const NtxVariant& value) = 0;
|
||||
virtual NtxVariant getProperty(const NtxString& key) const = 0;
|
||||
virtual void removeProperty(const NtxString& key) = 0;
|
||||
|
||||
// --- NtxIPayload Interface: Index-basiert ---
|
||||
virtual bool hasProperty(size_t index) const = 0;
|
||||
virtual void setProperty(size_t index, const NtxVariant& value) = 0;
|
||||
virtual NtxVariant getProperty(size_t index) const = 0;
|
||||
|
||||
//virtual NtxIPayload clone() const = 0;
|
||||
template<typename TPayload>
|
||||
TPayload clonePayload() const
|
||||
{
|
||||
return TPayload(*this);
|
||||
}
|
||||
|
||||
// --- Payload Wrapper (Convenience) ---
|
||||
template <typename T>
|
||||
void set(const NtxString& key, T&& value)
|
||||
{
|
||||
setProperty(key, NtxVariant(std::forward<T>(value)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> get(const NtxString& key) const
|
||||
{
|
||||
// 1. Hole rohen Variant
|
||||
NtxVariant raw = getProperty(key);
|
||||
|
||||
// 2. Prüfe ob der Typ T im Variant aktiv ist
|
||||
// std::get_if liefert nullptr, wenn der Typ nicht passt.
|
||||
if (const T* valPtr = std::get_if<T>(&raw))
|
||||
return *valPtr;
|
||||
// Typ passt nicht oder Key existiert nicht (monostate)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// @brief Komfort-Überladung: Liefert 'defaultValue', wenn Key fehlt oder Typ falsch ist.
|
||||
template <typename T>
|
||||
T get(const NtxString& key, const T& defaultValue) const
|
||||
{
|
||||
auto res = get<T>(key);
|
||||
if (res.has_value())
|
||||
return res.value();
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
virtual void forEachProperty(NtxPayloadVisitor visitor) const = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_IPAYLOAD_H
|
||||
212
nodes/nodes/ntxlinknode.cpp
Normal file
212
nodes/nodes/ntxlinknode.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
#include <ntxlinknode.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <ntxnodeiterators.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
class NtxProxyNodeExpiredException : public std::runtime_error
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
NtxNodePtr lockOriginalNodeOrThrow(const NtxNodeWeakPtr& original)
|
||||
{
|
||||
auto orig = original.lock();
|
||||
if (!orig)
|
||||
throw NtxProxyNodeExpiredException("NtxLinkNode: Original node expired");
|
||||
return orig;
|
||||
}
|
||||
|
||||
NtxNodeCPtr lockOriginalNodeOrThrowConst(const NtxNodeWeakPtr& original)
|
||||
{
|
||||
auto orig = original.lock();
|
||||
if (!orig)
|
||||
throw NtxProxyNodeExpiredException("NtxLinkNode: Original node expired");
|
||||
return orig;
|
||||
}
|
||||
}
|
||||
|
||||
// Private constructor
|
||||
NtxLinkNode::NtxLinkNode(NtxNodePtr originalNode)
|
||||
: m_originalNode{originalNode}
|
||||
{
|
||||
if (!originalNode)
|
||||
{
|
||||
throw std::invalid_argument("NtxLinkNode: Original node cannot be nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
// Factory method
|
||||
NtxNodePtr NtxLinkNode::makeLink(NtxNodePtr originalNode)
|
||||
{
|
||||
return std::shared_ptr<NtxLinkNode>(new NtxLinkNode(originalNode));
|
||||
}
|
||||
|
||||
void NtxLinkNode::setParent(NtxNodePtr parent)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->setParent(parent);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Type Access
|
||||
// =========================================================================
|
||||
|
||||
const NtxClassTypeId NtxLinkNode::getClassTypeId() const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getClassTypeId();
|
||||
}
|
||||
|
||||
const NtxString& NtxLinkNode::getClassTypeLabel() const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getClassTypeLabel();
|
||||
}
|
||||
|
||||
void NtxLinkNode::setClassTypeLabel(const NtxString& idString)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->setClassTypeLabel(idString);
|
||||
}
|
||||
|
||||
void NtxLinkNode::setClassTypeId(NtxClassTypeId classTypeId)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->setClassTypeId(classTypeId);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Original Node Access
|
||||
// =========================================================================
|
||||
|
||||
NtxNodePtr NtxLinkNode::getOriginalNode()
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode);
|
||||
}
|
||||
|
||||
NtxNodeCPtr NtxLinkNode::getOriginalNode() const
|
||||
{
|
||||
return lockOriginalNodeOrThrowConst(m_originalNode);
|
||||
}
|
||||
|
||||
bool NtxLinkNode::isValid() const
|
||||
{
|
||||
return !m_originalNode.expired();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Payload: Key-basiert
|
||||
// =========================================================================
|
||||
|
||||
bool NtxLinkNode::hasProperty(const NtxString& key) const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->hasProperty(key);
|
||||
}
|
||||
|
||||
void NtxLinkNode::setProperty(const NtxString& key, const NtxVariant& value)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->setProperty(key, value);
|
||||
}
|
||||
|
||||
NtxVariant NtxLinkNode::getProperty(const NtxString& key) const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getProperty(key);
|
||||
}
|
||||
|
||||
void NtxLinkNode::removeProperty(const NtxString& key)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->removeProperty(key);
|
||||
}
|
||||
|
||||
void NtxLinkNode::clearProperties()
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->clearProperties();
|
||||
}
|
||||
|
||||
void NtxLinkNode::forEachProperty(NtxPayloadVisitor visitor) const
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->forEachProperty(visitor);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Payload: Index-basiert
|
||||
// =========================================================================
|
||||
|
||||
bool NtxLinkNode::hasProperty(size_t index) const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->hasProperty(index);
|
||||
}
|
||||
|
||||
void NtxLinkNode::setProperty(size_t index, const NtxVariant& value)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->setProperty(index, value);
|
||||
}
|
||||
|
||||
NtxVariant NtxLinkNode::getProperty(size_t index) const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getProperty(index);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Children
|
||||
// =========================================================================
|
||||
|
||||
size_t NtxLinkNode::getChildCount() const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getChildCount();
|
||||
}
|
||||
|
||||
bool NtxLinkNode::hasChildren() const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->hasChildren();
|
||||
}
|
||||
|
||||
NtxNodePtr NtxLinkNode::doGetParent() const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->doGetParent();
|
||||
}
|
||||
|
||||
NtxNodePtr NtxLinkNode::doGetChild(size_t index) const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getChild(index);
|
||||
}
|
||||
|
||||
void NtxLinkNode::addChild(NtxNodePtr child)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->addChild(child);
|
||||
}
|
||||
|
||||
bool NtxLinkNode::removeChild(size_t index)
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->removeChild(index);
|
||||
}
|
||||
|
||||
void NtxLinkNode::clearChildren()
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->clearChildren();
|
||||
}
|
||||
|
||||
NtxNodePtr NtxLinkNode::clone() const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->clone();
|
||||
}
|
||||
|
||||
void NtxLinkNode::insertChild(size_t index, NtxNodePtr child)
|
||||
{
|
||||
lockOriginalNodeOrThrow(m_originalNode)->insertChild(index, child);
|
||||
}
|
||||
|
||||
size_t NtxLinkNode::getChildIndex(const NtxNodePtr& child) const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getChildIndex(child);
|
||||
}
|
||||
|
||||
size_t NtxLinkNode::getPropertyCount() const
|
||||
{
|
||||
return lockOriginalNodeOrThrow(m_originalNode)->getPropertyCount();
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
72
nodes/nodes/ntxlinknode.h
Normal file
72
nodes/nodes/ntxlinknode.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef NTX_LINKNODE_H
|
||||
#define NTX_LINKNODE_H
|
||||
|
||||
#include <ntxinode.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
class NtxLinkNode : public NtxINode
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Factory method to create a link to an original node
|
||||
static NtxNodePtr makeLink(NtxNodePtr originalNode);
|
||||
|
||||
void setParent(NtxNodePtr parent) override;
|
||||
|
||||
const NtxClassTypeId getClassTypeId() const override;
|
||||
const NtxString& getClassTypeLabel() const override;
|
||||
void setClassTypeLabel(const NtxString& idString) override;
|
||||
void setClassTypeId(const NtxClassTypeId classTypeId) override;
|
||||
|
||||
// Kinder
|
||||
size_t getChildCount() const override;
|
||||
bool hasChildren() const override;
|
||||
|
||||
void addChild(NtxNodePtr child) override;
|
||||
void insertChild(size_t index, NtxNodePtr child) override;
|
||||
bool removeChild(size_t index) override;
|
||||
size_t getChildIndex(const NtxNodePtr& child) const override;
|
||||
size_t getPropertyCount() const override;
|
||||
void clearChildren() override;
|
||||
|
||||
NtxNodePtr clone() const override;
|
||||
|
||||
// Payload: Key-basiert
|
||||
bool hasProperty(const NtxString& key) const override;
|
||||
void setProperty(const NtxString& key, const NtxVariant& value) override;
|
||||
NtxVariant getProperty(const NtxString& key) const override;
|
||||
void removeProperty(const NtxString& key) override;
|
||||
void clearProperties() override;
|
||||
void forEachProperty(NtxPayloadVisitor visitor) const override;
|
||||
|
||||
// Payload: Index-basiert
|
||||
bool hasProperty(size_t index) const override;
|
||||
void setProperty(size_t index, const NtxVariant& value) override;
|
||||
NtxVariant getProperty(size_t index) const override;
|
||||
|
||||
// Returns the original node this link points to
|
||||
NtxNodePtr getOriginalNode();
|
||||
NtxNodeCPtr getOriginalNode() const;
|
||||
|
||||
// Checks if the link is still valid (original node exists)
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
|
||||
NtxNodePtr doGetParent() const override;
|
||||
NtxNodePtr doGetChild(size_t index) const override;
|
||||
|
||||
// Private constructor - use makeLink() factory method
|
||||
explicit NtxLinkNode(NtxNodePtr originalNode);
|
||||
|
||||
// Weak pointer to avoid circular references
|
||||
NtxNodeWeakPtr m_originalNode;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_LINKNODE_H
|
||||
18
nodes/nodes/ntxnode.cpp
Normal file
18
nodes/nodes/ntxnode.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <ntxnode.h>
|
||||
#include <ntxnodefactory.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
// Für Factory mit CTypeId
|
||||
NtxNode::NtxNode(NtxClassTypeId id)
|
||||
: NtxNode()
|
||||
{
|
||||
setClassTypeId(id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
45
nodes/nodes/ntxnode.h
Normal file
45
nodes/nodes/ntxnode.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef NTX_NODE_H
|
||||
#define NTX_NODE_H
|
||||
|
||||
#include <ntxtcloneable.h>
|
||||
#include <ntxtaggregatenode.h>
|
||||
#include <ntxtmixinnode.h>
|
||||
#include <ntxmaptor.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
class NtxNodeFactory;
|
||||
|
||||
using NtxVariantMaptor = NtxMaptor<NtxVariant>;
|
||||
using NtxMixInNode = NtxTMixInNode<NtxVariantMaptor>;
|
||||
using NtxAggregateNode = NtxTAggregateNode<NtxVariantMaptor>;
|
||||
|
||||
//class NtxNode : public NtxTCloneable<NtxNode, NtxMixInNode>
|
||||
class NtxNode : public NtxTCloneable<NtxNode, NtxAggregateNode>
|
||||
{
|
||||
friend class NtxNodeFactory;
|
||||
friend class NtxLinkNode;
|
||||
|
||||
public:
|
||||
|
||||
NtxNode() = default;
|
||||
~NtxNode() override = default;
|
||||
|
||||
// Copy-Ctor wird von NtxTCloneable::clone() benötigt
|
||||
NtxNode(const NtxNode&) = default;
|
||||
NtxNode& operator=(const NtxNode&) = delete;
|
||||
|
||||
NtxNode(NtxNode&&) noexcept = default;
|
||||
NtxNode& operator=(NtxNode&&) noexcept = default;
|
||||
|
||||
// clone() wird automatisch durch NtxTCloneable generiert
|
||||
|
||||
private:
|
||||
|
||||
explicit NtxNode(NtxClassTypeId id);
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_NODE_H
|
||||
112
nodes/nodes/ntxnodefactory.cpp
Normal file
112
nodes/nodes/ntxnodefactory.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include <memory>
|
||||
|
||||
#include "ntxnodefactory.h"
|
||||
#include "ntxnode.h"
|
||||
#include <ntxiclasstyperepo.h> // implementation of default repository
|
||||
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
NtxNodeFactory::NtxNodeFactory()
|
||||
: m_ctypeRepository(std::make_unique<NtxCTypeHashRepo>()) // Default: Hash-basiert
|
||||
{
|
||||
}
|
||||
|
||||
NtxNodeFactory& NtxNodeFactory::getInstance()
|
||||
{
|
||||
static NtxNodeFactory instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
const NtxString& NtxNodeFactory::lookupCTypeLabel(NtxClassTypeId id)
|
||||
{
|
||||
return getInstance().getCTypeRepository().lookupLabel(id);
|
||||
}
|
||||
|
||||
NtxClassTypeId NtxNodeFactory::generateCTypeId(const NtxString& cTypeLabel)
|
||||
{
|
||||
return getInstance().getCTypeRepository().generateId(cTypeLabel);
|
||||
}
|
||||
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeNode(const NtxString& label)
|
||||
{
|
||||
return getInstance().makeNodeByLabel(label);
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeNode(NtxClassTypeId id)
|
||||
{
|
||||
return getInstance().makeNodeById(id);
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeSharedNode(const NtxString& label, NtxNodePtr sharedSource)
|
||||
{
|
||||
return getInstance().makeSharedNodeByLabel(label, sharedSource);
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeSharedNode(NtxClassTypeId id, NtxNodePtr sharedSource)
|
||||
{
|
||||
return getInstance().makeSharedNodeById(id, sharedSource);
|
||||
}
|
||||
|
||||
/*
|
||||
Geile Recursion!
|
||||
NtxNodePtr NtxNodeFactory::cloneNode(NtxNodeCPtr originalNode)
|
||||
{
|
||||
return originalNode->clone();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeNodeByLabel(const NtxString& ctypelabel)
|
||||
{
|
||||
// ID generieren und zuweisen
|
||||
NtxClassTypeId id = m_ctypeRepository->generateId(ctypelabel);
|
||||
return makeNodeById(id);
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeNodeById(NtxClassTypeId id)
|
||||
{
|
||||
// Node erstellen über friend-Zugriff
|
||||
auto node = std::shared_ptr<NtxNode>(new NtxNode(id));
|
||||
|
||||
// Label aus Repository holen (wird in NtxIBasicNode::getClassTypeLabel() automatisch gemacht)
|
||||
// Kein expliziter setClassTypeLabel-Aufruf nötig
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeSharedNodeByLabel(const NtxString& label, NtxNodePtr sharedSource)
|
||||
{
|
||||
// ID generieren und zuweisen
|
||||
NtxClassTypeId id = m_ctypeRepository->generateId(label);
|
||||
return makeSharedNodeById(id, sharedSource);
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeFactory::makeSharedNodeById(NtxClassTypeId id, NtxNodePtr sharedSource)
|
||||
{
|
||||
return nullptr; // std::shared_ptr<NtxSharedNode>(new NtxSharedNode(id, sharedSource));
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
NtxIClassTypeRepo& NtxNodeFactory::getCTypeRepository()
|
||||
{
|
||||
return *m_ctypeRepository;
|
||||
}
|
||||
|
||||
const NtxIClassTypeRepo& NtxNodeFactory::getCTypeRepository() const
|
||||
{
|
||||
return *m_ctypeRepository;
|
||||
}
|
||||
|
||||
void NtxNodeFactory::setCTypeRepository(std::unique_ptr<NtxIClassTypeRepo> repo)
|
||||
{
|
||||
if (repo)
|
||||
m_ctypeRepository = std::move(repo);
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
59
nodes/nodes/ntxnodefactory.h
Normal file
59
nodes/nodes/ntxnodefactory.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef NTX_NODEFACTORY_H
|
||||
#define NTX_NODEFACTORY_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <ntxinode.h>
|
||||
#include <ntxiclasstyperepo.h> // Include for repo interface
|
||||
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
/**
|
||||
* @brief Factory für die Erstellung von Nodes. Das Management von den ClassTypeIds und ihren
|
||||
* ClassTypeLabels wird hier versteckt. @see NtxIClassTypeRepo
|
||||
*/
|
||||
class NtxNodeFactory
|
||||
{
|
||||
public:
|
||||
|
||||
// Singleton-Zugriff auf die Factory-Instanz.
|
||||
static NtxNodeFactory& getInstance();
|
||||
// Statische Hilfsmethoden für CType-Management und Node-Erstellung.
|
||||
static const NtxString& lookupCTypeLabel(NtxClassTypeId id);
|
||||
static NtxClassTypeId generateCTypeId(const NtxString& cTypeLabel);
|
||||
|
||||
static NtxNodePtr makeNode(const NtxString& label);
|
||||
static NtxNodePtr makeNode(NtxClassTypeId id);
|
||||
static NtxNodePtr makeSharedNode(const NtxString& label, NtxNodePtr sharedSource);
|
||||
static NtxNodePtr makeSharedNode(NtxClassTypeId id, NtxNodePtr sharedSource);
|
||||
//static NtxNodePtr makeLinkedNode(const NtxString& label, NtxNodePtr sharedSource);
|
||||
//static NtxNodePtr makeLinkedNode(NtxClassTypeId id, NtxNodePtr sharedSource);
|
||||
|
||||
//static NtxNodePtr cloneNode(NtxNodeCPtr originalNode);
|
||||
|
||||
NtxNodePtr makeNodeByLabel(const NtxString& label);
|
||||
NtxNodePtr makeNodeById(NtxClassTypeId id);
|
||||
NtxNodePtr makeSharedNodeByLabel(const NtxString& label, NtxNodePtr sharedSource);
|
||||
NtxNodePtr makeSharedNodeById(NtxClassTypeId id, NtxNodePtr sharedSource);
|
||||
|
||||
NtxIClassTypeRepo& getCTypeRepository();
|
||||
const NtxIClassTypeRepo& getCTypeRepository() const;
|
||||
void setCTypeRepository(std::unique_ptr<NtxIClassTypeRepo> repo);
|
||||
|
||||
private:
|
||||
|
||||
NtxNodeFactory();
|
||||
~NtxNodeFactory() = default;
|
||||
|
||||
// Nicht kopierbar
|
||||
NtxNodeFactory(const NtxNodeFactory&) = delete;
|
||||
NtxNodeFactory& operator=(const NtxNodeFactory&) = delete;
|
||||
|
||||
// Das zentrale Repository für alle Nodes
|
||||
std::unique_ptr<NtxIClassTypeRepo> m_ctypeRepository;
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_NODEFACTORY_H
|
||||
127
nodes/nodes/ntxnodeiterators.h
Normal file
127
nodes/nodes/ntxnodeiterators.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef NTXNODE_ITERATORS_H
|
||||
#define NTXNODE_ITERATORS_H
|
||||
|
||||
#include <iterator>
|
||||
#include <stack>
|
||||
#include <type_traits> // Wichtig für std::remove_cv_t
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Tiefensuche-Iterator für NtxINode Baumstrukturen
|
||||
*/
|
||||
template<typename T>
|
||||
struct NtxNodeDepthFirstIterator
|
||||
{
|
||||
// C++20 Concepts Support:
|
||||
// Wir definieren iterator_concept, um explizit Forward Iterator Verhalten zu signalisieren.
|
||||
using iterator_concept = std::forward_iterator_tag;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
// FIX 1: value_type darf NIE const sein, auch wenn T const ist!
|
||||
using value_type = std::remove_cv_t<T>;
|
||||
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
NtxNodeDepthFirstIterator()
|
||||
: m_root{ nullptr }, m_current{ nullptr }
|
||||
{
|
||||
}
|
||||
|
||||
explicit NtxNodeDepthFirstIterator(pointer node)
|
||||
: m_root{ node }, m_current{ node }
|
||||
{
|
||||
if (m_current) {
|
||||
m_stack.push({ m_current, 0 });
|
||||
}
|
||||
}
|
||||
|
||||
pointer get() const
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
int level() const
|
||||
{
|
||||
return static_cast<int>(m_stack.size()) - 1;
|
||||
}
|
||||
|
||||
// FIX 2: Dereferenzierung muss const sein
|
||||
pointer operator->() const
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
// FIX 2: Dereferenzierung muss const sein
|
||||
reference operator*() const
|
||||
{
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return m_current != nullptr;
|
||||
}
|
||||
|
||||
NtxNodeDepthFirstIterator& operator++()
|
||||
{
|
||||
if (!m_current || m_stack.empty()) {
|
||||
m_current = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
while (!m_stack.empty()) {
|
||||
auto& top = m_stack.top();
|
||||
auto node = top.first;
|
||||
auto& nextChildIndex = top.second;
|
||||
|
||||
// node->getChildCount() funktioniert, da T (bzw. ntx::NtxINode) hier vollständig bekannt ist
|
||||
const auto childCount = node->getChildCount();
|
||||
while (nextChildIndex < childCount) {
|
||||
auto child = node->getChild(nextChildIndex++);
|
||||
if (child) {
|
||||
m_current = child.get();
|
||||
m_stack.push({ m_current, 0 });
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
m_stack.pop();
|
||||
}
|
||||
|
||||
m_current = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
NtxNodeDepthFirstIterator operator++(int)
|
||||
{
|
||||
NtxNodeDepthFirstIterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Hidden Friends für Vergleiche (ADL)
|
||||
friend bool operator==(const NtxNodeDepthFirstIterator& a, const NtxNodeDepthFirstIterator& b)
|
||||
{
|
||||
return a.m_current == b.m_current;
|
||||
}
|
||||
|
||||
friend bool operator!=(const NtxNodeDepthFirstIterator& a, const NtxNodeDepthFirstIterator& b)
|
||||
{
|
||||
return a.m_current != b.m_current;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
pointer m_root;
|
||||
pointer m_current;
|
||||
std::stack<std::pair<pointer, size_t>> m_stack;
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTXNODE_ITERATORS_H
|
||||
57
nodes/nodes/ntxnodeproxy.h
Normal file
57
nodes/nodes/ntxnodeproxy.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef NTX_NODEPROXY_H
|
||||
#define NTX_NODEPROXY_H
|
||||
|
||||
#include <ntxinode.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Transparenter Proxy für NtxINodePtr.
|
||||
*
|
||||
* operator->() → delegiert ALLE Methodenaufrufe an den internen Pointer.
|
||||
* operator NtxINodePtr() → impliziter Cast wo NtxINodePtr erwartet wird.
|
||||
*
|
||||
* Keine einzige NtxINode-Methode muss reimplementiert werden.
|
||||
*/
|
||||
class NtxNodeProxy
|
||||
{
|
||||
public:
|
||||
|
||||
explicit NtxNodeProxy(NtxINodePtr node)
|
||||
: m_node(std::move(node))
|
||||
{}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Das Herzstück: leitet JEDEN Methodenaufruf transparent weiter
|
||||
// proxy->getProperty("x") → m_node->getProperty("x")
|
||||
// -----------------------------------------------------------------------
|
||||
NtxINode* operator->() { return m_node.get(); }
|
||||
const NtxINode* operator->() const { return m_node.get(); }
|
||||
|
||||
NtxINode& operator*() { return *m_node; }
|
||||
const NtxINode& operator*() const { return *m_node; }
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Implizite Konvertierung — überall wo NtxINodePtr erwartet wird
|
||||
// -----------------------------------------------------------------------
|
||||
operator NtxINodePtr() const { return m_node; }
|
||||
operator NtxNodeCPtr() const { return m_node; }
|
||||
operator bool() const { return m_node != nullptr; }
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Expliziter Zugriff
|
||||
// -----------------------------------------------------------------------
|
||||
NtxINodePtr get() const { return m_node; }
|
||||
|
||||
void reset(NtxINodePtr node = nullptr) { m_node = std::move(node); }
|
||||
|
||||
private:
|
||||
|
||||
NtxINodePtr m_node;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_NODEPROXY_H
|
||||
150
nodes/nodes/ntxsharedpayload.cpp
Normal file
150
nodes/nodes/ntxsharedpayload.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include <ntxsharedpayload.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
// =========================================================================
|
||||
// NtxSharedPayload: Key-basiert
|
||||
// =========================================================================
|
||||
|
||||
NtxSharedPayload::NtxSharedPayload(const NtxPayloadPtr& original)
|
||||
: m_originalPayload(original)
|
||||
{
|
||||
}
|
||||
|
||||
bool NtxSharedPayload::hasValue(const NtxString& key) const
|
||||
{
|
||||
return m_originalPayload && m_originalPayload->hasValue(key);
|
||||
}
|
||||
|
||||
void NtxSharedPayload::setValue(const NtxString& key, const NtxVariant& value)
|
||||
{
|
||||
if (m_originalPayload)
|
||||
m_originalPayload->setValue(key, value);
|
||||
}
|
||||
|
||||
NtxVariant NtxSharedPayload::getValue(const NtxString& key) const
|
||||
{
|
||||
if (m_originalPayload)
|
||||
return m_originalPayload->getValue(key);
|
||||
return NtxVariant{};
|
||||
}
|
||||
|
||||
void NtxSharedPayload::removeValue(const NtxString& key)
|
||||
{
|
||||
if (m_originalPayload)
|
||||
m_originalPayload->removeValue(key);
|
||||
}
|
||||
|
||||
void NtxSharedPayload::clearValues()
|
||||
{
|
||||
if (m_originalPayload)
|
||||
m_originalPayload->clearValues();
|
||||
}
|
||||
|
||||
size_t NtxSharedPayload::getValueCount() const
|
||||
{
|
||||
return m_originalPayload ? m_originalPayload->getValueCount() : 0;
|
||||
}
|
||||
|
||||
void NtxSharedPayload::forEachProperty(NtxPayloadVisitor visitor) const
|
||||
{
|
||||
if (m_originalPayload)
|
||||
m_originalPayload->forEachProperty(visitor);
|
||||
}
|
||||
|
||||
/*
|
||||
NtxStringList NtxSharedPayload::getValueKeys() const
|
||||
{
|
||||
if (m_originalPayload)
|
||||
return m_originalPayload->getValueKeys();
|
||||
return {};
|
||||
}
|
||||
*/
|
||||
|
||||
// =========================================================================
|
||||
// NtxSharedPayload: Index-basiert
|
||||
// =========================================================================
|
||||
|
||||
bool NtxSharedPayload::hasValue(size_t index) const
|
||||
{
|
||||
return m_originalPayload && m_originalPayload->hasValue(index);
|
||||
}
|
||||
|
||||
void NtxSharedPayload::setValue(size_t index, const NtxVariant& value)
|
||||
{
|
||||
if (m_originalPayload)
|
||||
m_originalPayload->setValue(index, value);
|
||||
}
|
||||
|
||||
NtxVariant NtxSharedPayload::getValue(size_t index) const
|
||||
{
|
||||
if (m_originalPayload)
|
||||
return m_originalPayload->getValue(index);
|
||||
return NtxVariant{};
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// NtxSharedPayload: Iteratoren
|
||||
// =========================================================================
|
||||
|
||||
/*
|
||||
NtxPayloadIterator NtxSharedPayload::valuesBegin()
|
||||
{
|
||||
if (m_originalPayload)
|
||||
return m_originalPayload->valuesBegin();
|
||||
// Leerer Iterator: Kein gültiger Fallback möglich → UB vermeiden
|
||||
static std::vector<NtxVariant> empty;
|
||||
return empty.begin();
|
||||
}
|
||||
|
||||
NtxPayloadIterator NtxSharedPayload::valuesEnd()
|
||||
{
|
||||
if (m_originalPayload)
|
||||
return m_originalPayload->valuesEnd();
|
||||
static std::vector<NtxVariant> empty;
|
||||
return empty.end();
|
||||
}
|
||||
|
||||
NtxPayloadCIterator NtxSharedPayload::valuesBegin() const
|
||||
{
|
||||
if (m_originalPayload)
|
||||
return m_originalPayload->valuesBegin();
|
||||
static const std::vector<NtxVariant> empty;
|
||||
return empty.cbegin();
|
||||
}
|
||||
|
||||
NtxPayloadCIterator NtxSharedPayload::valuesEnd() const
|
||||
{
|
||||
if (m_originalPayload)
|
||||
return m_originalPayload->valuesEnd();
|
||||
static const std::vector<NtxVariant> empty;
|
||||
return empty.cend();
|
||||
}
|
||||
*/
|
||||
|
||||
// =========================================================================
|
||||
// NtxSharedPayload: Sonstiges
|
||||
// =========================================================================
|
||||
|
||||
NtxPayloadPtr NtxSharedPayload::getOriginalPayload() const
|
||||
{
|
||||
return m_originalPayload;
|
||||
}
|
||||
|
||||
void NtxSharedPayload::setOriginalPayload(const NtxPayloadPtr& original)
|
||||
{
|
||||
m_originalPayload = original;
|
||||
}
|
||||
|
||||
bool NtxSharedPayload::isValid() const
|
||||
{
|
||||
return m_originalPayload != nullptr;
|
||||
}
|
||||
|
||||
void NtxSharedPayload::detach()
|
||||
{
|
||||
m_originalPayload.reset();
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
89
nodes/nodes/ntxtaggregatenode.h
Normal file
89
nodes/nodes/ntxtaggregatenode.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef NTX_AGGREGATENODE_H
|
||||
#define NTX_AGGREGATENODE_H
|
||||
|
||||
#include <memory>
|
||||
#include <ntxibasicnode.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Implementierung via Aggregation (KISS-Variante).
|
||||
*
|
||||
* Besitzt oder referenziert einen NtxIPayload über shared_ptr.
|
||||
* Owning: NtxTAggregateNode(std::make_shared<MyPayload>(...))
|
||||
* Referencing: NtxTAggregateNode(existingPayloadPtr)
|
||||
*/
|
||||
template<typename TPayloadImpl>
|
||||
class NtxTAggregateNode : public NtxIBasicNode
|
||||
{
|
||||
public:
|
||||
|
||||
// Owning: erstellt eigene TPayloadImpl-Instanz
|
||||
/*
|
||||
template<typename... Args>
|
||||
explicit NtxTAggregateNode(Args&&... args)
|
||||
: NtxIBasicNode{}
|
||||
, m_payload(std::make_shared<TPayloadImpl>(std::forward<Args>(args)...))
|
||||
{}
|
||||
*/
|
||||
|
||||
NtxTAggregateNode()
|
||||
: NtxIBasicNode{}, m_payload(std::make_shared<TPayloadImpl>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Referencing: verknüpft bestehenden Payload
|
||||
explicit NtxTAggregateNode(std::shared_ptr<TPayloadImpl> sharedPayload)
|
||||
: NtxIBasicNode{}
|
||||
, m_payload(std::move(sharedPayload))
|
||||
{}
|
||||
|
||||
// Payload zur Laufzeit austauschen (Owning ↔ Referencing)
|
||||
void setPayload(NtxPayloadPtr payload) { m_payload = std::move(payload); }
|
||||
NtxPayloadPtr getPayload() const { return m_payload; }
|
||||
|
||||
// ========================================
|
||||
// NtxIPayload Interface: Delegation
|
||||
// ========================================
|
||||
|
||||
size_t getPropertyCount() const override { return m_payload->getPropertyCount(); }
|
||||
void clearProperties() override { m_payload->clearProperties(); }
|
||||
|
||||
bool hasProperty(const NtxString& key) const override { return m_payload->hasProperty(key); }
|
||||
void setProperty(const NtxString& key, const NtxVariant& value) override
|
||||
{ m_payload->setProperty(key, value); }
|
||||
NtxVariant getProperty(const NtxString& key) const override
|
||||
{ return m_payload->getProperty(key); }
|
||||
void removeProperty(const NtxString& key) override { m_payload->removeProperty(key); }
|
||||
|
||||
bool hasProperty(size_t index) const override { return m_payload->hasProperty(index); }
|
||||
void setProperty(size_t index, const NtxVariant& value) override
|
||||
{ m_payload->setProperty(index, value); }
|
||||
NtxVariant getProperty(size_t index) const override { return m_payload->getProperty(index); }
|
||||
|
||||
void forEachProperty(NtxPayloadVisitor visitor) const override
|
||||
{
|
||||
//m_payload->forEachProperty(visitor);
|
||||
}
|
||||
|
||||
NtxNodePtr clone() const override
|
||||
{
|
||||
// m_payload ist bereits shared_ptr<TPayloadImpl> — kein cast nötig
|
||||
auto newNode = std::make_shared<NtxTAggregateNode<TPayloadImpl>>(
|
||||
std::make_shared<TPayloadImpl>(*m_payload));
|
||||
newNode->setClassTypeId(this->getClassTypeId());
|
||||
return newNode;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// NtxPayloadPtr m_payload; // Nein! das ist eine völlig unnötige Einschränkung auf IPayload.
|
||||
std::shared_ptr<TPayloadImpl> m_payload;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_AGGREGATENODE_H
|
||||
34
nodes/nodes/ntxtcloneable.h
Normal file
34
nodes/nodes/ntxtcloneable.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef NTX_CLONEABLE_H
|
||||
#define NTX_CLONEABLE_H
|
||||
|
||||
#include <memory>
|
||||
#include <ntxinode.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief CRTP-Mixin: generiert clone() automatisch für jede Subklasse.
|
||||
*
|
||||
* Voraussetzung: Derived ist copy-konstruierbar.
|
||||
*
|
||||
* Verwendung:
|
||||
* class MyNode : public NtxTCloneable<MyNode, NtxTMixInNode<MyPayload>> { ... };
|
||||
*/
|
||||
template<typename Derived, typename Base>
|
||||
class NtxTCloneable : public Base
|
||||
{
|
||||
public:
|
||||
|
||||
using Base::Base; // Konstruktoren durchreichen
|
||||
|
||||
NtxNodePtr clone() const override
|
||||
{
|
||||
return std::make_shared<Derived>(static_cast<const Derived&>(*this));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_CLONEABLE_H
|
||||
73
nodes/nodes/ntxtmixinnode.h
Normal file
73
nodes/nodes/ntxtmixinnode.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef NTX_TMIXINNODE_H
|
||||
#define NTX_TMIXINNODE_H
|
||||
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <ntxibasicnode.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Implementierung via Vererbung (Mixin).
|
||||
*
|
||||
* TPayloadImpl wird als Basisklasse eingemischt.
|
||||
*/
|
||||
template<typename TPayloadImpl>
|
||||
class NtxTMixInNode : public NtxIBasicNode, public TPayloadImpl
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Konstruktor forwarding an PayloadImpl
|
||||
template<typename... Args>
|
||||
explicit NtxTMixInNode(Args&&... args)
|
||||
: NtxIBasicNode{},
|
||||
TPayloadImpl{std::forward<Args>(args)...}
|
||||
{
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// NtxINode Interface: Payload Forwarding
|
||||
// ========================================
|
||||
|
||||
size_t getPropertyCount() const override { return TPayloadImpl::getPropertyCount(); }
|
||||
void clearProperties() override { TPayloadImpl::clearProperties(); }
|
||||
|
||||
bool hasProperty(const NtxString& key) const override { return TPayloadImpl::hasProperty(key); }
|
||||
void setProperty(const NtxString& key, const NtxVariant& value) override { TPayloadImpl::setProperty(key, value); }
|
||||
NtxVariant getProperty(const NtxString& key) const override { return TPayloadImpl::getProperty(key); }
|
||||
void removeProperty(const NtxString& key) override { TPayloadImpl::removeProperty(key); }
|
||||
|
||||
bool hasProperty(size_t index) const override { return TPayloadImpl::hasProperty(index); }
|
||||
void setProperty(size_t index, const NtxVariant& value) override { TPayloadImpl::setProperty(index, value); }
|
||||
NtxVariant getProperty(size_t index) const override { return TPayloadImpl::getProperty(index); }
|
||||
|
||||
|
||||
// Deducing This Support (Raw Access)
|
||||
//std::vector<NtxVariant>& doGetValues() override { return TPayloadImpl::doGetValues(); }
|
||||
//const std::vector<NtxVariant>& doGetValues() const override { return TPayloadImpl::doGetValues(); }
|
||||
|
||||
|
||||
void forEachProperty(NtxPayloadVisitor visitor) const override
|
||||
{
|
||||
//TPayloadImpl::forEachProperty(visitor);
|
||||
}
|
||||
|
||||
|
||||
NtxNodePtr clone() const override
|
||||
{
|
||||
// Basic Clone Implementation: Kopiert PayloadImpl Teil via Copy-Ctor
|
||||
auto newNode = std::make_shared<NtxTMixInNode<TPayloadImpl>>(*static_cast<const TPayloadImpl*>(this));
|
||||
// Base Properties kopieren
|
||||
newNode->setClassTypeId(this->getClassTypeId());
|
||||
return newNode;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_TMIXINNODE_H
|
||||
83
nodes/services/ntxclipboard.cpp
Normal file
83
nodes/services/ntxclipboard.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "ntxclipboard.h"
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
void NtxClipboard::copyNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
m_nodeEntryList.clear();
|
||||
|
||||
for (const auto& node : nodes)
|
||||
{
|
||||
if (!node) continue;
|
||||
|
||||
NtxNodeEntry entry;
|
||||
entry.clone = createOrphanClone(node);
|
||||
entry.originalParent = node->getParent();
|
||||
entry.originalPosition = node->ownPos().value_or(0);
|
||||
|
||||
m_nodeEntryList.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void NtxClipboard::cutNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
// Identisch zu copyNodes - Der Unterschied liegt in NtxHeadNode
|
||||
copyNodes(nodes);
|
||||
}
|
||||
|
||||
NtxNodeList NtxClipboard::pasteNodes() const
|
||||
{
|
||||
NtxNodeList result;
|
||||
|
||||
for (const auto& entry : m_nodeEntryList)
|
||||
{
|
||||
if (!entry.clone) continue;
|
||||
|
||||
// Neuen Klon vom Clipboard-Clone erstellen (mehrfaches Paste möglich)
|
||||
auto freshClone = entry.clone->clone();
|
||||
if (freshClone)
|
||||
{
|
||||
result.push_back(freshClone);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool NtxClipboard::isEmpty() const
|
||||
{
|
||||
return m_nodeEntryList.empty();
|
||||
}
|
||||
|
||||
size_t NtxClipboard::getCount() const
|
||||
{
|
||||
return m_nodeEntryList.size();
|
||||
}
|
||||
|
||||
void NtxClipboard::clear()
|
||||
{
|
||||
m_nodeEntryList.clear();
|
||||
}
|
||||
|
||||
const NtxNodeEntryList& NtxClipboard::getEntries() const
|
||||
{
|
||||
return m_nodeEntryList;
|
||||
}
|
||||
|
||||
NtxNodePtr NtxClipboard::createOrphanClone(NtxNodePtr node) const
|
||||
{
|
||||
if (!node) return nullptr;
|
||||
|
||||
// Deep-Clone erstellen
|
||||
auto clone = node->clone();
|
||||
|
||||
// Parent-Verbindung trennen (Elternlos machen)
|
||||
if (clone)
|
||||
{
|
||||
clone->setParent(nullptr);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
47
nodes/services/ntxclipboard.h
Normal file
47
nodes/services/ntxclipboard.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef NTX_CLIPBOARD_H
|
||||
#define NTX_CLIPBOARD_H
|
||||
|
||||
#include <ntxicommand.h>
|
||||
#include <vector>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
/**
|
||||
* @brief Einfaches Clipboard für Copy/Cut/Paste-Operationen.
|
||||
*
|
||||
* Speichert elternlose Deep-Clones mit Original-Position für Undo.
|
||||
* Kein Singleton - wird als Member von NtxHeadNode verwendet.
|
||||
*/
|
||||
class NtxClipboard
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NtxClipboard() = default;
|
||||
~NtxClipboard() = default;
|
||||
|
||||
// Copy/Cut Operations
|
||||
void copyNodes(const NtxNodeList& nodes);
|
||||
void cutNodes(const NtxNodeList& nodes);
|
||||
|
||||
// Paste Operations
|
||||
NtxNodeList pasteNodes() const;
|
||||
|
||||
// State
|
||||
bool isEmpty() const;
|
||||
size_t getCount() const;
|
||||
void clear();
|
||||
|
||||
// Access
|
||||
const NtxNodeEntryList& getEntries() const;
|
||||
|
||||
private:
|
||||
|
||||
NtxNodeEntryList m_nodeEntryList;
|
||||
|
||||
NtxNodePtr createOrphanClone(NtxNodePtr node) const;
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_CLIPBOARD_H
|
||||
141
nodes/services/ntxcmdlist.cpp
Normal file
141
nodes/services/ntxcmdlist.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include <NtxCmdList.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
NtxCmdList::NtxCmdList()
|
||||
: m_executedCount(0)
|
||||
{
|
||||
setDescription("Multi Command");
|
||||
}
|
||||
|
||||
NtxCmdList::NtxCmdList(const NtxString& description)
|
||||
: m_executedCount(0)
|
||||
{
|
||||
setDescription(description);
|
||||
}
|
||||
|
||||
bool NtxCmdList::execute()
|
||||
{
|
||||
m_executedCount = 0;
|
||||
|
||||
for (size_t i = 0; i < m_commands.size(); ++i)
|
||||
{
|
||||
if (!m_commands[i]->canExecute())
|
||||
{
|
||||
rollback(i);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_commands[i]->execute())
|
||||
{
|
||||
rollback(i);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_executedCount++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxCmdList::undo()
|
||||
{
|
||||
if (m_executedCount == 0)
|
||||
return false;
|
||||
|
||||
for (size_t i = m_executedCount; i > 0; --i)
|
||||
{
|
||||
size_t index = i - 1;
|
||||
|
||||
if (!m_commands[index]->canUndo())
|
||||
continue;
|
||||
|
||||
m_commands[index]->undo();
|
||||
}
|
||||
|
||||
m_executedCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxCmdList::canExecute() const
|
||||
{
|
||||
if (m_commands.empty())
|
||||
return false;
|
||||
|
||||
for (const auto& cmd : m_commands)
|
||||
{
|
||||
if (!cmd->canExecute())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxCmdList::canUndo() const
|
||||
{
|
||||
if (m_executedCount == 0)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < m_executedCount; ++i)
|
||||
{
|
||||
if (m_commands[i]->canUndo())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NtxString NtxCmdList::getDescription() const
|
||||
{
|
||||
NtxString desc = NtxICommand::getDescription();
|
||||
|
||||
if (!desc.empty())
|
||||
return desc;
|
||||
|
||||
if (m_commands.empty())
|
||||
return "Empty Multi Command";
|
||||
|
||||
return "Multi Command (" + std::to_string(m_commands.size()) + " commands)";
|
||||
}
|
||||
|
||||
void NtxCmdList::addCommand(NtxCommandUPtr command)
|
||||
{
|
||||
if (command)
|
||||
{
|
||||
m_commands.push_back(std::move(command));
|
||||
}
|
||||
}
|
||||
|
||||
void NtxCmdList::clear()
|
||||
{
|
||||
m_commands.clear();
|
||||
m_executedCount = 0;
|
||||
}
|
||||
|
||||
size_t NtxCmdList::count() const
|
||||
{
|
||||
return m_commands.size();
|
||||
}
|
||||
|
||||
bool NtxCmdList::isEmpty() const
|
||||
{
|
||||
return m_commands.empty();
|
||||
}
|
||||
|
||||
void NtxCmdList::rollback(size_t upToIndex)
|
||||
{
|
||||
for (size_t i = upToIndex; i > 0; --i)
|
||||
{
|
||||
size_t index = i - 1;
|
||||
|
||||
if (m_commands[index]->canUndo())
|
||||
{
|
||||
m_commands[index]->undo();
|
||||
}
|
||||
}
|
||||
|
||||
m_executedCount = 0;
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
42
nodes/services/ntxcmdlist.h
Normal file
42
nodes/services/ntxcmdlist.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef NTX_CMDLIST_H
|
||||
#define NTX_CMDLIST_H
|
||||
|
||||
#include <ntxicommand.h>
|
||||
#include <vector>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
class NtxCmdList : public NtxICommand
|
||||
{
|
||||
public:
|
||||
|
||||
NtxCmdList();
|
||||
explicit NtxCmdList(const NtxString& description);
|
||||
~NtxCmdList() override = default;
|
||||
|
||||
bool execute() override;
|
||||
bool undo() override;
|
||||
|
||||
bool canExecute() const override;
|
||||
bool canUndo() const override;
|
||||
|
||||
NtxString getDescription() const override;
|
||||
|
||||
void addCommand(NtxCommandUPtr command);
|
||||
void clear();
|
||||
|
||||
size_t count() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<NtxCommandUPtr> m_commands;
|
||||
size_t m_executedCount;
|
||||
|
||||
void rollback(size_t upToIndex);
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_CMDLIST_H
|
||||
55
nodes/services/ntxheadnode.cpp
Normal file
55
nodes/services/ntxheadnode.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <ntxheadnode.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
bool NtxHeadNode::copyNode(NtxNodePtr node)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NtxHeadNode::cutNode(NtxNodePtr node)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
NtxNodePtr NtxHeadNode::pasteNode(NtxNodePtr parent, int index)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool NtxHeadNode::addNode(NtxNodePtr parent, NtxNodePtr node, int index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NtxHeadNode::deleteNode(NtxNodePtr node)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NtxHeadNode::hasClipboard() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void NtxHeadNode::clearClipboard()
|
||||
{
|
||||
}
|
||||
|
||||
NtxNodePtr NtxHeadNode::peekClipboard() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool NtxHeadNode::validateNode(NtxNodePtr node) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NtxHeadNode::canAddToParent(NtxNodePtr parent, NtxNodePtr child) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
46
nodes/services/ntxheadnode.h
Normal file
46
nodes/services/ntxheadnode.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef NTX_HEADNODE_H
|
||||
#define NTX_HEADNODE_H
|
||||
|
||||
#include <ntxinode.h>
|
||||
#include <ntxclipboard.h>
|
||||
#include <memory>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
class NtxINode;
|
||||
using NtxNodePtr = std::shared_ptr<NtxINode>;
|
||||
|
||||
class NtxHeadNode
|
||||
{
|
||||
public:
|
||||
|
||||
NtxHeadNode() = default;
|
||||
~NtxHeadNode() = default;
|
||||
|
||||
NtxHeadNode(const NtxHeadNode&) = delete;
|
||||
NtxHeadNode& operator=(const NtxHeadNode&) = delete;
|
||||
NtxHeadNode(NtxHeadNode&&) = default;
|
||||
NtxHeadNode& operator=(NtxHeadNode&&) = default;
|
||||
|
||||
bool copyNode(NtxNodePtr node);
|
||||
bool cutNode(NtxNodePtr node);
|
||||
NtxNodePtr pasteNode(NtxNodePtr parent, int index = -1);
|
||||
bool addNode(NtxNodePtr parent, NtxNodePtr node, int index = -1);
|
||||
bool deleteNode(NtxNodePtr node);
|
||||
|
||||
bool hasClipboard() const;
|
||||
void clearClipboard();
|
||||
NtxNodePtr peekClipboard() const;
|
||||
|
||||
private:
|
||||
|
||||
NtxClipboard m_clipboard; // ← Eigene Klasse als Member!
|
||||
bool m_isCutOperation{false};
|
||||
|
||||
bool validateNode(NtxNodePtr node) const;
|
||||
bool canAddToParent(NtxNodePtr parent, NtxNodePtr child) const;
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_HEADNODE_H
|
||||
21
nodes/services/ntxicommand.cpp
Normal file
21
nodes/services/ntxicommand.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <ntxicommand.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
bool NtxICommand::canUndo() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
NtxString NtxICommand::getDescription() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
void NtxICommand::setDescription(const NtxString& description)
|
||||
{
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
52
nodes/services/ntxicommand.h
Normal file
52
nodes/services/ntxicommand.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef NTX_ICOMMAND_H
|
||||
#define NTX_ICOMMAND_H
|
||||
|
||||
#include <ntxinode.h>
|
||||
#include <memory>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
// Einfache Struct für Clipboard-Eintrag
|
||||
struct NtxNodeEntry
|
||||
{
|
||||
NtxNodePtr clone; // Elternloser Deep-Clone
|
||||
NtxNodeWeakPtr originalParent; // Schwache Referenz für Undo
|
||||
size_t originalPosition; // Position im Original-Parent
|
||||
};
|
||||
|
||||
using NtxNodeEntryList = std::vector<NtxNodeEntry>;
|
||||
|
||||
class NtxICommand
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~NtxICommand() = default;
|
||||
|
||||
virtual bool execute() = 0;
|
||||
virtual bool undo() = 0;
|
||||
|
||||
virtual bool canExecute() const = 0;
|
||||
virtual bool canUndo() const;
|
||||
|
||||
virtual NtxString getDescription() const;
|
||||
|
||||
protected:
|
||||
|
||||
NtxICommand() = default;
|
||||
NtxICommand(const NtxICommand&) = default;
|
||||
NtxICommand& operator=(const NtxICommand&) = default;
|
||||
|
||||
void setDescription(const NtxString& description);
|
||||
|
||||
private:
|
||||
|
||||
NtxString m_description;
|
||||
};
|
||||
|
||||
using NtxCommandPtr = std::shared_ptr<NtxICommand>;
|
||||
using NtxCommandUPtr = std::unique_ptr<NtxICommand>;
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_ICOMMAND_H
|
||||
161
nodes/services/ntxnodecommands.cpp
Normal file
161
nodes/services/ntxnodecommands.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#include "ntxnodecommands.h"
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
// =========================================================================
|
||||
// NtxInsertNodeCmd
|
||||
// =========================================================================
|
||||
|
||||
NtxInsertNodeCmd::NtxInsertNodeCmd(NtxNodePtr parent, NtxNodePtr node, size_t index)
|
||||
: m_parent(std::move(parent))
|
||||
, m_node(std::move(node))
|
||||
, m_index(index)
|
||||
{
|
||||
setDescription("Insert node");
|
||||
}
|
||||
|
||||
bool NtxInsertNodeCmd::execute()
|
||||
{
|
||||
if (!canExecute())
|
||||
return false;
|
||||
|
||||
if (m_index > m_parent->getChildCount())
|
||||
m_index = m_parent->getChildCount();
|
||||
|
||||
m_parent->insertChild(m_index, m_node);
|
||||
m_executed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxInsertNodeCmd::undo()
|
||||
{
|
||||
if (!m_executed)
|
||||
return false;
|
||||
|
||||
auto idx = m_parent->getChildIndex(m_node);
|
||||
if (idx == static_cast<size_t>(-1))
|
||||
return false;
|
||||
|
||||
m_parent->removeChild(idx);
|
||||
m_executed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxInsertNodeCmd::canExecute() const
|
||||
{
|
||||
return m_parent && m_node && !m_executed;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// NtxRemoveNodeCmd
|
||||
// =========================================================================
|
||||
|
||||
NtxRemoveNodeCmd::NtxRemoveNodeCmd(NtxNodePtr node)
|
||||
: m_node(std::move(node))
|
||||
{
|
||||
setDescription("Remove node");
|
||||
}
|
||||
|
||||
bool NtxRemoveNodeCmd::execute()
|
||||
{
|
||||
if (!canExecute())
|
||||
return false;
|
||||
|
||||
m_parent = m_node->getParent();
|
||||
if (!m_parent)
|
||||
return false;
|
||||
|
||||
auto pos = m_node->ownPos();
|
||||
if (!pos)
|
||||
return false;
|
||||
|
||||
m_index = *pos;
|
||||
m_parent->removeChild(m_index);
|
||||
m_executed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxRemoveNodeCmd::undo()
|
||||
{
|
||||
if (!m_executed || !m_parent)
|
||||
return false;
|
||||
|
||||
m_parent->insertChild(m_index, m_node);
|
||||
m_executed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxRemoveNodeCmd::canExecute() const
|
||||
{
|
||||
return m_node && m_node->getParent() && !m_executed;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// NtxMacroCommand
|
||||
// =========================================================================
|
||||
|
||||
NtxMacroCommand::NtxMacroCommand(const NtxString& description)
|
||||
{
|
||||
setDescription(description);
|
||||
}
|
||||
|
||||
NtxCommandUPtr NtxMacroCommand::create(
|
||||
const NtxString& description,
|
||||
std::vector<NtxCommandUPtr> commands)
|
||||
{
|
||||
auto macro = std::make_unique<NtxMacroCommand>(description);
|
||||
for (auto& cmd : commands)
|
||||
macro->add(std::move(cmd));
|
||||
return macro;
|
||||
}
|
||||
|
||||
void NtxMacroCommand::add(NtxCommandUPtr cmd)
|
||||
{
|
||||
if (cmd)
|
||||
m_commands.push_back(std::move(cmd));
|
||||
}
|
||||
|
||||
bool NtxMacroCommand::execute()
|
||||
{
|
||||
m_executedCount = 0;
|
||||
|
||||
for (auto& cmd : m_commands)
|
||||
{
|
||||
if (!cmd->execute())
|
||||
{
|
||||
// Rollback: Bereits ausgeführte rückgängig machen
|
||||
for (size_t i = m_executedCount; i > 0; --i)
|
||||
m_commands[i - 1]->undo();
|
||||
m_executedCount = 0;
|
||||
return false;
|
||||
}
|
||||
++m_executedCount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxMacroCommand::undo()
|
||||
{
|
||||
for (size_t i = m_executedCount; i > 0; --i)
|
||||
{
|
||||
if (!m_commands[i - 1]->undo())
|
||||
return false;
|
||||
}
|
||||
m_executedCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxMacroCommand::canExecute() const
|
||||
{
|
||||
if (m_commands.empty())
|
||||
return false;
|
||||
for (const auto& cmd : m_commands)
|
||||
{
|
||||
if (!cmd->canExecute())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
102
nodes/services/ntxnodecommands.h
Normal file
102
nodes/services/ntxnodecommands.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#ifndef NTX_NODECOMMANDS_H
|
||||
#define NTX_NODECOMMANDS_H
|
||||
|
||||
#include <ntxicommand.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
// =========================================================================
|
||||
// Atomar: Knoten einfügen
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* @brief Fügt einen Knoten an einer Position ein.
|
||||
* Undo entfernt ihn wieder.
|
||||
*/
|
||||
class NtxInsertNodeCmd : public NtxICommand
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NtxInsertNodeCmd(NtxNodePtr parent, NtxNodePtr node, size_t index);
|
||||
|
||||
bool execute() override;
|
||||
bool undo() override;
|
||||
bool canExecute() const override;
|
||||
|
||||
private:
|
||||
|
||||
NtxNodePtr m_parent;
|
||||
NtxNodePtr m_node;
|
||||
size_t m_index;
|
||||
bool m_executed{false};
|
||||
};
|
||||
|
||||
// =========================================================================
|
||||
// Atomar: Knoten entfernen
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* @brief Entfernt einen Knoten. Merkt sich Parent + Position für Undo.
|
||||
*/
|
||||
class NtxRemoveNodeCmd : public NtxICommand
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
explicit NtxRemoveNodeCmd(NtxNodePtr node);
|
||||
|
||||
bool execute() override;
|
||||
bool undo() override;
|
||||
bool canExecute() const override;
|
||||
|
||||
private:
|
||||
|
||||
NtxNodePtr m_node;
|
||||
NtxNodePtr m_parent;
|
||||
size_t m_index{0};
|
||||
bool m_executed{false};
|
||||
};
|
||||
|
||||
// =========================================================================
|
||||
// Makro-Command (Composite Command)
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* @brief Führt mehrere Commands als atomare Einheit aus.
|
||||
*
|
||||
* execute(): Alle Commands vorwärts ausführen.
|
||||
* undo(): Alle Commands rückwärts rückgängig machen.
|
||||
* Bei Fehler: Rollback der bereits ausgeführten.
|
||||
*/
|
||||
class NtxMacroCommand : public NtxICommand
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NtxMacroCommand() = default;
|
||||
explicit NtxMacroCommand(const NtxString& description);
|
||||
|
||||
/// Factory: Erzeugt ein Makro aus einer Liste von Commands.
|
||||
static NtxCommandUPtr create(
|
||||
const NtxString& description,
|
||||
std::vector<NtxCommandUPtr> commands);
|
||||
|
||||
void add(NtxCommandUPtr cmd);
|
||||
|
||||
bool execute() override;
|
||||
bool undo() override;
|
||||
bool canExecute() const override;
|
||||
|
||||
size_t commandCount() const { return m_commands.size(); }
|
||||
|
||||
private:
|
||||
|
||||
std::vector<NtxCommandUPtr> m_commands;
|
||||
size_t m_executedCount{0};
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_NODECOMMANDS_H
|
||||
209
nodes/services/ntxnodetree.cpp
Normal file
209
nodes/services/ntxnodetree.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include <ntxnodetree.h>
|
||||
#include <ntxnodefactory.h>
|
||||
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
NtxNodeTree::NtxNodeTree(NtxClassTypeId id)
|
||||
{
|
||||
//m_ctypeId = id;
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeTree::clone() const
|
||||
{
|
||||
/*
|
||||
auto cloned = NtxNodeFactory::makeNode(getClassTypeLabel());
|
||||
qDebug() << "Cloning NtxNodeTree with CTypeLabel: NOT DONE: " << getClassTypeLabel().c_str();
|
||||
|
||||
forEachProperty([&](const NtxString& key, const NtxVariant& value) {
|
||||
cloned->setProperty(key, value);
|
||||
});
|
||||
for (size_t i = 0; i < getChildCount(); ++i)
|
||||
cloned->addChild(getChild(i)->clone());
|
||||
|
||||
|
||||
|
||||
|
||||
return cloned;
|
||||
|
||||
*/
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Command-Ausführung (delegiert an NtxUndoStack)
|
||||
// =========================================================================
|
||||
|
||||
bool NtxNodeTree::execute(NtxCommandUPtr cmd)
|
||||
{
|
||||
if (!cmd || !cmd->canExecute())
|
||||
return false;
|
||||
m_undoStack.push(std::move(cmd));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::undo()
|
||||
{
|
||||
if (!canUndo())
|
||||
return false;
|
||||
m_undoStack.undo();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::redo()
|
||||
{
|
||||
if (!canRedo())
|
||||
return false;
|
||||
m_undoStack.redo();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::canUndo() const { return m_undoStack.canUndo(); }
|
||||
bool NtxNodeTree::canRedo() const { return m_undoStack.canRedo(); }
|
||||
NtxString NtxNodeTree::undoText() const { return m_undoStack.undoText(); }
|
||||
NtxString NtxNodeTree::redoText() const { return m_undoStack.redoText(); }
|
||||
|
||||
void NtxNodeTree::setClean() { m_undoStack.setClean(); }
|
||||
bool NtxNodeTree::isDirty() const { return !m_undoStack.isClean(); }
|
||||
|
||||
// =========================================================================
|
||||
// Einzel-Operationen
|
||||
// =========================================================================
|
||||
|
||||
bool NtxNodeTree::addNode(NtxNodePtr parent, NtxNodePtr node, size_t index)
|
||||
{
|
||||
return execute(std::make_unique<NtxInsertNodeCmd>(
|
||||
std::move(parent), std::move(node), index));
|
||||
}
|
||||
|
||||
bool NtxNodeTree::deleteNode(NtxNodePtr node)
|
||||
{
|
||||
return execute(std::make_unique<NtxRemoveNodeCmd>(std::move(node)));
|
||||
}
|
||||
|
||||
bool NtxNodeTree::moveNode(NtxNodePtr node, NtxNodePtr newParent, size_t newIndex)
|
||||
{
|
||||
// Move = Remove + Insert als Makro
|
||||
auto macro = std::make_unique<NtxMacroCommand>("Move node");
|
||||
macro->add(std::make_unique<NtxRemoveNodeCmd>(node));
|
||||
macro->add(std::make_unique<NtxInsertNodeCmd>(
|
||||
std::move(newParent), std::move(node), newIndex));
|
||||
return execute(std::move(macro));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Listen-Operationen (Makro-Commands)
|
||||
// =========================================================================
|
||||
|
||||
bool NtxNodeTree::addNodes(NtxNodePtr parent, const NtxNodeList& nodes, size_t index)
|
||||
{
|
||||
std::vector<NtxCommandUPtr> cmds;
|
||||
cmds.reserve(nodes.size());
|
||||
|
||||
for (size_t i = 0; i < nodes.size(); ++i)
|
||||
{
|
||||
cmds.push_back(std::make_unique<NtxInsertNodeCmd>(
|
||||
parent, nodes[i], index + i));
|
||||
}
|
||||
|
||||
return execute(NtxMacroCommand::create(
|
||||
"Insert " + std::to_string(nodes.size()) + " nodes",
|
||||
std::move(cmds)));
|
||||
}
|
||||
|
||||
bool NtxNodeTree::deleteNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
std::vector<NtxCommandUPtr> cmds;
|
||||
cmds.reserve(nodes.size());
|
||||
|
||||
// Rückwärts löschen → Indizes bleiben stabil
|
||||
for (auto it = nodes.rbegin(); it != nodes.rend(); ++it)
|
||||
cmds.push_back(std::make_unique<NtxRemoveNodeCmd>(*it));
|
||||
|
||||
return execute(NtxMacroCommand::create(
|
||||
"Delete " + std::to_string(nodes.size()) + " nodes",
|
||||
std::move(cmds)));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Clipboard
|
||||
// =========================================================================
|
||||
|
||||
void NtxNodeTree::copyNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
m_clipboard.copyNodes(nodes);
|
||||
m_isCutOperation = false;
|
||||
}
|
||||
|
||||
void NtxNodeTree::cutNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
m_clipboard.copyNodes(nodes);
|
||||
m_isCutOperation = true;
|
||||
}
|
||||
|
||||
NtxNodeList NtxNodeTree::pasteNodes(NtxNodePtr parent, size_t index)
|
||||
{
|
||||
NtxNodeList pasted = m_clipboard.pasteNodes();
|
||||
if (pasted.empty())
|
||||
return {};
|
||||
|
||||
if (m_isCutOperation)
|
||||
{
|
||||
// Cut+Paste = Remove originals + Insert clones (als Makro)
|
||||
auto macro = std::make_unique<NtxMacroCommand>(
|
||||
"Paste " + std::to_string(pasted.size()) + " nodes (cut)");
|
||||
|
||||
// 1. Originale entfernen (rückwärts für stabile Indizes)
|
||||
const auto& entries = m_clipboard.getEntries();
|
||||
for (auto it = entries.rbegin(); it != entries.rend(); ++it)
|
||||
{
|
||||
if (auto origParent = it->originalParent.lock())
|
||||
{
|
||||
if (it->originalPosition < origParent->getChildCount())
|
||||
{
|
||||
auto origNode = origParent->getChild(it->originalPosition);
|
||||
if (origNode)
|
||||
macro->add(std::make_unique<NtxRemoveNodeCmd>(origNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Clones einfügen
|
||||
for (size_t i = 0; i < pasted.size(); ++i)
|
||||
{
|
||||
macro->add(std::make_unique<NtxInsertNodeCmd>(
|
||||
parent, pasted[i], index + i));
|
||||
}
|
||||
|
||||
if (!execute(std::move(macro)))
|
||||
return {};
|
||||
|
||||
m_isCutOperation = false;
|
||||
m_clipboard.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy+Paste = nur Insert
|
||||
if (!addNodes(parent, pasted, index))
|
||||
return {};
|
||||
}
|
||||
|
||||
return pasted;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::hasClipboard() const
|
||||
{
|
||||
return !m_clipboard.isEmpty();
|
||||
}
|
||||
|
||||
void NtxNodeTree::clearClipboard()
|
||||
{
|
||||
m_clipboard.clear();
|
||||
m_isCutOperation = false;
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
99
nodes/services/ntxnodetree.h
Normal file
99
nodes/services/ntxnodetree.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef NTX_NODETREE_H
|
||||
#define NTX_NODETREE_H
|
||||
|
||||
#include <ntxnode.h>
|
||||
#include <ntxclipboard.h>
|
||||
#include <ntxundostack.h>
|
||||
#include <ntxnodecommands.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Service-Schicht für Knoten-Operationen mit Undo/Redo.
|
||||
*
|
||||
* Ist selbst ein NtxINode (Composite-Pattern): Kann als Wurzel
|
||||
* eines Teilbaums dienen und in andere NtxNodeTrees eingehängt werden.
|
||||
*
|
||||
* Bietet:
|
||||
* - Command-basierte Baum-Manipulation (add/delete/move)
|
||||
* - Undo/Redo via NtxUndoStack
|
||||
* - Copy/Cut/Paste via NtxClipboard
|
||||
* - Listen-Operationen via NtxMacroCommand
|
||||
*/
|
||||
class NtxNodeTree //: public NtxNode
|
||||
{
|
||||
friend class NtxNodeFactory;
|
||||
|
||||
public:
|
||||
|
||||
//~NtxNodeTree() override = default;
|
||||
|
||||
NtxNodeTree(const NtxNodeTree&) = delete;
|
||||
NtxNodeTree& operator=(const NtxNodeTree&) = delete;
|
||||
|
||||
NtxNodePtr clone() const;// override;
|
||||
|
||||
// =========================================================================
|
||||
// Command-Ausführung
|
||||
// =========================================================================
|
||||
|
||||
/// Führt ein beliebiges Command aus (mit Undo-Support).
|
||||
bool execute(NtxCommandUPtr cmd);
|
||||
|
||||
bool undo();
|
||||
bool redo();
|
||||
bool canUndo() const;
|
||||
bool canRedo() const;
|
||||
NtxString undoText() const;
|
||||
NtxString redoText() const;
|
||||
|
||||
void setClean();
|
||||
bool isDirty() const;
|
||||
|
||||
// =========================================================================
|
||||
// Einzel-Operationen (erzeugen intern Commands)
|
||||
// =========================================================================
|
||||
|
||||
bool addNode(NtxNodePtr parent, NtxNodePtr node, size_t index);
|
||||
bool deleteNode(NtxNodePtr node);
|
||||
bool moveNode(NtxNodePtr node, NtxNodePtr newParent, size_t newIndex);
|
||||
|
||||
// =========================================================================
|
||||
// Listen-Operationen (erzeugen NtxMacroCommand)
|
||||
// =========================================================================
|
||||
|
||||
bool addNodes(NtxNodePtr parent, const NtxNodeList& nodes, size_t index);
|
||||
bool deleteNodes(const NtxNodeList& nodes);
|
||||
|
||||
// =========================================================================
|
||||
// Clipboard
|
||||
// =========================================================================
|
||||
|
||||
void copyNodes(const NtxNodeList& nodes);
|
||||
void cutNodes(const NtxNodeList& nodes);
|
||||
NtxNodeList pasteNodes(NtxNodePtr parent, size_t index);
|
||||
|
||||
bool hasClipboard() const;
|
||||
void clearClipboard();
|
||||
|
||||
// =========================================================================
|
||||
// Zugriff auf Interna
|
||||
// =========================================================================
|
||||
|
||||
NtxUndoStack& undoStack() { return m_undoStack; }
|
||||
const NtxUndoStack& undoStack() const { return m_undoStack; }
|
||||
|
||||
private:
|
||||
|
||||
NtxNodeTree() = default;
|
||||
explicit NtxNodeTree(NtxClassTypeId id);
|
||||
|
||||
NtxUndoStack m_undoStack;
|
||||
NtxClipboard m_clipboard;
|
||||
bool m_isCutOperation{false};
|
||||
};
|
||||
|
||||
} // namespace ntx
|
||||
|
||||
#endif // NTX_NODETREE_H
|
||||
209
nodes/services/ntxnodexml.cpp
Normal file
209
nodes/services/ntxnodexml.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
|
||||
|
||||
#include "ntxnodexml.h"
|
||||
#include <ntxnodefactory.h>
|
||||
#include <pugixml.hpp>
|
||||
#include <iostream>
|
||||
#include <sstream> // Add this include at the top of the file
|
||||
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
// Rekursive Hilfsfunktion
|
||||
static NtxNodePtr parseElementRecursive(const pugi::xml_node& xmlNode)
|
||||
{
|
||||
if (!xmlNode)
|
||||
return nullptr;
|
||||
|
||||
// 1. Tag-Name als ID-String verwenden
|
||||
NtxString tagName = xmlNode.name();
|
||||
|
||||
// Ignoriere spezielle Knotentypen (Kommentare, PCDATA/Text, etc.) wenn sie leer sind
|
||||
// In diesem einfachen Beispiel behandeln wir nur Element-Knoten als echte NtxNodes.
|
||||
if (xmlNode.type() != pugi::node_element)
|
||||
return nullptr;
|
||||
|
||||
// 2. Erzeuge Knoten via Factory (nutzt implizit CTypeFactory für Mapping)
|
||||
NtxNodePtr newNode = NtxNodeFactory::makeNode(tagName);
|
||||
if (!newNode)
|
||||
return nullptr;
|
||||
|
||||
// 3. Attribute übertragen
|
||||
for (pugi::xml_attribute attr : xmlNode.attributes())
|
||||
{
|
||||
NtxString key = attr.name();
|
||||
|
||||
// Einfache Heuristik für Typen:
|
||||
// PugiXML liefert strings. Wir könnten versuchen zu konvertieren oder alles als String lassen.
|
||||
// Hier: Alles als String speichern, oder versuchen int/double zu parsen.
|
||||
// Fürs erste: Speichern als String, Payload erlaubt mixed types.
|
||||
newNode->set(key, NtxString(attr.value()));
|
||||
|
||||
/* Optional: Intelligentes Parsen
|
||||
if (attr.as_int() != 0 || std::string(attr.value()) == "0")
|
||||
newNode->set(key, attr.as_int());
|
||||
else
|
||||
newNode->set(key, NtxString(attr.value()));
|
||||
*/
|
||||
}
|
||||
|
||||
// 4. Kinder rekursiv verarbeiten
|
||||
for (pugi::xml_node child : xmlNode.children())
|
||||
{
|
||||
NtxNodePtr childNode = parseElementRecursive(child);
|
||||
if (childNode)
|
||||
{
|
||||
newNode->addChild(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeXml::loadFromFile(const std::string& filename)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_parse_result result = doc.load_file(filename.c_str());
|
||||
|
||||
if (!result)
|
||||
{
|
||||
std::cerr << "XML Load Error: " << result.description() << " in " << filename << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Wir nehmen den ersten Root-Knoten (das Wurzelelement)
|
||||
// doc.document_element() gibt das erste Kind vom Typ Element zurück (ignoriert PI, DOCTYPE etc.)
|
||||
return parseElementRecursive(doc.document_element());
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeXml::loadFromString(const std::string& xmlContent)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_parse_result result = doc.load_string(xmlContent.c_str());
|
||||
|
||||
if (!result)
|
||||
{
|
||||
std::cerr << "XML Parse Error: " << result.description() << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return parseElementRecursive(doc.document_element());
|
||||
}
|
||||
|
||||
// Rekursive Hilfsfunktion zum Serialisieren
|
||||
static void serializeNodeRecursive(const NtxNodeCPtr& node, pugi::xml_node& xmlNode)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
// 1. Tag-Name aus CType-Label holen
|
||||
NtxString tagName = node->getClassTypeLabel();
|
||||
pugi::xml_node childElement = xmlNode.append_child(tagName.c_str());
|
||||
|
||||
// 2. Alle Attribute aus dem Payload schreiben
|
||||
node->forEachProperty([&childElement](const NtxString& key, const NtxVariant& value)
|
||||
{
|
||||
// Konvertiere NtxVariant zu String und setze als XML-Attribut
|
||||
std::visit([&childElement, &key](auto&& arg)
|
||||
{
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, std::monostate>)
|
||||
{
|
||||
// Überspringe leere Werte
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, NtxString>)
|
||||
{
|
||||
childElement.append_attribute(key.c_str()).set_value(arg.c_str());
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, int>)
|
||||
{
|
||||
childElement.append_attribute(key.c_str()).set_value(arg);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, double>)
|
||||
{
|
||||
childElement.append_attribute(key.c_str()).set_value(arg);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, bool>)
|
||||
{
|
||||
childElement.append_attribute(key.c_str()).set_value(arg);
|
||||
}
|
||||
}, value);
|
||||
});
|
||||
|
||||
// 3. Kinder rekursiv verarbeiten
|
||||
for (size_t i = 0; i < node->getChildCount(); ++i)
|
||||
{
|
||||
NtxNodeCPtr child = node->getChild(i);
|
||||
if (child)
|
||||
{
|
||||
serializeNodeRecursive(child, childElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NtxNodeXml::saveToFile(const NtxNodePtr& node, const std::string& filename)
|
||||
{
|
||||
return saveToFile(std::const_pointer_cast<const NtxINode>(node), filename);
|
||||
}
|
||||
|
||||
bool NtxNodeXml::saveToFile(const NtxNodeCPtr& node, const std::string& filename)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
std::cerr << "Cannot save null node to file: " << filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
pugi::xml_document doc;
|
||||
|
||||
// XML-Deklaration hinzufügen
|
||||
pugi::xml_node declaration = doc.prepend_child(pugi::node_declaration);
|
||||
declaration.append_attribute("version") = "1.0";
|
||||
declaration.append_attribute("encoding") = "UTF-8";
|
||||
|
||||
// Root-Node serialisieren
|
||||
serializeNodeRecursive(node, doc);
|
||||
|
||||
// In Datei speichern mit Formatierung
|
||||
bool success = doc.save_file(filename.c_str(), " ", pugi::format_default, pugi::encoding_utf8);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
std::cerr << "Failed to save XML to file: " << filename << std::endl;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
std::string NtxNodeXml::saveToString(const NtxNodePtr& node)
|
||||
{
|
||||
return saveToString(std::const_pointer_cast<const NtxINode>(node));
|
||||
}
|
||||
|
||||
std::string NtxNodeXml::saveToString(const NtxNodeCPtr& node)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
std::cerr << "Cannot serialize null node to string" << std::endl;
|
||||
return "";
|
||||
}
|
||||
|
||||
pugi::xml_document doc;
|
||||
|
||||
// XML-Deklaration hinzufügen
|
||||
pugi::xml_node declaration = doc.prepend_child(pugi::node_declaration);
|
||||
declaration.append_attribute("version") = "1.0";
|
||||
declaration.append_attribute("encoding") = "UTF-8";
|
||||
|
||||
// Root-Node serialisieren
|
||||
serializeNodeRecursive(node, doc);
|
||||
|
||||
// In String konvertieren
|
||||
std::ostringstream oss;
|
||||
doc.save(oss, " ", pugi::format_default, pugi::encoding_utf8);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
27
nodes/services/ntxnodexml.h
Normal file
27
nodes/services/ntxnodexml.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef NTX_NODEXML_H
|
||||
#define NTX_NODEXML_H
|
||||
|
||||
#include <ntxinode.h>
|
||||
#include <string>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
class NtxNodeXml
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
static NtxNodePtr loadFromFile(const std::string& filename);
|
||||
static NtxNodePtr loadFromString(const std::string& xmlContent);
|
||||
|
||||
// Methoden zum Speichern
|
||||
static bool saveToFile(const NtxNodePtr& node, const std::string& filename);
|
||||
static bool saveToFile(const NtxNodeCPtr& node, const std::string& filename);
|
||||
|
||||
static std::string saveToString(const NtxNodePtr& node);
|
||||
static std::string saveToString(const NtxNodeCPtr& node);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NTX_NODEXML_H
|
||||
156
nodes/services/ntxundostack.cpp
Normal file
156
nodes/services/ntxundostack.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <ntxundostack.h>
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
NtxUndoStack::NtxUndoStack()
|
||||
: m_index(0)
|
||||
, m_cleanIndex(0)
|
||||
, m_undoLimit(0)
|
||||
{
|
||||
}
|
||||
|
||||
void NtxUndoStack::push(NtxCommandUPtr command)
|
||||
{
|
||||
if (!command)
|
||||
return;
|
||||
|
||||
if (!command->canExecute())
|
||||
return;
|
||||
|
||||
if (!command->execute())
|
||||
return;
|
||||
|
||||
if (m_index < static_cast<int>(m_commands.size()))
|
||||
{
|
||||
m_commands.erase(m_commands.begin() + m_index, m_commands.end());
|
||||
}
|
||||
|
||||
m_commands.push_back(std::move(command));
|
||||
m_index++;
|
||||
|
||||
if (m_cleanIndex > m_index)
|
||||
m_cleanIndex = -1;
|
||||
|
||||
checkUndoLimit();
|
||||
}
|
||||
|
||||
bool NtxUndoStack::canUndo() const
|
||||
{
|
||||
return m_index > 0;
|
||||
}
|
||||
|
||||
bool NtxUndoStack::canRedo() const
|
||||
{
|
||||
return m_index < static_cast<int>(m_commands.size());
|
||||
}
|
||||
|
||||
void NtxUndoStack::undo()
|
||||
{
|
||||
if (!canUndo())
|
||||
return;
|
||||
|
||||
m_index--;
|
||||
|
||||
if (m_commands[m_index]->canUndo())
|
||||
{
|
||||
m_commands[m_index]->undo();
|
||||
}
|
||||
}
|
||||
|
||||
void NtxUndoStack::redo()
|
||||
{
|
||||
if (!canRedo())
|
||||
return;
|
||||
|
||||
if (m_commands[m_index]->canExecute())
|
||||
{
|
||||
m_commands[m_index]->execute();
|
||||
}
|
||||
|
||||
m_index++;
|
||||
}
|
||||
|
||||
int NtxUndoStack::index() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
int NtxUndoStack::count() const
|
||||
{
|
||||
return static_cast<int>(m_commands.size());
|
||||
}
|
||||
|
||||
NtxString NtxUndoStack::undoText() const
|
||||
{
|
||||
if (!canUndo())
|
||||
return NtxString();
|
||||
|
||||
return m_commands[m_index - 1]->getDescription();
|
||||
}
|
||||
|
||||
NtxString NtxUndoStack::redoText() const
|
||||
{
|
||||
if (!canRedo())
|
||||
return NtxString();
|
||||
|
||||
return m_commands[m_index]->getDescription();
|
||||
}
|
||||
|
||||
void NtxUndoStack::clear()
|
||||
{
|
||||
m_commands.clear();
|
||||
m_index = 0;
|
||||
m_cleanIndex = 0;
|
||||
}
|
||||
|
||||
void NtxUndoStack::setClean()
|
||||
{
|
||||
m_cleanIndex = m_index;
|
||||
}
|
||||
|
||||
bool NtxUndoStack::isClean() const
|
||||
{
|
||||
return m_cleanIndex == m_index;
|
||||
}
|
||||
|
||||
void NtxUndoStack::setUndoLimit(int limit)
|
||||
{
|
||||
m_undoLimit = limit;
|
||||
checkUndoLimit();
|
||||
}
|
||||
|
||||
int NtxUndoStack::undoLimit() const
|
||||
{
|
||||
return m_undoLimit;
|
||||
}
|
||||
|
||||
const NtxICommand* NtxUndoStack::command(int index) const
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(m_commands.size()))
|
||||
return nullptr;
|
||||
|
||||
return m_commands[index].get();
|
||||
}
|
||||
|
||||
void NtxUndoStack::checkUndoLimit()
|
||||
{
|
||||
if (m_undoLimit <= 0)
|
||||
return;
|
||||
|
||||
int deleteCount = m_index - m_undoLimit;
|
||||
if (deleteCount <= 0)
|
||||
return;
|
||||
|
||||
m_commands.erase(m_commands.begin(), m_commands.begin() + deleteCount);
|
||||
m_index -= deleteCount;
|
||||
|
||||
if (m_cleanIndex != -1)
|
||||
{
|
||||
m_cleanIndex -= deleteCount;
|
||||
if (m_cleanIndex < 0)
|
||||
m_cleanIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user