1#include <Core/Resources/Resources.hpp>
2#include <Core/Utils/StdFilesystem.hpp>
3#include <Gui/Utils/KeyMappingManager.hpp>
4#include <catch2/catch_test_macros.hpp>
9using namespace Ra::Gui;
17 static void configureKeyMapping_impl();
26 bool checkIntegrity(
const std::string& mess )
const;
29#define KeyMappingDummy \
33#define KMA_VALUE( XX ) static KeyMappingManager::KeyMappingAction XX;
38#define KMA_VALUE( XX ) Gui::KeyMappingManager::KeyMappingAction Dummy::XX;
47void Dummy::configureKeyMapping_impl() {
49 Gui::KeyMappingManager::getInstance()->getContext(
"DummyContext" ) );
50 if ( getContext().isInvalid() ) {
51 LOG( Ra::Core::Utils::logINFO )
52 <<
"DummyContext not defined (maybe the configuration file do not contains it)";
57 Ra::Gui::KeyMappingManager::getInstance()->getAction( getContext(),
"MyActionName" );
60#define KMA_VALUE( XX ) \
61 XX = Gui::KeyMappingManager::getInstance()->getAction( \
62 KeyMappingManageable<Dummy>::getContext(), #XX );
67TEST_CASE(
"Gui/Utils/KeyMappingManager",
"[unittests][Gui][Gui/Utils][KeyMappingManager]" ) {
68 QCoreApplication::setOrganizationName(
"RadiumUnitTests" );
69 QCoreApplication::setApplicationName(
"KeyMappingManager" );
72 KeyMappingManager::createInstance();
73 auto mgr = Gui::KeyMappingManager::getInstance();
75 auto resourcesRootDir { optionalPath.value_or(
"[[Default resrouces path not found]]" ) };
77 auto defaultConfigFile = resourcesRootDir +
std::string(
"Configs/default.xml" );
79 SECTION(
"key mapping file load" ) {
80 REQUIRE( std::filesystem::path { defaultConfigFile } ==
81 std::filesystem::path { mgr->getLoadedFilename() } );
82 mgr->loadConfiguration(
"dummy" );
83 REQUIRE( std::filesystem::path { defaultConfigFile } ==
84 std::filesystem::path { mgr->getLoadedFilename() } );
85 std::cout << std::filesystem::current_path() <<
"\n";
86 mgr->loadConfiguration(
"data/keymapping-valid.xml" );
87 REQUIRE(
"data/keymapping-valid.xml" == mgr->getLoadedFilename() );
89 mgr->loadConfiguration(
"data/keymapping-invalid.xml" );
90 REQUIRE( std::filesystem::path { defaultConfigFile } ==
91 std::filesystem::path { mgr->getLoadedFilename() } );
93 mgr->loadConfiguration(
"data/keymapping-double-actions.xml" );
94 REQUIRE(
"data/keymapping-double-actions.xml" == mgr->getLoadedFilename() );
96 mgr->loadConfiguration(
"data/keymapping-bad-tag.xml" );
97 REQUIRE( std::filesystem::path { defaultConfigFile } ==
98 std::filesystem::path { mgr->getLoadedFilename() } );
100 mgr->loadConfiguration(
"data/keymapping-bad-main.xml" );
101 REQUIRE(
"data/keymapping-bad-main.xml" == mgr->getLoadedFilename() );
104 SECTION(
"getAction" ) {
105 mgr->loadConfiguration(
"data/keymapping-valid.xml" );
107 auto cameraContext { mgr->getContext(
"CameraContext" ) };
108 REQUIRE( cameraContext.isValid() );
109 REQUIRE( mgr->getContextName( cameraContext ) ==
"CameraContext" );
111 auto viewerContext { mgr->getContext(
"ViewerContext" ) };
112 REQUIRE( viewerContext.isValid() );
113 REQUIRE( viewerContext != cameraContext );
115 auto invalidContext { mgr->getContext(
"InvalidContext" ) };
116 REQUIRE( invalidContext.isInvalid() );
118 REQUIRE( mgr->getContextName( Ctx {} ) ==
"Invalid" );
119 REQUIRE( mgr->getContextName( Ctx { 42 } ) ==
"Invalid" );
122 auto validAction { mgr->getAction( cameraContext, Qt::LeftButton, Qt::NoModifier, -1 ) };
123 REQUIRE( validAction.isValid() );
124 REQUIRE( validAction == mgr->getAction( cameraContext,
"TRACKBALLCAMERA_ROTATE" ) );
125 REQUIRE( mgr->getAction( Ctx {},
"TRACKBALLCAMERA_ROTATE" ).isInvalid() );
126 REQUIRE( mgr->getAction( Ctx { 42 },
"TRACKBALLCAMERA_ROTATE" ).isInvalid() );
127 REQUIRE( mgr->getActionName( cameraContext, validAction ) ==
"TRACKBALLCAMERA_ROTATE" );
130 REQUIRE( mgr->getActionName( cameraContext, Idx {} ) ==
"Invalid" );
133 validAction = mgr->getAction( cameraContext, Qt::LeftButton, Qt::ShiftModifier, -1 );
135 mgr->getAction( cameraContext, Qt::LeftButton, Qt::ShiftModifier, Qt::Key_Shift ) };
136 REQUIRE( validAction == action2 );
139 auto invalidAction { mgr->getAction( cameraContext, Qt::LeftButton, Qt::AltModifier, -1 ) };
140 REQUIRE( invalidAction.isInvalid() );
141 REQUIRE( invalidAction != mgr->getAction( cameraContext,
"TRACKBALLCAMERA_ROTATE" ) );
142 REQUIRE( mgr->getAction( Idx {}, Qt::LeftButton, Qt::AltModifier, -1 ).isInvalid() );
143 REQUIRE( mgr->getAction( Idx {}, Qt::LeftButton, Qt::AltModifier, 1 ).isInvalid() );
144 REQUIRE( mgr->getAction( Idx {}, Qt::LeftButton, Qt::NoModifier, -1 ).isInvalid() );
145 REQUIRE( mgr->getAction( Idx {}, Qt::RightButton, Qt::AltModifier, -1 ).isInvalid() );
148 validAction = mgr->getAction( viewerContext, Qt::RightButton, Qt::NoModifier, Qt::Key_V );
149 REQUIRE( validAction.isValid() );
150 REQUIRE( validAction == mgr->getAction( viewerContext,
"VIEWER_PICKING_VERTEX" ) );
153 REQUIRE( mgr->getAction( viewerContext,
"UnkownAction" ).isInvalid() );
154 validAction = mgr->getAction( viewerContext, Qt::NoButton, Qt::ControlModifier, Qt::Key_W );
155 REQUIRE( validAction.isValid() );
156 REQUIRE( validAction == mgr->getAction( viewerContext,
"VIEWER_TOGGLE_WIREFRAME" ) );
159 invalidAction = mgr->getAction( viewerContext, Qt::LeftButton, Qt::NoModifier, -1 );
160 REQUIRE( invalidAction.isInvalid() );
161 REQUIRE( mgr->getAction( cameraContext,
"VIEWER_TOGGLE_WIREFRAME" ).isInvalid() );
164 SECTION(
"listener" ) {
177 mgr->loadConfiguration(
"data/dummy1.xml" );
180 auto test1Idx = mgr->getAction( Dummy::getContext(),
"TEST1" );
181 auto test2Idx = mgr->getAction( Dummy::getContext(),
"TEST2" );
184 mgr->getAction( Dummy::getContext(), Qt::LeftButton, Qt::NoModifier, -1 ) );
186 mgr->getAction( Dummy::getContext(), Qt::RightButton, Qt::NoModifier, -1 ) );
188 REQUIRE( Dummy::TEST1 == test1Idx );
189 REQUIRE( Dummy::TEST2 == test2Idx );
192 mgr->loadConfiguration(
"data/dummy2.xml" );
193 auto test1Idx2 = mgr->getAction( Dummy::getContext(),
"TEST1" );
194 auto test2Idx2 = mgr->getAction( Dummy::getContext(),
"TEST2" );
197 REQUIRE( Dummy::TEST1 ==
198 mgr->getAction( Dummy::getContext(), Qt::RightButton, Qt::NoModifier, -1 ) );
199 REQUIRE( Dummy::TEST2 ==
200 mgr->getAction( Dummy::getContext(), Qt::LeftButton, Qt::NoModifier, -1 ) );
202 REQUIRE( test1Idx != Dummy::TEST1 );
203 REQUIRE( test2Idx != Dummy::TEST2 );
206 mgr->removeListener( didx );
207 mgr->loadConfiguration(
"data/dummy1.xml" );
210 mgr->getAction( Dummy::getContext(), Qt::LeftButton, Qt::NoModifier, -1 ) );
212 mgr->getAction( Dummy::getContext(), Qt::RightButton, Qt::NoModifier, -1 ) );
214 REQUIRE( Dummy::TEST1 != test1Idx );
215 REQUIRE( Dummy::TEST1 == test1Idx2 );
216 REQUIRE( Dummy::TEST2 != test2Idx );
217 REQUIRE( Dummy::TEST2 == test2Idx2 );
220 SECTION(
"Custom context and actions" ) {
221 auto nonExistingcontext = mgr->getContext(
"Keymapping::CustomContext" );
222 REQUIRE( nonExistingcontext.isInvalid() );
223 auto customContext = mgr->addContext(
"Keymapping::CustomContext" );
224 REQUIRE( customContext.isValid() );
225 auto replicateContext = mgr->addContext(
"Keymapping::CustomContext" );
226 REQUIRE( replicateContext == customContext );
227 auto customAction = mgr->addAction(
228 customContext, mgr->createEventBindingFromStrings(
"",
"",
"Key_F1" ),
"CustomAction" );
229 REQUIRE( customAction.isValid() );
230 auto customActionDuplicate = mgr->addAction(
231 customContext, mgr->createEventBindingFromStrings(
"",
"",
"Key_F1" ),
"CustomAction" );
232 REQUIRE( customActionDuplicate.isValid() );
233 REQUIRE( customActionDuplicate == customAction );
234 auto customActionOtherBinding = mgr->addAction(
235 customContext, mgr->createEventBindingFromStrings(
"",
"",
"Key_F2" ),
"CustomAction" );
236 REQUIRE( customActionOtherBinding.isValid() );
237 REQUIRE( customActionOtherBinding == customAction );
240 SECTION(
"Get Binding" ) {
241 mgr->loadConfiguration(
"data/keymapping-valid.xml" );
243 auto cameraContext { mgr->getContext(
"CameraContext" ) };
244 REQUIRE( cameraContext.isValid() );
245 REQUIRE( mgr->getContextName( cameraContext ) ==
"CameraContext" );
248 auto validAction { mgr->getAction( cameraContext, Qt::LeftButton, Qt::NoModifier, -1 ) };
249 auto validBinding { mgr->getBinding( cameraContext, validAction ) };
250 REQUIRE( validAction.isValid() );
251 REQUIRE( validBinding );
252 REQUIRE( validAction == mgr->getAction( cameraContext,
253 validBinding->m_buttons,
254 validBinding->m_modifiers,
255 validBinding->m_key ) );
256 REQUIRE( validBinding->m_buttons == Qt::LeftButton );
257 REQUIRE( validBinding->m_modifiers == Qt::NoModifier );
258 REQUIRE( validBinding->m_key == -1 );
259 REQUIRE( validBinding->m_wheel ==
false );
261 auto invalidBinding { mgr->getBinding( cameraContext, {} ) };
262 REQUIRE( !invalidBinding );
266 REQUIRE( mouseEvent.isMouseEvent() );
269 REQUIRE( wheelEvent.isWheelEvent() );
272 REQUIRE( keyEvent.isKeyEvent() );
275 Qt::LeftButton, Qt::MetaModifier, Qt::Key_Bar };
276 REQUIRE( ( !combinedEvent.isKeyEvent() && combinedEvent.isMouseEvent() ) );
[Declare KeyMappingManageable]
Dummy()
[Declare KeyMappingManageable]
KeyMappingManageable decorator to use as CRTP.
static void configureKeyMapping()
Inner class to store event binding.
Ra::Core::Utils::Index KeyMappingAction
handle to an action
Ra::Core::Utils::Index Context
handle to a Context
optional< std::string > getRadiumResourcesPath()
Get the path of Radium internal resources.
hepler function to manage enum as underlying types in VariableSet