├── .gitignore ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── app ├── CMakeLists.txt ├── resources │ ├── Fontin-SmallCaps.ttf │ ├── LabCompass.ico │ ├── OpenSans-Regular.ttf │ ├── app.qrc │ ├── images │ │ ├── browse.svg │ │ ├── check.svg │ │ ├── close.svg │ │ ├── compass │ │ │ ├── direction-hud.svg │ │ │ ├── door-normal.svg │ │ │ ├── door-target.svg │ │ │ ├── loot-normal.svg │ │ │ ├── loot-target.svg │ │ │ ├── minimap-hud.svg │ │ │ ├── tile-cross.svg │ │ │ ├── tile-full.svg │ │ │ └── tile-trap.svg │ │ ├── focus.svg │ │ ├── github.svg │ │ ├── instruction │ │ │ ├── backward.svg │ │ │ ├── direction.svg │ │ │ ├── direction_E.svg │ │ │ ├── direction_N.svg │ │ │ ├── direction_NE.svg │ │ │ ├── direction_NW.svg │ │ │ ├── direction_S.svg │ │ │ ├── direction_SE.svg │ │ │ ├── direction_SW.svg │ │ │ ├── direction_W.svg │ │ │ ├── direction_unknown.svg │ │ │ ├── izaro-kill.svg │ │ │ ├── izaro-wait.svg │ │ │ ├── loaded-map-cruel.svg │ │ │ ├── loaded-map-merciless.svg │ │ │ ├── loaded-map-normal.svg │ │ │ ├── loaded-map-uber.svg │ │ │ ├── loot.svg │ │ │ ├── mechanics.svg │ │ │ ├── opposite.svg │ │ │ ├── secret-passage.svg │ │ │ └── warning.svg │ │ ├── lab-content │ │ │ ├── argus.svg │ │ │ ├── darkshrine.svg │ │ │ ├── gauntlet-puzzle.svg │ │ │ ├── golden-door.svg │ │ │ ├── golden-key.svg │ │ │ ├── izaro.svg │ │ │ ├── silver-door.svg │ │ │ └── silver-key.svg │ │ ├── map-marker-light.svg │ │ ├── map-marker-orange.svg │ │ ├── navigation-light.svg │ │ ├── patreon.svg │ │ ├── paypal.svg │ │ ├── planner │ │ │ ├── drop-area-border.svg │ │ │ └── map.svg │ │ ├── puzzle-light.svg │ │ ├── room-preset │ │ │ ├── c_branch.svg │ │ │ ├── c_branch_bottleneck_1.svg │ │ │ ├── c_branch_bottleneck_2.svg │ │ │ ├── c_branch_door.svg │ │ │ ├── c_end_bottleneck.svg │ │ │ ├── c_quad.svg │ │ │ ├── c_quad_door.svg │ │ │ ├── c_straight.svg │ │ │ ├── c_straight_bottleneck.svg │ │ │ ├── dg_branch.svg │ │ │ ├── dg_branch_bottleneck_1.svg │ │ │ ├── dg_branch_bottleneck_2.svg │ │ │ ├── dg_branch_door.svg │ │ │ ├── dg_end_bottleneck.svg │ │ │ ├── dg_quad.svg │ │ │ ├── dg_quad_door.svg │ │ │ ├── dg_straight.svg │ │ │ ├── dg_straight_bottleneck.svg │ │ │ ├── disabled.svg │ │ │ ├── eh_block_branch.svg │ │ │ ├── eh_branch.svg │ │ │ ├── eh_branch_bottleneck_2.svg │ │ │ ├── eh_branch_door.svg │ │ │ ├── eh_end_bottleneck.svg │ │ │ ├── eh_quad.svg │ │ │ ├── eh_quad_door.svg │ │ │ ├── eh_straight.svg │ │ │ ├── eh_straight_bottleneck.svg │ │ │ ├── oh_branch.svg │ │ │ ├── oh_branch_bottleneck_1.svg │ │ │ ├── oh_branch_bottleneck_2.svg │ │ │ ├── oh_branch_door.svg │ │ │ ├── oh_end_bottleneck.svg │ │ │ ├── oh_quad.svg │ │ │ ├── oh_quad_door.svg │ │ │ ├── oh_straight.svg │ │ │ ├── oh_straight_bottleneck.svg │ │ │ ├── p_branch.svg │ │ │ ├── p_branch_bottleneck_1.svg │ │ │ ├── p_branch_bottleneck_2.svg │ │ │ ├── p_branch_door.svg │ │ │ ├── p_end_bottleneck.svg │ │ │ ├── p_quad.svg │ │ │ ├── p_straight.svg │ │ │ ├── p_straight_bottleneck.svg │ │ │ ├── rt_branch.svg │ │ │ ├── rt_branch_bottleneck_1.svg │ │ │ ├── rt_branch_bottleneck_2.svg │ │ │ ├── rt_branch_door.svg │ │ │ ├── rt_end_bottleneck.svg │ │ │ ├── rt_quad.svg │ │ │ ├── rt_quad_door.svg │ │ │ ├── rt_straight.svg │ │ │ └── rt_straight_bottleneck.svg │ │ ├── rounded-corner.svg │ │ ├── settings-light.svg │ │ ├── star-gold.svg │ │ ├── star-light.svg │ │ └── view-list-light.svg │ └── ui │ │ ├── CircleProgressBar.qml │ │ ├── DragMoveArea.qml │ │ ├── Dummy.qml │ │ ├── Global.qml │ │ ├── GlobalAccessor.qml │ │ ├── Header.qml │ │ ├── HighlightTab.qml │ │ ├── MaterialInk.qml │ │ ├── NotificationIndicator.qml │ │ ├── Puzzle.qml │ │ ├── RoomContentIcon.qml │ │ ├── RoomContentView.qml │ │ ├── StandardAnimation.qml │ │ ├── SvgImage.qml │ │ ├── TabLabel.qml │ │ ├── TextHighlightTab.qml │ │ ├── Toolbar.qml │ │ ├── ToolbarButton.qml │ │ ├── TooltipHoverArea.qml │ │ ├── WindowWithShadow.qml │ │ ├── compass │ │ ├── Compass.qml │ │ ├── CompassToolbar.qml │ │ ├── DirectionDisplay.qml │ │ └── MinimapDisplay.qml │ │ ├── instruction │ │ ├── DirectionInstructionItem.qml │ │ ├── InstructionItem.qml │ │ ├── InstructionList.qml │ │ ├── IzaroInstructionItem.qml │ │ ├── LoadedMapInstructionItem.qml │ │ ├── LootInstructionItem.qml │ │ └── WarningInstructionItem.qml │ │ ├── options │ │ ├── KeySequenceEdit.qml │ │ ├── Options.qml │ │ └── OptionsGridLayout.qml │ │ ├── planner │ │ ├── LabyrinthMapDisplay.qml │ │ ├── MapDropArea.qml │ │ ├── PlanSummaryDisplay.qml │ │ ├── PlannedRouteDisplay.qml │ │ ├── Planner.qml │ │ ├── RoomClickModeSwitch.qml │ │ └── RoomLabel.qml │ │ ├── point.js │ │ ├── rect.js │ │ └── roompresets │ │ ├── MinimapLegend.qml │ │ ├── RoomPresets.qml │ │ └── StaticMinimapDisplay.qml ├── src │ ├── application.cpp │ ├── application.h │ ├── hotkey │ │ ├── hotkeybinding.cpp │ │ └── hotkeybinding.h │ ├── keysequence │ │ ├── keysequencehelper.cpp │ │ └── keysequencehelper.h │ ├── main.cpp │ ├── stdafx.h │ ├── tray │ │ ├── trayiconmenu.cpp │ │ └── trayiconmenu.h │ ├── util │ │ ├── setupdebugoutput.cpp │ │ └── setupdebugoutput.h │ └── window │ │ ├── compasstoolbarwindow.cpp │ │ ├── compasstoolbarwindow.h │ │ ├── compasswindow.cpp │ │ ├── compasswindow.h │ │ ├── headerwindow.cpp │ │ ├── headerwindow.h │ │ ├── instructionlistwindow.cpp │ │ ├── instructionlistwindow.h │ │ ├── optionswindow.cpp │ │ ├── optionswindow.h │ │ ├── plannerwindow.cpp │ │ ├── plannerwindow.h │ │ ├── puzzlewindow.cpp │ │ ├── puzzlewindow.h │ │ ├── roompresetswindow.cpp │ │ ├── roompresetswindow.h │ │ ├── toolbarwindow.cpp │ │ ├── toolbarwindow.h │ │ ├── window.cpp │ │ └── window.h └── win32-dlls │ ├── libeay32.dll │ └── ssleay32.dll ├── common ├── CMakeLists.txt ├── resources │ ├── common.qrc │ ├── map.schema.json │ ├── room-presets-legacy.json │ ├── room-presets.json │ └── room-presets.schema.json └── src │ ├── controller │ ├── labyrinthcontroller.cpp │ ├── labyrinthcontroller.h │ ├── navigationcontroller.cpp │ └── navigationcontroller.h │ ├── global.h │ ├── helper │ ├── directionnormalizer.cpp │ ├── directionnormalizer.h │ ├── roompresethelper.cpp │ └── roompresethelper.h │ ├── model │ ├── applicationmodel.cpp │ ├── applicationmodel.h │ ├── connectionmodel.cpp │ ├── connectionmodel.h │ ├── goldendoormodel.cpp │ ├── goldendoormodel.h │ ├── instructionmodel.cpp │ ├── instructionmodel.h │ ├── labyrinthdata.cpp │ ├── labyrinthdata.h │ ├── labyrinthmodel.cpp │ ├── labyrinthmodel.h │ ├── listmodel.cpp │ ├── listmodel.h │ ├── navigationdata.cpp │ ├── navigationdata.h │ ├── plandata.cpp │ ├── plandata.h │ ├── plannedroutemodel.cpp │ ├── plannedroutemodel.h │ ├── plansummarymodel.cpp │ ├── plansummarymodel.h │ ├── roommodel.cpp │ ├── roommodel.h │ ├── roompresetmodel.cpp │ └── roompresetmodel.h │ ├── settings.cpp │ ├── settings.h │ ├── stdafx.h │ └── worker │ ├── datechecker.cpp │ ├── datechecker.h │ ├── logwatcher.cpp │ ├── logwatcher.h │ ├── versionchecker.cpp │ └── versionchecker.h ├── logsimulator ├── CMakeLists.txt └── src │ ├── application.cpp │ ├── application.h │ ├── main.cpp │ ├── stdafx.h │ ├── widget.cpp │ ├── widget.h │ └── widget.ui ├── tests ├── CMakeLists.txt ├── data │ ├── 2018-01-09_cruel.jpg │ ├── 2018-01-09_cruel.json │ ├── 2018-01-09_merciless.jpg │ ├── 2018-01-09_merciless.json │ ├── 2018-01-09_normal.jpg │ ├── 2018-01-09_normal.json │ ├── 2018-01-09_uber.jpg │ ├── 2018-01-09_uber.json │ ├── 2018-01-10_cruel.jpg │ ├── 2018-01-10_cruel.json │ ├── 2018-01-10_merciless.jpg │ ├── 2018-01-10_merciless.json │ ├── 2018-01-10_normal.jpg │ ├── 2018-01-10_normal.json │ ├── 2018-01-10_uber.jpg │ └── 2018-01-10_uber.json └── src │ ├── main.cpp │ ├── navigation │ ├── navigationcontrollerwrapper.cpp │ └── navigationcontrollerwrapper.h │ └── tests │ ├── labyrinthdata │ ├── labyrinthdataloadtest.cpp │ ├── labyrinthdataloadtest.h │ ├── labyrinthdataroomistrialtest.cpp │ └── labyrinthdataroomistrialtest.h │ ├── labyrinthmodel │ ├── labyrinthmodelpropertiestest.cpp │ └── labyrinthmodelpropertiestest.h │ ├── testdataavailabletest.cpp │ └── testdataavailabletest.h └── vendor ├── HungarianAlgorithm ├── CMakeLists.txt ├── Hungarian.cpp ├── Hungarian.h ├── LICENSE └── README.txt ├── QHotkey ├── .github │ └── workflows │ │ └── build.yml ├── .gitignore ├── CMakeLists.txt ├── HotkeyTest │ ├── CMakeLists.txt │ ├── HotkeyTest.pro │ ├── hottestwidget.cpp │ ├── hottestwidget.h │ ├── hottestwidget.ui │ └── main.cpp ├── LICENSE ├── QHotkey.pro ├── QHotkey │ ├── QHotkey │ ├── QHotkey.pro │ ├── qhotkey.cpp │ ├── qhotkey.h │ ├── qhotkey.pri │ ├── qhotkey_mac.cpp │ ├── qhotkey_p.h │ ├── qhotkey_win.cpp │ └── qhotkey_x11.cpp ├── README.md ├── doc │ ├── Doxyfile │ └── qhotkey.dox ├── qhotkey.prc ├── qhotkey.pri ├── qpm.json └── qpmx.json ├── QtJsonSchema ├── CMakeLists.txt ├── include │ └── QtJsonSchema └── src │ ├── error │ ├── jsonschemavalidationerror.cpp │ └── jsonschemavalidationerror.h │ ├── hashfunctions.cpp │ ├── hashfunctions.h │ ├── jsonschema.cpp │ ├── jsonschema.h │ ├── jsonschema_p.h │ ├── jsonschemaversion.h │ ├── metaschema │ ├── draft04.h │ ├── draft06.h │ └── draft07.h │ ├── pointer │ ├── jsonpointer.cpp │ └── jsonpointer.h │ ├── reference-resolver │ ├── referenceresolver.cpp │ └── referenceresolver.h │ ├── utils.cpp │ ├── utils.h │ └── validator │ ├── jsonschemanodevalidator.cpp │ ├── jsonschemanodevalidator.h │ ├── jsonschemanodevalidator07.cpp │ └── jsonschemanodevalidator07.h └── QtSuperMacros ├── .gitignore ├── .gitlab-ci.yml ├── CMakeLists.txt ├── LICENSE.md ├── QQmlAutoPropertyHelpers.h ├── QQmlConstRefPropertyHelpers.h ├── QQmlEnumClassHelper.h ├── QQmlHelpers.cpp ├── QQmlHelpersCommon.h ├── QQmlListPropertyHelper.h ├── QQmlPtrPropertyHelpers.h ├── QQmlSingletonHelper.h ├── QQmlUniquePtrPropertyHelpers.h ├── QQmlVarPropertyHelpers.h ├── QtSuperMacros.pri ├── QtSuperMacros.pro ├── QtSuperMacros.qbs ├── README.md └── qtsupermacros.h /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.autosave 3 | 4 | *.qm 5 | 6 | \.DS_Store 7 | 8 | *.tmp 9 | 10 | *.user 11 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | project(LabCompass) 4 | 5 | set(CMAKE_AUTOMOC TRUE) 6 | set(CMAKE_AUTOUIC TRUE) 7 | set(CMAKE_AUTORCC TRUE) 8 | 9 | find_package(Qt5 REQUIRED 10 | Core 11 | Gui 12 | Widgets 13 | Network 14 | Qml 15 | QuickWidgets 16 | QuickControls2 17 | Test 18 | ) 19 | 20 | add_subdirectory(vendor/QtSuperMacros) 21 | add_subdirectory(vendor/HungarianAlgorithm) 22 | add_subdirectory(vendor/QtJsonSchema) 23 | add_subdirectory(vendor/QHotkey) 24 | 25 | add_subdirectory(common) 26 | 27 | add_subdirectory(app) 28 | add_subdirectory(logsimulator) 29 | add_subdirectory(tests) 30 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME app) 2 | 3 | file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS 4 | *.cpp *.h *.qrc 5 | ) 6 | 7 | add_executable(${TARGET_NAME} WIN32 ${SOURCES}) 8 | 9 | target_include_directories(${TARGET_NAME} PRIVATE 10 | src 11 | ) 12 | 13 | target_precompile_headers(${TARGET_NAME} PRIVATE 14 | src/stdafx.h 15 | ) 16 | 17 | target_link_libraries(${TARGET_NAME} PUBLIC 18 | common 19 | qhotkey 20 | ) 21 | -------------------------------------------------------------------------------- /app/resources/Fontin-SmallCaps.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/app/resources/Fontin-SmallCaps.ttf -------------------------------------------------------------------------------- /app/resources/LabCompass.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/app/resources/LabCompass.ico -------------------------------------------------------------------------------- /app/resources/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/app/resources/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /app/resources/images/browse.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/focus.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 55 | 56 | -------------------------------------------------------------------------------- /app/resources/images/instruction/backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_E.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_N.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_NE.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_NW.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_S.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_SE.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_SW.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_W.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/instruction/direction_unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/instruction/izaro-kill.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/instruction/izaro-wait.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/instruction/mechanics.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 55 | 56 | -------------------------------------------------------------------------------- /app/resources/images/instruction/opposite.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 55 | 56 | -------------------------------------------------------------------------------- /app/resources/images/instruction/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/lab-content/golden-door.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 55 | 56 | -------------------------------------------------------------------------------- /app/resources/images/map-marker-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/map-marker-orange.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/navigation-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/planner/map.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/images/rounded-corner.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 23 | 25 | image/svg+xml 26 | 28 | 29 | 30 | 31 | 32 | 34 | 54 | 59 | 60 | -------------------------------------------------------------------------------- /app/resources/images/star-gold.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/star-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 51 | 56 | 57 | -------------------------------------------------------------------------------- /app/resources/images/view-list-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /app/resources/ui/CircleProgressBar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import QtQuick.Controls 2.2 3 | import QtGraphicalEffects 1.0 4 | 5 | ProgressBar { 6 | id: root 7 | 8 | property real circleWidth: 4 9 | property color color: 'black' 10 | 11 | background: null 12 | 13 | contentItem: Item { 14 | 15 | Rectangle { 16 | id: ring 17 | anchors.fill: parent 18 | anchors.margins: border.width / 2 + 1 19 | radius: Math.max(width, height) / 2 20 | color: 'transparent' 21 | border.width: root.circleWidth 22 | visible: false 23 | } 24 | 25 | ConicalGradient { 26 | source: ring 27 | anchors.fill: parent 28 | gradient: Gradient { 29 | GradientStop { position: 0; color: root.color } 30 | GradientStop { position: root.value; color: root.color } 31 | GradientStop { position: root.value + 0.001; color: 'transparent' } 32 | GradientStop { position: 1; color: 'transparent' } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/resources/ui/DragMoveArea.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | 3 | MouseArea { 4 | id: root 5 | 6 | signal drag(int dx, int dy) 7 | 8 | property bool dragging: false 9 | property point clickPos 10 | 11 | cursorShape: dragging ? Qt.ClosedHandCursor : Qt.OpenHandCursor 12 | onPressed: { 13 | dragging = true; 14 | clickPos = Qt.point(mouse.x, mouse.y); 15 | } 16 | onReleased: { 17 | dragging = false; 18 | } 19 | onPositionChanged: { 20 | root.drag(mouse.x - clickPos.x, mouse.y - clickPos.y); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/resources/ui/Dummy.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | 3 | Item { 4 | width: 1 5 | height: 1 6 | } 7 | -------------------------------------------------------------------------------- /app/resources/ui/GlobalAccessor.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | QtObject { 5 | property QtObject o: Global 6 | } 7 | -------------------------------------------------------------------------------- /app/resources/ui/Header.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | Row { 5 | id: root 6 | spacing: 4 7 | 8 | signal drag(int dx, int dy) 9 | signal exit() 10 | 11 | Rectangle { 12 | height: 24 13 | width: 120 14 | color: Global.lightPrimaryColor 15 | Text { 16 | text: 'LabCompass' 17 | color: Global.primaryTextColor 18 | anchors.centerIn: parent 19 | } 20 | DragMoveArea { 21 | anchors.fill: parent 22 | onDrag: root.drag(dx, dy) 23 | } 24 | } 25 | 26 | ToolbarButton { 27 | source: 'qrc:/images/close.svg' 28 | onClicked: exit() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/resources/ui/HighlightTab.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import QtGraphicalEffects 1.0 3 | import com.labcompass 1.0 4 | 5 | Item { 6 | id: root 7 | 8 | signal itemClicked(int index) 9 | 10 | property int items 11 | property int currentItem 12 | 13 | property alias inactiveLayerComponent: inactiveLayerLoader.sourceComponent 14 | property alias activeLayerComponent: activeLayerLoader.sourceComponent 15 | 16 | Loader { 17 | id: inactiveLayerLoader 18 | anchors.fill: parent 19 | } 20 | 21 | Item { 22 | id: mask 23 | anchors.fill: parent 24 | Rectangle { 25 | id: rect 26 | anchors.top: parent.top 27 | anchors.bottom: parent.bottom 28 | x: root.width / items * currentItem 29 | width: root.width / items 30 | color: root.enabled ? Global.lightPrimaryColor : Global.primaryColor 31 | radius: 4 32 | border.width: 2 33 | border.color: Global.lightPrimaryColor 34 | 35 | Behavior on x { 36 | NumberAnimation { 37 | easing.type: Easing.Bezier 38 | easing.bezierCurve: [0.4, 0.0, 0.2, 1.0, 1.0, 1.0] 39 | duration: 150 40 | } 41 | } 42 | } 43 | } 44 | 45 | Loader { 46 | id: activeLayerLoader 47 | anchors.fill: parent 48 | visible: false 49 | } 50 | 51 | OpacityMask { 52 | anchors.fill: parent 53 | source: activeLayerLoader 54 | maskSource: mask 55 | } 56 | 57 | MouseArea { 58 | cursorShape: Qt.PointingHandCursor 59 | anchors.fill: parent 60 | onClicked: itemClicked(Math.floor(mouse.x * items / root.width)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/resources/ui/NotificationIndicator.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | 3 | Rectangle { 4 | property int size: 8 5 | property int margin: 4 6 | 7 | color: '#f44336' 8 | width: size 9 | height: size 10 | radius: size / 2 11 | anchors { 12 | top: parent.top 13 | right: parent.right 14 | topMargin: margin 15 | rightMargin: margin 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/resources/ui/RoomContentIcon.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import QtGraphicalEffects 1.0 3 | import com.labcompass 1.0 4 | 5 | Item { 6 | id: root 7 | 8 | property string content 9 | 10 | width: 16 11 | height: 16 12 | visible: String(icon.source) 13 | 14 | SvgImage { 15 | id: icon 16 | anchors.fill: parent 17 | source: content in Global.contentIconMapping ? 'qrc:/images/lab-content/' + Global.contentIconMapping[content] + '.svg' : '' 18 | } 19 | 20 | DropShadow { 21 | anchors.fill: parent 22 | source: icon 23 | verticalOffset: 1 24 | radius: 2.0 25 | samples: 8 26 | color: '#80000000' 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/resources/ui/RoomContentView.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | Row { 5 | id: root 6 | property var model 7 | 8 | spacing: 2 9 | 10 | Repeater { 11 | id: contentView 12 | model: root.model 13 | 14 | RoomContentIcon { 15 | content: modelData 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/resources/ui/StandardAnimation.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | 3 | NumberAnimation { 4 | easing.type: Easing.Bezier 5 | easing.bezierCurve: [0.4, 0.0, 0.2, 1.0, 1.0, 1.0] 6 | duration: 100 7 | } 8 | -------------------------------------------------------------------------------- /app/resources/ui/SvgImage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | 3 | Image { 4 | id: root 5 | width: String(source) ? 16 : 0 6 | height: String(source) ? 16 : 0 7 | sourceSize: String(source) ? Qt.size(width * 4, height * 4) : Qt.size(0, 0) 8 | mipmap: true 9 | asynchronous: true 10 | } 11 | -------------------------------------------------------------------------------- /app/resources/ui/TabLabel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | Item { 5 | id: root 6 | property alias text: text.text 7 | property bool active: true 8 | 9 | Text { 10 | id: text 11 | anchors.centerIn: parent 12 | font.pixelSize: 16 13 | color: root.active ? Global.primaryTextColor : Global.secondaryTextColor 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/resources/ui/TextHighlightTab.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | 3 | HighlightTab { 4 | id: root 5 | 6 | property var model: [] 7 | 8 | items: model.length ? model.length : 1 9 | onItemClicked: currentItem = index 10 | 11 | activeLayerComponent: Row { 12 | Repeater { 13 | model: root.model 14 | TabLabel { 15 | width: root.width / root.items 16 | height: root.height 17 | active: true 18 | text: modelData 19 | } 20 | } 21 | } 22 | 23 | inactiveLayerComponent: Row { 24 | Repeater { 25 | model: root.model 26 | TabLabel { 27 | width: root.width / root.items 28 | height: root.height 29 | active: false 30 | text: modelData 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/resources/ui/Toolbar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | Column { 5 | id: root 6 | spacing: 4 7 | 8 | ToolbarButton { 9 | height: 40 10 | source: 'qrc:/images/navigation-light.svg' 11 | active: Global && Global.plannerWindowOpen 12 | onClicked: { 13 | if (Global) { 14 | var open = Global.plannerWindowOpen; 15 | closeAllWindows(); 16 | if (!open) 17 | Global.plannerWindowOpen = true; 18 | } 19 | } 20 | NotificationIndicator { 21 | visible: !Global.loadedMapUpToDate 22 | } 23 | } 24 | 25 | ToolbarButton { 26 | height: 40 27 | source: 'qrc:/images/puzzle-light.svg' 28 | active: Global && Global.puzzleWindowOpen 29 | onClicked: { 30 | if (Global) { 31 | var open = Global.puzzleWindowOpen; 32 | closeAllWindows(); 33 | if (!open) 34 | Global.puzzleWindowOpen = true; 35 | } 36 | } 37 | } 38 | 39 | ToolbarButton { 40 | height: 40 41 | source: 'qrc:/images/settings-light.svg' 42 | active: Global && Global.optionsWindowOpen 43 | onClicked: { 44 | if (Global) { 45 | var open = Global.optionsWindowOpen; 46 | closeAllWindows(); 47 | if (!open) 48 | Global.optionsWindowOpen = true; 49 | } 50 | } 51 | NotificationIndicator { 52 | visible: Global.model.newVersionAvailable 53 | } 54 | } 55 | 56 | function closeAllWindows() { 57 | Global.plannerWindowOpen = false; 58 | Global.puzzleWindowOpen = false; 59 | Global.optionsWindowOpen = false; 60 | Global.roomPresetsWindowOpen = false; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/resources/ui/ToolbarButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | Rectangle { 5 | id: root 6 | property string source 7 | property bool active 8 | signal clicked() 9 | 10 | height: 24 11 | width: 24 12 | color: active ? Global.lightPrimaryColor : Global.backgroundColor 13 | SvgImage { 14 | source: root.source 15 | anchors.centerIn: parent 16 | } 17 | MaterialInk { 18 | anchors.fill: parent 19 | onClicked: root.clicked() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/resources/ui/TooltipHoverArea.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | MouseArea { 5 | id: root 6 | property bool shouldDisplayTooltip: false 7 | hoverEnabled: true 8 | 9 | onContainsMouseChanged: { 10 | if (containsMouse) { 11 | exitTimer.stop(); 12 | if (Global.lastActiveTooltipHoverArea && Global.lastActiveTooltipHoverArea.shouldDisplayTooltip) { 13 | Global.lastActiveTooltipHoverArea.shouldDisplayTooltip = false; 14 | shouldDisplayTooltip = true; 15 | Global.lastActiveTooltipHoverArea = root; 16 | } else { 17 | enterTimer.restart(); 18 | } 19 | } else { 20 | enterTimer.stop(); 21 | exitTimer.restart(); 22 | } 23 | } 24 | onPressed: { 25 | enterTimer.stop(); 26 | shouldDisplayTooltip = false; 27 | mouse.accepted = false; 28 | } 29 | 30 | Timer { 31 | id: enterTimer 32 | interval: 800 33 | onTriggered: { 34 | shouldDisplayTooltip = true; 35 | Global.lastActiveTooltipHoverArea = root; 36 | } 37 | } 38 | Timer { 39 | id: exitTimer 40 | interval: 300 41 | onTriggered: { 42 | shouldDisplayTooltip = false; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/resources/ui/WindowWithShadow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import QtGraphicalEffects 1.0 3 | import com.labcompass 1.0 4 | 5 | Item { 6 | id: root 7 | width: contents.width + 20 8 | height: contents.height + 20 9 | 10 | default property alias content: contents.children 11 | property var root: contents 12 | 13 | RectangularGlow { 14 | x: 10 15 | y: 13 16 | width: contents.width 17 | height: contents.height 18 | glowRadius: 3 19 | spread: 0.0 20 | color: Qt.rgba(0, 0, 0, 0.8) 21 | cornerRadius: glowRadius 22 | } 23 | 24 | Item { 25 | id: contents 26 | x: 10 27 | y: 10 28 | width: childrenRect.x + childrenRect.width 29 | height: childrenRect.y + childrenRect.height 30 | 31 | Rectangle { 32 | anchors.fill: parent 33 | color: Global.backgroundColor 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/resources/ui/compass/CompassToolbar.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '..' 4 | 5 | ToolbarButton { 6 | id: root 7 | 8 | width: 24 9 | height: 24 10 | source: 'qrc:/images/view-list-light.svg' 11 | active: Global && Global.roomPresetsWindowOpen 12 | onClicked: { 13 | if (Global) { 14 | var open = Global.roomPresetsWindowOpen; 15 | closeAllWindows(); 16 | if (!open) 17 | Global.roomPresetsWindowOpen = true; 18 | } 19 | } 20 | 21 | function closeAllWindows() { 22 | Global.plannerWindowOpen = false; 23 | Global.puzzleWindowOpen = false; 24 | Global.optionsWindowOpen = false; 25 | Global.roomPresetsWindowOpen = false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/resources/ui/compass/DirectionDisplay.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '..' 4 | 5 | Item { 6 | id: root 7 | property var instructionModel 8 | 9 | Item { 10 | anchors.centerIn: parent 11 | 12 | Repeater { 13 | id: exitDirectionView 14 | model: instructionModel.doorExitLocations 15 | anchors.centerIn: parent 16 | 17 | Rectangle { 18 | x: Global.directionMapping[modelData.direction].dx * 48 - width / 2 19 | y: Global.directionMapping[modelData.direction].dy * 48 - height / 2 20 | width: 16 21 | height: 16 22 | radius: 8 23 | color: modelData.direction === instructionModel.nextRoomDirection ? Global.activePathColor : '#909090' 24 | border { 25 | width: 1 26 | color: 'black' 27 | } 28 | } 29 | } 30 | 31 | Repeater { 32 | id: contentLocationsView 33 | model: instructionModel.contentLocations 34 | 35 | Rectangle { 36 | x: Global.directionMapping[modelData.direction].dx * 30 - width / 2 37 | y: Global.directionMapping[modelData.direction].dy * 30 - height / 2 38 | width: 8 39 | height: 8 40 | rotation: 45 41 | color: instructionModel.nextRoomConnectionType === 'secret' && !modelData.major ? Global.activePathColor : '#FFA726' 42 | border { 43 | width: 1 44 | color: 'black' 45 | } 46 | } 47 | } 48 | 49 | RoomContentView { 50 | anchors.centerIn: parent 51 | model: instructionModel.roomLoot 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/resources/ui/compass/MinimapDisplay.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '../point.js' as Point 4 | import '..' 5 | 6 | Item { 7 | id: root 8 | property var instructionModel 9 | 10 | SvgImage { 11 | anchors.fill: parent 12 | source: 'qrc:/images/room-preset/' + instructionModel.preset.areaCode + '.svg' 13 | } 14 | 15 | Repeater { 16 | id: exitDirectionView 17 | model: instructionModel.doorExitLocations 18 | 19 | SvgImage { 20 | x: modelData.tileRect.x * root.width 21 | y: modelData.tileRect.y * root.height 22 | width: modelData.tileRect.width * root.width 23 | height: modelData.tileRect.height * root.height 24 | source: modelData.direction === instructionModel.nextRoomDirection ? 'qrc:/images/compass/door-target.svg' 25 | : 'qrc:/images/compass/door-normal.svg' 26 | } 27 | } 28 | 29 | Repeater { 30 | id: contentLocationsView 31 | model: instructionModel.contentLocations 32 | 33 | SvgImage { 34 | x: modelData.tileRect.x * root.width 35 | y: modelData.tileRect.y * root.height 36 | width: modelData.tileRect.width * root.width 37 | height: modelData.tileRect.height * root.height 38 | source: instructionModel.nextRoomConnectionType === 'secret' && !modelData.major ? 'qrc:/images/compass/loot-target.svg' 39 | : 'qrc:/images/compass/loot-normal.svg' 40 | } 41 | } 42 | 43 | Item { 44 | width: 36 45 | height: 16 46 | anchors.bottom: parent.bottom 47 | 48 | RoomContentView { 49 | anchors.centerIn: parent 50 | model: instructionModel.roomLoot 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/resources/ui/instruction/DirectionInstructionItem.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | InstructionItem { 5 | id: root 6 | 7 | property string connectionType 8 | property string direction 9 | property string nextRoomName 10 | property bool atPlaza 11 | property bool nextRoomIsPreviousRoom 12 | property bool nextRoomIsUnmarkedOppositeDirection 13 | 14 | iconSource: connectionType == 'secret' ? 'qrc:/images/instruction/secret-passage.svg' : 15 | direction in Global.directionMapping ? 'qrc:/images/instruction/direction_' + direction + '.svg' : 16 | nextRoomIsPreviousRoom ? 'qrc:/images/instruction/backward.svg' : 17 | nextRoomIsUnmarkedOppositeDirection ? 'qrc:/images/instruction/opposite.svg' : 18 | 'qrc:/images/instruction/direction_unknown.svg' 19 | 20 | Text { 21 | visible: atPlaza 22 | color: Global.primaryTextColor 23 | text: 'Enter the Labyrinth' 24 | } 25 | 26 | Text { 27 | visible: !atPlaza 28 | color: Global.primaryTextColor 29 | text: nextRoomIsPreviousRoom ? 'Back to Previous Room' : 30 | direction in Global.directionMapping ? Global.directionMapping[direction].name + ' Exit' : 31 | connectionType == 'secret' ? 'Secret Passage' : 32 | nextRoomIsUnmarkedOppositeDirection ? 'Opposite Exit' : 33 | 'Unmarked Exit' 34 | } 35 | 36 | Text { 37 | visible: !atPlaza 38 | color: Global.primaryTextColor 39 | text: (nextRoomIsPreviousRoom ? '' : 'To ') + nextRoomName 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/resources/ui/instruction/InstructionItem.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import '..' 3 | 4 | Item { 5 | id: root 6 | 7 | property color color 8 | property url iconSource 9 | property alias iconComponent: iconComponentLoader.sourceComponent 10 | default property alias content: column.children 11 | 12 | width: 260 13 | height: background.height + 8 14 | 15 | Rectangle { 16 | id: background 17 | color: root.color 18 | width: root.width 19 | height: Math.max(40, column.height + 12) 20 | opacity: 0.75 21 | } 22 | SvgImage { 23 | id: icon 24 | source: root.iconSource 25 | anchors.verticalCenter: background.verticalCenter 26 | x: (40 - width) / 2 27 | width: 20 28 | height: 20 29 | } 30 | Column { 31 | id: column 32 | x: 40 33 | anchors.verticalCenter: background.verticalCenter 34 | width: root.width - 40 35 | spacing: 4 36 | } 37 | 38 | Loader { 39 | id: iconComponentLoader 40 | anchors.centerIn: icon 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/resources/ui/instruction/LoadedMapInstructionItem.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '..' 4 | 5 | InstructionItem { 6 | id: root 7 | 8 | property var model 9 | 10 | property string name: model ? model.title : '' 11 | property string difficulty: model ? model.difficulty : '' 12 | 13 | iconSource: { 14 | return { 15 | 'Normal': 'qrc:/images/instruction/loaded-map-normal.svg', 16 | 'Cruel': 'qrc:/images/instruction/loaded-map-cruel.svg', 17 | 'Merciless': 'qrc:/images/instruction/loaded-map-merciless.svg', 18 | 'Uber': 'qrc:/images/instruction/loaded-map-uber.svg', 19 | '': '' 20 | }[difficulty]; 21 | } 22 | 23 | Text { 24 | color: Global.primaryTextColor 25 | text: 'Loaded Map:' 26 | } 27 | Text { 28 | color: Global.primaryTextColor 29 | text: name 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/resources/ui/instruction/LootInstructionItem.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '..' 4 | 5 | InstructionItem { 6 | id: root 7 | 8 | property alias model: lootView.model 9 | 10 | iconSource: 'qrc:/images/instruction/loot.svg' 11 | 12 | Text { 13 | color: Global.primaryTextColor 14 | text: 'Loot:' 15 | } 16 | 17 | Repeater { 18 | id: lootView 19 | 20 | Grid { 21 | columns: 2 22 | spacing: 4 23 | verticalItemAlignment: Grid.AlignVCenter 24 | 25 | SvgImage { 26 | source: modelData in Global.contentIconMapping ? 'qrc:/images/lab-content/' + Global.contentIconMapping[modelData] + '.svg' : '' 27 | width: 16 28 | height: 16 29 | } 30 | 31 | Text { 32 | color: Global.primaryTextColor 33 | text: modelData in Global.nameMapping ? Global.nameMapping[modelData] : modelData 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/resources/ui/instruction/WarningInstructionItem.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | 4 | InstructionItem { 5 | id: root 6 | 7 | property string text 8 | 9 | color: '#D32F2F' 10 | iconSource: 'qrc:/images/instruction/warning.svg' 11 | 12 | Text { 13 | width: parent.width 14 | wrapMode: Text.WordWrap 15 | text: root.text 16 | color: Global.primaryTextColor 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/resources/ui/options/KeySequenceEdit.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Controls.Material 2.1 4 | import QtQuick.Layouts 1.3 5 | import com.labcompass 1.0 6 | 7 | Button { 8 | id: root 9 | 10 | Layout.minimumWidth: 200 11 | 12 | property alias modifierlessAllowed: helper.modifierlessAllowed 13 | property alias multiKeyShortcutsAllowed: helper.multiKeyShortcutsAllowed 14 | property alias keySequence: helper.keySequence 15 | 16 | KeySequenceHelper { 17 | id: helper 18 | multiKeyShortcutsAllowed: false 19 | modifierlessAllowed: true 20 | onCaptureFinished: focus = false; 21 | } 22 | 23 | checkable: true 24 | focus: checked 25 | text: helper.shortcutDisplay 26 | 27 | onClicked: { 28 | if (!checked) { 29 | helper.cancelRecording(); 30 | } 31 | } 32 | 33 | onCheckedChanged: { 34 | if (checked) { 35 | forceActiveFocus(); 36 | helper.captureKeySequence(); 37 | } 38 | } 39 | 40 | onFocusChanged: { 41 | if (!focus) { 42 | checked = false; 43 | } 44 | } 45 | 46 | Keys.onPressed: { 47 | helper.keyPressed(event.key, event.modifiers); 48 | event.accepted = true; 49 | } 50 | Keys.onReleased: { 51 | helper.keyReleased(event.key, event.modifiers); 52 | event.accepted = true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/resources/ui/options/OptionsGridLayout.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import QtQuick.Layouts 1.3 3 | 4 | GridLayout { 5 | columns: 2 6 | columnSpacing: 10 7 | anchors.fill: parent 8 | } 9 | -------------------------------------------------------------------------------- /app/resources/ui/planner/MapDropArea.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import '..' 3 | 4 | Item { 5 | id: root 6 | 7 | signal dropUrl(url url) 8 | 9 | property bool downloadInProgress: false 10 | 11 | DropArea { 12 | id: dropArea 13 | anchors.fill: parent 14 | keys: ['text/uri-list'] 15 | 16 | onDropped: { 17 | if (drop.hasUrls) { 18 | root.dropUrl(drop.urls[0]); 19 | drop.acceptProposedAction(); 20 | } 21 | } 22 | } 23 | 24 | Rectangle { 25 | opacity: downloadInProgress || dropArea.containsDrag ? 1 : 0 26 | anchors.fill: parent 27 | color: Qt.rgba(0, 0, 0, 0.5) 28 | 29 | Behavior on opacity { StandardAnimation { duration: 200 } } 30 | } 31 | 32 | Rectangle { 33 | visible: dropArea.containsDrag 34 | anchors.centerIn: parent 35 | width: dropArea.containsDrag ? 200 : 0 36 | height: width 37 | radius: 36 38 | color: '#03A9F4' 39 | clip: true 40 | 41 | Behavior on width { StandardAnimation { duration: 200 } } 42 | 43 | SvgImage { 44 | anchors.centerIn: parent 45 | width: 200 46 | height: 200 47 | source: 'qrc:/images/planner/drop-area-border.svg' 48 | } 49 | 50 | Grid { 51 | anchors.centerIn: parent 52 | columns: 1 53 | horizontalItemAlignment: Grid.AlignHCenter 54 | 55 | SvgImage { 56 | width: 64 57 | height: 64 58 | source: 'qrc:/images/planner/map.svg' 59 | } 60 | 61 | Item { 62 | width: 1 63 | height: dropArea.containsDrag ? 10 : 50 64 | Behavior on height { StandardAnimation { duration: 200 } } 65 | } 66 | 67 | Text { 68 | color: Global.primaryTextColor 69 | text: 'Drop to Import' 70 | font.pixelSize: 16 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/resources/ui/planner/PlanSummaryDisplay.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import '..' 3 | 4 | Rectangle { 5 | id: root 6 | property var model 7 | 8 | Grid { 9 | anchors.horizontalCenter: parent.horizontalCenter 10 | horizontalItemAlignment: Grid.AlignHCenter 11 | padding: 10 12 | spacing: 16 13 | columns: 1 14 | Text { 15 | text: 'Plan Summary' 16 | font.pixelSize: 26 17 | color: Global.primaryTextColor 18 | } 19 | Grid { 20 | rowSpacing: 12 21 | columnSpacing: 30 22 | columns: 2 23 | verticalItemAlignment: Grid.AlignVCenter 24 | Text { color: Global.primaryTextColor; text: 'Rooms' } 25 | Text { color: Global.primaryTextColor; width: 30; horizontalAlignment: Text.AlignHCenter; text: model.rooms } 26 | Text { color: Global.primaryTextColor; text: 'Length' } 27 | Text { color: Global.primaryTextColor; width: 30; horizontalAlignment: Text.AlignHCenter; text: model.length } 28 | Row { 29 | spacing: 4 30 | SvgImage { source: 'qrc:/images/lab-content/argus.svg' } 31 | Text { color: Global.primaryTextColor; text: 'Argus' } 32 | } 33 | Text { color: Global.primaryTextColor; width: 30; horizontalAlignment: Text.AlignHCenter; text: model.argus } 34 | Row { 35 | spacing: 4 36 | SvgImage { source: 'qrc:/images/lab-content/gauntlet-puzzle.svg' } 37 | Text { color: Global.primaryTextColor; text: 'Trove/Lockbox' } 38 | } 39 | Text { color: 'white'; width: 30; horizontalAlignment: Text.AlignHCenter; text: model.troves } 40 | Row { 41 | spacing: 4 42 | SvgImage { source: 'qrc:/images/lab-content/darkshrine.svg' } 43 | Text { color: Global.primaryTextColor; text: 'Darkshrine' } 44 | } 45 | Text { color: 'white'; width: 30; horizontalAlignment: Text.AlignHCenter; text: model.darkshrines } 46 | Row { 47 | spacing: 4 48 | SvgImage { source: 'qrc:/images/lab-content/silver-door.svg' } 49 | Text { color: Global.primaryTextColor; text: 'Silver Cache' } 50 | } 51 | Text { color: Global.primaryTextColor; width: 30; horizontalAlignment: Text.AlignHCenter; text: model.silverCaches } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/resources/ui/planner/PlannedRouteDisplay.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '..' 4 | 5 | Item { 6 | id: root 7 | 8 | property var plannedRouteModel 9 | 10 | Row { 11 | width: parent.width 12 | spacing: 4 13 | clip: true 14 | anchors.verticalCenter: parent.verticalCenter 15 | Text { 16 | anchors.verticalCenter: parent.verticalCenter 17 | text: 'Plan: ' 18 | color: Global.primaryTextColor 19 | font.pixelSize: 20 20 | } 21 | Repeater { 22 | id: planView 23 | model: root.plannedRouteModel 24 | Rectangle { 25 | width: 28 26 | height: 28 27 | color: Global.primaryColor 28 | Text { 29 | anchors.centerIn: parent 30 | text: model.id 31 | color: Global.primaryTextColor 32 | font.pixelSize: 16 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/resources/ui/planner/RoomClickModeSwitch.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import '..' 3 | 4 | HighlightTab { 5 | id: root 6 | 7 | width: 48 8 | height: 24 9 | items: 2 10 | currentItem: 0 11 | 12 | activeLayerComponent: Row { 13 | Item { 14 | width: 24 15 | height: 24 16 | SvgImage { 17 | anchors.centerIn: parent 18 | source: 'qrc:/images/star-gold.svg' 19 | } 20 | } 21 | Item { 22 | width: 24 23 | height: 24 24 | SvgImage { 25 | anchors.centerIn: parent 26 | source: 'qrc:/images/map-marker-orange.svg' 27 | } 28 | } 29 | } 30 | 31 | inactiveLayerComponent: Row { 32 | Item { 33 | width: 24 34 | height: 24 35 | SvgImage { 36 | anchors.centerIn: parent 37 | source: 'qrc:/images/star-light.svg' 38 | } 39 | } 40 | Item { 41 | width: 24 42 | height: 24 43 | SvgImage { 44 | anchors.centerIn: parent 45 | source: 'qrc:/images/map-marker-light.svg' 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/resources/ui/planner/RoomLabel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '..' 4 | 5 | Rectangle { 6 | property string roomName 7 | property var roomContents: [] 8 | 9 | x: -width / 2 + parent.width / 2 10 | y: -height - 36 + parent.height / 2 11 | width: grid.width 12 | height: grid.height 13 | color: Qt.rgba(0, 0, 0, 0.8) 14 | Grid { 15 | id: grid 16 | padding: 10 17 | spacing: 16 18 | columns: 1 19 | horizontalItemAlignment: Grid.AlignHCenter 20 | Text { 21 | color: Global.primaryTextColor 22 | text: roomName 23 | } 24 | Grid { 25 | spacing: 2 26 | columns: 1 27 | horizontalItemAlignment: Grid.AlignHCenter 28 | Repeater { 29 | model: roomContents 30 | Row { 31 | spacing: 2 32 | SvgImage { 33 | source: modelData in Global.contentIconMapping ? 'qrc:/images/lab-content/' + Global.contentIconMapping[modelData] + '.svg' : '' 34 | } 35 | Text { 36 | text: modelData in Global.nameMapping ? Global.nameMapping[modelData] : modelData 37 | color: Global.primaryTextColor 38 | font.pixelSize: 14 39 | } 40 | } 41 | } 42 | } 43 | } 44 | Rectangle { 45 | x: 10 46 | y: 36 47 | width: grid.width - 20 48 | height: 1 49 | color: Qt.lighter(Global.primaryColor) 50 | visible: roomContents.length 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/resources/ui/point.js: -------------------------------------------------------------------------------- 1 | .pragma library 2 | 3 | function add(p1, p2) { 4 | return Qt.point(p1.x + p2.x, p1.y + p2.y); 5 | } 6 | 7 | function subtract(p1, p2) { 8 | return Qt.point(p1.x - p2.x, p1.y - p2.y); 9 | } 10 | 11 | function negate(p) { 12 | return Qt.point(-p.x, -p.y); 13 | } 14 | 15 | function scale(p, scaling) { 16 | return Qt.point(p.x * scaling, p.y * scaling); 17 | } 18 | 19 | function distance(p1, p2) { 20 | return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); 21 | } 22 | 23 | function round(p) { 24 | return Qt.point(Math.round(p.x), Math.round(p.y)); 25 | } 26 | -------------------------------------------------------------------------------- /app/resources/ui/rect.js: -------------------------------------------------------------------------------- 1 | .pragma library 2 | 3 | function ltrb(left, top, right, bottom) { 4 | return Qt.rect(left, top, right - left, bottom - top); 5 | } 6 | 7 | function ltwh(left, top, width, height) { 8 | return Qt.rect(left, top, width, height); 9 | } 10 | 11 | function left(rect) { 12 | return rect.x; 13 | } 14 | 15 | function top(rect) { 16 | return rect.y; 17 | } 18 | 19 | function right(rect) { 20 | return rect.x + rect.width; 21 | } 22 | 23 | function bottom(rect) { 24 | return rect.y + rect.height; 25 | } 26 | 27 | function translate(rect, point) { 28 | return ltwh(rect.x + point.x, rect.y + point.y, rect.width, rect.height); 29 | } 30 | 31 | function center(rect) { 32 | return Qt.point(rect.x + rect.width / 2, rect.y + rect.height / 2); 33 | } 34 | 35 | function topLeft(rect) { 36 | return Qt.point(rect.left, rect.top); 37 | } 38 | 39 | function topRight(rect) { 40 | return Qt.point(rect.right, rect.top); 41 | } 42 | 43 | function bottomLeft(rect) { 44 | return Qt.point(rect.left, rect.bottom); 45 | } 46 | 47 | function bottomRight(rect) { 48 | return Qt.point(rect.right, rect.bottom); 49 | } 50 | 51 | function contains(rect, p1, p2) { 52 | if (p2 !== undefined) { 53 | return p1 >= rect.x && p1 <= rect.x + rect.width && 54 | p2 >= rect.y && p2 <= rect.y + rect.height; 55 | } else { 56 | return p1.x >= rect.x && p1.x <= rect.x + rect.width && 57 | p1.y >= rect.y && p1.y <= rect.y + rect.height; 58 | } 59 | } 60 | 61 | function pointDistance(p1, p2) { 62 | return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); 63 | } 64 | 65 | function boundingCircleRadius(rect, circlePos) { 66 | return Math.max(pointDistance(topLeft(rect), circlePos), 67 | pointDistance(topRight(rect), circlePos), 68 | pointDistance(bottomLeft(rect), circlePos), 69 | pointDistance(bottomRight(rect), circlePos)); 70 | } 71 | 72 | function boundingBox(item) { 73 | return Qt.rect(item.x, item.y, item.width, item.height) 74 | } 75 | -------------------------------------------------------------------------------- /app/resources/ui/roompresets/MinimapLegend.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '..' 4 | 5 | Item { 6 | id: root 7 | width: grid.width 8 | height: grid.height 9 | 10 | Rectangle { 11 | anchors.fill: parent 12 | color: Global.primaryColor 13 | } 14 | 15 | Grid { 16 | id: grid 17 | anchors.centerIn: parent 18 | columns: 1 19 | spacing: 16 20 | leftPadding: 20 21 | rightPadding: 20 22 | topPadding: 12 23 | bottomPadding: 12 24 | horizontalItemAlignment: Grid.AlignHCenter 25 | 26 | Text { 27 | font.pixelSize: 20 28 | color: Global.primaryTextColor 29 | text: 'Legend' 30 | } 31 | 32 | Grid { 33 | columns: 2 34 | horizontalItemAlignment: Grid.AlignHCenter 35 | verticalItemAlignment: Grid.AlignVCenter 36 | rowSpacing: 12 37 | columnSpacing: 20 38 | 39 | Row { 40 | spacing: 2 41 | SvgImage { width: 26; height: 20; source: 'qrc:/images/compass/tile-full.svg' } 42 | SvgImage { width: 26; height: 20; source: 'qrc:/images/compass/tile-cross.svg' } 43 | } 44 | Text { color: Global.primaryTextColor; text: 'Path' } 45 | 46 | SvgImage { width: 26; height: 20; source: 'qrc:/images/compass/tile-trap.svg' } 47 | Text { color: Global.primaryTextColor; text: 'Traps' } 48 | 49 | SvgImage { width: 26; height: 20; source: 'qrc:/images/compass/door-target.svg' } 50 | Text { color: Global.primaryTextColor; text: 'Exit' } 51 | 52 | SvgImage { width: 26; height: 20; source: 'qrc:/images/compass/loot-normal.svg' } 53 | Text { color: Global.primaryTextColor; text: 'Loot' } 54 | } 55 | } 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/resources/ui/roompresets/StaticMinimapDisplay.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.8 2 | import com.labcompass 1.0 3 | import '../point.js' as Point 4 | import '..' 5 | 6 | Item { 7 | id: root 8 | property var presetModel 9 | 10 | SvgImage { 11 | anchors.fill: parent 12 | source: presetModel && presetModel.areaCode ? 'qrc:/images/room-preset/' + presetModel.areaCode + '.svg' : '' 13 | } 14 | 15 | Repeater { 16 | id: exitDirectionView 17 | model: presetModel ? presetModel.doorExitLocations : [] 18 | 19 | SvgImage { 20 | x: modelData.tileRect.x * root.width 21 | y: modelData.tileRect.y * root.height 22 | width: modelData.tileRect.width * root.width 23 | height: modelData.tileRect.height * root.height 24 | source: 'qrc:/images/compass/door-target.svg' 25 | } 26 | } 27 | 28 | Repeater { 29 | id: contentLocationsView 30 | model: presetModel ? presetModel.contentLocations: [] 31 | 32 | SvgImage { 33 | x: modelData.tileRect.x * root.width 34 | y: modelData.tileRect.y * root.height 35 | width: modelData.tileRect.width * root.width 36 | height: modelData.tileRect.height * root.height 37 | source: 'qrc:/images/compass/loot-normal.svg' 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/hotkey/hotkeybinding.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "hotkeybinding.h" 4 | 5 | HotkeyBinding::HotkeyBinding(QObject* global, QObject* settings, QByteArray propertyName, QByteArray propertyChangeSignal) 6 | : QHotkey() 7 | { 8 | this->global = global; 9 | this->settings = settings; 10 | this->propertyName = propertyName; 11 | rebindHotkey(); 12 | 13 | connect(settings, propertyChangeSignal, 14 | this, SLOT(rebindHotkey())); 15 | connect(global, SIGNAL(optionsWindowOpenChanged()), 16 | this, SLOT(onOptionsWindowOpenChanged())); 17 | } 18 | 19 | void HotkeyBinding::rebindHotkey() 20 | { 21 | setRegistered(false); 22 | setShortcut(QKeySequence(settings->property(propertyName.toLatin1().constData()).toString())); 23 | setRegistered(true); 24 | } 25 | 26 | void HotkeyBinding::onOptionsWindowOpenChanged() 27 | { 28 | bool open = global->property("optionsWindowOpen").toBool(); 29 | setRegistered(!open); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/hotkey/hotkeybinding.h: -------------------------------------------------------------------------------- 1 | #ifndef HOTKEYBINDING_H 2 | #define HOTKEYBINDING_H 3 | 4 | #include 5 | 6 | class HotkeyBinding : public QHotkey { 7 | Q_OBJECT 8 | 9 | QObject* global; 10 | QObject* settings; 11 | QString propertyName; 12 | 13 | public: 14 | HotkeyBinding(QObject* global, QObject* settings, QByteArray propertyName, QByteArray propertyChangeSignal); 15 | 16 | private slots: 17 | void rebindHotkey(); 18 | void onOptionsWindowOpenChanged(); 19 | }; 20 | 21 | #endif // HOTKEYBINDING_H 22 | -------------------------------------------------------------------------------- /app/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "application.h" 4 | #include "global.h" 5 | #include "util/setupdebugoutput.h" 6 | 7 | int main(int argc, char** argv) 8 | { 9 | Q_INIT_RESOURCE(common); 10 | QApplication::setOrganizationName("FutureCode"); 11 | QApplication::setApplicationName("LabCompass"); 12 | 13 | setupDebugOutput(); 14 | qInfo() << "Operating System:" << QSysInfo::prettyProductName(); 15 | qInfo() << "LabCompass:" << VERSION; 16 | 17 | QSettings settings("FutureCode", "LabCompass"); 18 | const auto& scaleFactor = settings.value("scaleFactor", "1").toByteArray(); 19 | qputenv("QT_SCALE_FACTOR", scaleFactor); 20 | qInfo() << "Using scale factor:" << scaleFactor; 21 | 22 | qputenv("QML_DISABLE_DISK_CACHE", "1"); 23 | qputenv("QT_QUICK_CONTROLS_MATERIAL_THEME", "Dark"); 24 | qputenv("QT_QUICK_CONTROLS_MATERIAL_ACCENT", "#2196F3"); 25 | 26 | Application app(argc, argv); 27 | int r = app.exec(); 28 | qInfo() << "Exiting with code:" << r; 29 | return r; 30 | } 31 | -------------------------------------------------------------------------------- /app/src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef STDAFX_H 2 | #define STDAFX_H 3 | 4 | #include "qtsupermacros.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #endif // STDAFX_H 18 | -------------------------------------------------------------------------------- /app/src/tray/trayiconmenu.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "trayiconmenu.h" 4 | 5 | TrayIconMenu::TrayIconMenu() 6 | { 7 | addResetAction(); 8 | addQuitAction(); 9 | } 10 | 11 | void TrayIconMenu::addResetAction() 12 | { 13 | resetAction.reset(new QAction("Reset LabCompass")); 14 | addAction(resetAction.get()); 15 | 16 | connect(resetAction.get(), &QAction::triggered, []() { 17 | QSettings("FutureCode", "LabCompass").clear(); 18 | qApp->quit(); 19 | QProcess::startDetached(qApp->arguments()[0], qApp->arguments()); 20 | }); 21 | } 22 | 23 | void TrayIconMenu::addQuitAction() 24 | { 25 | quitAction.reset(new QAction("Quit")); 26 | addAction(quitAction.get()); 27 | 28 | connect(quitAction.get(), &QAction::triggered, 29 | []() { QCoreApplication::quit(); }); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/tray/trayiconmenu.h: -------------------------------------------------------------------------------- 1 | #ifndef TRAYICONMENU_H 2 | #define TRAYICONMENU_H 3 | 4 | class TrayIconMenu : public QMenu { 5 | std::unique_ptr resetAction; 6 | std::unique_ptr quitAction; 7 | 8 | public: 9 | TrayIconMenu(); 10 | 11 | private: 12 | void addResetAction(); 13 | void addQuitAction(); 14 | }; 15 | 16 | #endif // TRAYICONMENU_H 17 | -------------------------------------------------------------------------------- /app/src/util/setupdebugoutput.h: -------------------------------------------------------------------------------- 1 | #ifndef SETUPDEBUGOUTPUT_H 2 | #define SETUPDEBUGOUTPUT_H 3 | 4 | void setupDebugOutput(); 5 | 6 | #endif // SETUPDEBUGOUTPUT_H 7 | -------------------------------------------------------------------------------- /app/src/window/compasstoolbarwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "compasstoolbarwindow.h" 4 | 5 | CompassToolbarWindow::CompassToolbarWindow(QQmlEngine* engine) 6 | : Window(engine, false) 7 | { 8 | setSource(QUrl("qrc:/ui/compass/CompassToolbar.qml")); 9 | 10 | connect(global(), SIGNAL(compassToolbarVisibleChanged()), 11 | this, SLOT(onCompassToolbarVisibleChanged())); 12 | } 13 | 14 | void CompassToolbarWindow::onCompassToolbarVisibleChanged() 15 | { 16 | bool open = global()->property("compassToolbarVisible").toBool(); 17 | setVisible(open); 18 | } 19 | -------------------------------------------------------------------------------- /app/src/window/compasstoolbarwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPASSTOOLBARWINDOW_H 2 | #define COMPASSTOOLBARWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class CompassToolbarWindow : public Window { 7 | Q_OBJECT 8 | 9 | public: 10 | CompassToolbarWindow(QQmlEngine* engine); 11 | 12 | private slots: 13 | void onCompassToolbarVisibleChanged(); 14 | }; 15 | 16 | #endif // COMPASSTOOLBARWINDOW_H 17 | -------------------------------------------------------------------------------- /app/src/window/compasswindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "compasswindow.h" 4 | 5 | CompassWindow::CompassWindow(QQmlEngine* engine) 6 | : Window(engine, true) 7 | { 8 | setSource(QUrl("qrc:/ui/compass/Compass.qml")); 9 | 10 | connect(global(), SIGNAL(compassVisibleChanged()), 11 | this, SLOT(onCompassVisibleChanged())); 12 | } 13 | 14 | void CompassWindow::restartTimer() 15 | { 16 | QMetaObject::invokeMethod(rootObject(), "restartTimer"); 17 | } 18 | 19 | void CompassWindow::stopTimer() 20 | { 21 | QMetaObject::invokeMethod(rootObject(), "stopTimer"); 22 | } 23 | 24 | void CompassWindow::closeTimer() 25 | { 26 | QMetaObject::invokeMethod(rootObject(), "closeTimer"); 27 | } 28 | 29 | void CompassWindow::onCompassVisibleChanged() 30 | { 31 | bool visible = global()->property("compassVisible").toBool(); 32 | setVisible(visible); 33 | } 34 | -------------------------------------------------------------------------------- /app/src/window/compasswindow.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPASSWINDOW_H 2 | #define COMPASSWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class CompassWindow : public Window { 7 | Q_OBJECT 8 | 9 | public: 10 | CompassWindow(QQmlEngine* engine); 11 | 12 | public slots: 13 | void restartTimer(); 14 | void stopTimer(); 15 | void closeTimer(); 16 | 17 | private slots: 18 | void onCompassVisibleChanged(); 19 | }; 20 | 21 | #endif // COMPASSWINDOW_H 22 | -------------------------------------------------------------------------------- /app/src/window/headerwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "headerwindow.h" 4 | 5 | HeaderWindow::HeaderWindow(QQmlEngine* engine) 6 | : Window(engine, false) 7 | { 8 | setSource(QUrl("qrc:/ui/Header.qml")); 9 | 10 | connect(global(), SIGNAL(compassVisibleChanged()), 11 | this, SLOT(onCompassVisibleChanged())); 12 | connect(rootObject(), SIGNAL(drag(int, int)), 13 | this, SLOT(onDrag(int, int))); 14 | connect(rootObject(), SIGNAL(exit()), 15 | QCoreApplication::instance(), SLOT(quit())); 16 | } 17 | 18 | void HeaderWindow::onCompassVisibleChanged() 19 | { 20 | bool visible = global()->property("compassVisible").toBool(); 21 | setVisible(visible); 22 | } 23 | 24 | void HeaderWindow::onDrag(int dx, int dy) 25 | { 26 | move(x() + dx, y() + dy); 27 | emit moved(x(), y()); 28 | } 29 | -------------------------------------------------------------------------------- /app/src/window/headerwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef HEADERWINDOW_H 2 | #define HEADERWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class HeaderWindow : public Window { 7 | Q_OBJECT 8 | 9 | signals: 10 | void moved(int x, int y); 11 | 12 | public: 13 | HeaderWindow(QQmlEngine* engine); 14 | 15 | private slots: 16 | void onCompassVisibleChanged(); 17 | void onDrag(int dx, int dy); 18 | }; 19 | 20 | #endif // HEADERWINDOW_H 21 | -------------------------------------------------------------------------------- /app/src/window/instructionlistwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "instructionlistwindow.h" 4 | 5 | InstructionListWindow::InstructionListWindow(QQmlEngine* engine) 6 | : Window(engine, true) 7 | { 8 | setSource(QUrl("qrc:/ui/instruction/InstructionList.qml")); 9 | 10 | connect(global(), SIGNAL(compassVisibleChanged()), 11 | this, SLOT(onCompassVisibleChanged())); 12 | } 13 | 14 | void InstructionListWindow::onRoomChanged() 15 | { 16 | const auto& icon = rootObject()->findChild("izaroInstructionItemIcon"); 17 | if (icon) { 18 | icon->setProperty("state", ""); 19 | } 20 | } 21 | 22 | void InstructionListWindow::onIzaroBattleStarted() 23 | { 24 | const auto& icon = rootObject()->findChild("izaroInstructionItemIcon"); 25 | if (icon) { 26 | QMetaObject::invokeMethod(icon, "onIzaroBattleStarted"); 27 | } 28 | } 29 | 30 | void InstructionListWindow::onCompassVisibleChanged() 31 | { 32 | bool visible = global()->property("compassVisible").toBool(); 33 | setVisible(visible); 34 | } 35 | -------------------------------------------------------------------------------- /app/src/window/instructionlistwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef INSTRUCTIONLISTWINDOW_H 2 | #define INSTRUCTIONLISTWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class InstructionListWindow : public Window { 7 | Q_OBJECT 8 | 9 | public: 10 | InstructionListWindow(QQmlEngine* engine); 11 | 12 | public slots: 13 | void onRoomChanged(); 14 | void onIzaroBattleStarted(); 15 | 16 | private slots: 17 | void onCompassVisibleChanged(); 18 | }; 19 | 20 | #endif // INSTRUCTIONLISTWINDOW_H 21 | -------------------------------------------------------------------------------- /app/src/window/optionswindow.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTIONSWINDOW_H 2 | #define OPTIONSWINDOW_H 3 | 4 | #include "settings.h" 5 | #include "window/window.h" 6 | 7 | class OptionsWindow : public Window { 8 | Q_OBJECT 9 | 10 | Settings* settings; 11 | QStringList settingNames { 12 | "poeClientPath", 13 | "portalSkipsSection", 14 | "multiclientSupport", 15 | "showMinimap", 16 | "toggleHideUiHotkey", 17 | }; 18 | 19 | public: 20 | OptionsWindow(QQmlEngine* engine, Settings* settings); 21 | 22 | private slots: 23 | void onWindowOpenChanged(); 24 | void onBrowseClientPath(); 25 | void onOpenUrl(const QString& url); 26 | void load(); 27 | void save(); 28 | }; 29 | 30 | #endif // OPTIONSWINDOW_H 31 | -------------------------------------------------------------------------------- /app/src/window/plannerwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef PLANNERWINDOW_H 2 | #define PLANNERWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class PlannerWindow : public Window { 7 | Q_OBJECT 8 | 9 | signals: 10 | void importFile(QString fileName); 11 | void setRoomIsTarget(QString id, bool target); 12 | void setCurrentRoom(QString id); 13 | 14 | public: 15 | PlannerWindow(QQmlEngine* engine); 16 | 17 | private slots: 18 | void onWindowOpenChanged(); 19 | void onImportLabNotesFileClicked(); 20 | void onImportLabNotesFromUrl(const QUrl& url); 21 | void onOpenUrl(const QString& url); 22 | void onDrag(int dx, int dy); 23 | 24 | private: 25 | void importLabNotesFromFile(const QString& file); 26 | }; 27 | 28 | #endif // PLANNERWINDOW_H 29 | -------------------------------------------------------------------------------- /app/src/window/puzzlewindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "puzzlewindow.h" 4 | 5 | PuzzleWindow::PuzzleWindow(QQmlEngine* engine) 6 | : Window(engine, false) 7 | { 8 | setSource(QUrl("qrc:/ui/Puzzle.qml")); 9 | 10 | connect(global(), SIGNAL(puzzleWindowOpenChanged()), 11 | this, SLOT(onWindowOpenChanged())); 12 | } 13 | 14 | void PuzzleWindow::onWindowOpenChanged() 15 | { 16 | bool open = global()->property("puzzleWindowOpen").toBool(); 17 | setVisible(open); 18 | rootObject()->setProperty("switchModel", 0); 19 | rootObject()->setProperty("guideModel", 0); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/window/puzzlewindow.h: -------------------------------------------------------------------------------- 1 | #ifndef PUZZLEWINDOW_H 2 | #define PUZZLEWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class PuzzleWindow : public Window { 7 | Q_OBJECT 8 | 9 | public: 10 | PuzzleWindow(QQmlEngine* engine); 11 | 12 | private slots: 13 | void onWindowOpenChanged(); 14 | }; 15 | 16 | #endif // PUZZLEWINDOW_H 17 | -------------------------------------------------------------------------------- /app/src/window/roompresetswindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "roompresetswindow.h" 4 | 5 | RoomPresetsWindow::RoomPresetsWindow(QQmlEngine* engine) 6 | : Window(engine, false) 7 | { 8 | setSource(QUrl("qrc:/ui/roompresets/RoomPresets.qml")); 9 | 10 | roomPresetModel = global()->property("model").value()->property("roomPresetModel").value(); 11 | 12 | connect(rootObject(), SIGNAL(drag(int, int)), 13 | this, SLOT(onDrag(int, int))); 14 | connect(rootObject(), SIGNAL(applyPresetButtonClicked(QString)), 15 | this, SLOT(onApplyPresetButtonClicked(QString))); 16 | connect(global(), SIGNAL(roomPresetsWindowOpenChanged()), 17 | this, SLOT(onWindowOpenChanged())); 18 | connect(roomPresetModel, SIGNAL(presetsChanged(QVariantList)), 19 | this, SLOT(resetIndex())); 20 | } 21 | 22 | void RoomPresetsWindow::onWindowOpenChanged() 23 | { 24 | bool open = global()->property("roomPresetsWindowOpen").toBool(); 25 | setVisible(open); 26 | resetIndex(); 27 | } 28 | 29 | void RoomPresetsWindow::onDrag(int dx, int dy) 30 | { 31 | move(x() + dx, y() + dy); 32 | } 33 | 34 | void RoomPresetsWindow::onApplyPresetButtonClicked(const QString& areaCode) 35 | { 36 | const auto& roomId = roomPresetModel->property("roomId").toString(); 37 | emit setRoomPreset(roomId, areaCode); 38 | } 39 | 40 | void RoomPresetsWindow::resetIndex() 41 | { 42 | rootObject()->setProperty("presetListViewCurrentIndex", roomPresetModel->property("current").toInt()); 43 | } 44 | -------------------------------------------------------------------------------- /app/src/window/roompresetswindow.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOMPRESETSWINDOW_H 2 | #define ROOMPRESETSWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class RoomPresetsWindow : public Window { 7 | Q_OBJECT 8 | 9 | QObject* roomPresetModel; 10 | 11 | signals: 12 | void setRoomPreset(QString id, QString areaCode); 13 | 14 | public: 15 | RoomPresetsWindow(QQmlEngine* engine); 16 | 17 | private slots: 18 | void onWindowOpenChanged(); 19 | void onDrag(int dx, int dy); 20 | void onApplyPresetButtonClicked(const QString& areaCode); 21 | void resetIndex(); 22 | }; 23 | 24 | #endif // ROOMPRESETSWINDOW_H 25 | -------------------------------------------------------------------------------- /app/src/window/toolbarwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "toolbarwindow.h" 4 | 5 | ToolbarWindow::ToolbarWindow(QQmlEngine* engine) 6 | : Window(engine, false) 7 | { 8 | setSource(QUrl("qrc:/ui/Toolbar.qml")); 9 | 10 | connect(global(), SIGNAL(compassVisibleChanged()), 11 | this, SLOT(onCompassVisibleChanged())); 12 | } 13 | 14 | void ToolbarWindow::onCompassVisibleChanged() 15 | { 16 | bool visible = global()->property("compassVisible").toBool(); 17 | setVisible(visible); 18 | } 19 | -------------------------------------------------------------------------------- /app/src/window/toolbarwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef TOOLBARWINDOW_H 2 | #define TOOLBARWINDOW_H 3 | 4 | #include "window/window.h" 5 | 6 | class ToolbarWindow : public Window { 7 | Q_OBJECT 8 | 9 | public: 10 | ToolbarWindow(QQmlEngine* engine); 11 | 12 | private slots: 13 | void onCompassVisibleChanged(); 14 | }; 15 | 16 | #endif // TOOLBARWINDOW_H 17 | -------------------------------------------------------------------------------- /app/src/window/window.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "window.h" 4 | 5 | #ifdef Q_OS_WIN 6 | #include 7 | #endif 8 | 9 | Window::Window(QQmlEngine* engine, bool transparent, bool takeFocus, QWidget* parent) 10 | : QQuickWidget(engine, parent) 11 | { 12 | this->takeFocus = takeFocus; 13 | 14 | setClearColor(Qt::transparent); 15 | setAttribute(Qt::WA_NoSystemBackground); 16 | setAttribute(Qt::WA_TranslucentBackground); 17 | #if defined(Q_OS_LINUX) 18 | setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); 19 | #elif defined(Q_OS_MAC) 20 | setAttribute(Qt::WA_TransparentForMouseEvents, transparent); 21 | setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); 22 | #else 23 | setAttribute(Qt::WA_TransparentForMouseEvents, transparent); 24 | setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); 25 | #endif 26 | } 27 | 28 | void Window::setParentWindow(Window* parent, const QPoint& offset) 29 | { 30 | this->parentWindow = parent; 31 | this->parentOffset = offset; 32 | connect(parent->quickWindow(), &QQuickWindow::xChanged, 33 | this, &Window::repositionToParent); 34 | connect(parent->quickWindow(), &QQuickWindow::yChanged, 35 | this, &Window::repositionToParent); 36 | connect(quickWindow(), &QQuickWindow::visibleChanged, 37 | this, &Window::repositionToParent); 38 | } 39 | 40 | QObject* Window::global() 41 | { 42 | return dynamic_cast(engine())->rootObjects()[0]->property("o").value(); 43 | } 44 | 45 | void Window::showEvent(QShowEvent* e) 46 | { 47 | QQuickWidget::showEvent(e); 48 | 49 | #ifdef Q_OS_WIN 50 | if (!takeFocus) { 51 | HWND hwnd = (HWND)winId(); 52 | auto style = GetWindowLongW(hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE; 53 | SetWindowLongW(hwnd, GWL_EXSTYLE, style); 54 | } 55 | #endif 56 | } 57 | 58 | void Window::repositionToParent() 59 | { 60 | move(parentWindow->quickWindow()->x() + parentOffset.x(), 61 | parentWindow->quickWindow()->y() + parentOffset.y()); 62 | } 63 | -------------------------------------------------------------------------------- /app/src/window/window.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_H 2 | #define WINDOW_H 3 | 4 | class Window : public QQuickWidget { 5 | Q_OBJECT 6 | Window* parentWindow { nullptr }; 7 | QPoint parentOffset; 8 | 9 | protected: 10 | bool takeFocus; 11 | 12 | public: 13 | Window(QQmlEngine* engine, bool transparent = false, bool takeFocus = false, QWidget* parent = nullptr); 14 | void setParentWindow(Window* parent, const QPoint& offset); 15 | 16 | protected: 17 | QObject* global(); 18 | virtual void showEvent(QShowEvent* e); 19 | 20 | private slots: 21 | void repositionToParent(); 22 | }; 23 | 24 | #endif // WINDOW_H 25 | -------------------------------------------------------------------------------- /app/win32-dlls/libeay32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/app/win32-dlls/libeay32.dll -------------------------------------------------------------------------------- /app/win32-dlls/ssleay32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/app/win32-dlls/ssleay32.dll -------------------------------------------------------------------------------- /common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME common) 2 | 3 | file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS 4 | *.cpp *.h *.qrc 5 | ) 6 | 7 | add_library(${TARGET_NAME} ${SOURCES}) 8 | 9 | target_include_directories(${TARGET_NAME} PUBLIC 10 | src 11 | ) 12 | 13 | target_precompile_headers(${TARGET_NAME} PRIVATE 14 | src/stdafx.h 15 | ) 16 | 17 | target_link_libraries(${TARGET_NAME} PUBLIC 18 | QtSuperMacros 19 | HungarianAlgorithm 20 | QtJsonSchema 21 | Qt5::Core 22 | Qt5::Gui 23 | Qt5::Widgets 24 | Qt5::Network 25 | Qt5::Qml 26 | Qt5::QuickWidgets 27 | Qt5::QuickControls2 28 | ) 29 | -------------------------------------------------------------------------------- /common/resources/common.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | room-presets.json 4 | map.schema.json 5 | 6 | 7 | -------------------------------------------------------------------------------- /common/src/controller/labyrinthcontroller.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "labyrinthcontroller.h" 4 | 5 | LabyrinthController::LabyrinthController(ApplicationModel* model) 6 | { 7 | this->model = model; 8 | } 9 | 10 | void LabyrinthController::importFile(const QString& file) 11 | { 12 | qInfo() << "Import:" << file; 13 | 14 | if (model->loadFromFile(file)) { 15 | // update last loaded map date 16 | model->get_settings()->set_lastLoadedMapDate(model->labyrinthData.date); 17 | 18 | // copy the file to appdata directory 19 | const auto& appData = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); 20 | const auto& lastLoadedMap = appData.absoluteFilePath("lastLoaded.map"); 21 | appData.mkpath("."); 22 | if (QFileInfo(file) != QFileInfo(lastLoadedMap)) { 23 | QFile::remove(lastLoadedMap); 24 | QFile::copy(file, lastLoadedMap); 25 | } 26 | } 27 | } 28 | 29 | void LabyrinthController::onRoomPresetSet(const QString& id, const QString& areaCode) 30 | { 31 | auto& lab = model->labyrinthData; 32 | if (lab.roomIdIndex.contains(id)) { 33 | auto& room = lab.rooms[lab.roomIdIndex[id]]; 34 | room.areaCode = areaCode; 35 | 36 | lab.normalizeDoorDirections(id); 37 | 38 | model->updateModelOnPresetChange(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /common/src/controller/labyrinthcontroller.h: -------------------------------------------------------------------------------- 1 | #ifndef LABYRINTHCONTROLLER_H 2 | #define LABYRINTHCONTROLLER_H 3 | 4 | #include "model/applicationmodel.h" 5 | 6 | class LabyrinthController : public QObject { 7 | Q_OBJECT 8 | 9 | ApplicationModel* model; 10 | 11 | public: 12 | LabyrinthController(ApplicationModel* model); 13 | 14 | public slots: 15 | void importFile(const QString& file); 16 | void onRoomPresetSet(const QString& id, const QString& areaCode); 17 | }; 18 | 19 | #endif // LABYRINTHCONTROLLER_H 20 | -------------------------------------------------------------------------------- /common/src/controller/navigationcontroller.h: -------------------------------------------------------------------------------- 1 | #ifndef NAVIGATIONCONTROLLER_H 2 | #define NAVIGATIONCONTROLLER_H 3 | 4 | #include "model/applicationmodel.h" 5 | 6 | class NavigationController : public QObject { 7 | Q_OBJECT 8 | 9 | ApplicationModel* model; 10 | 11 | public: 12 | NavigationController(ApplicationModel* model); 13 | 14 | public slots: 15 | void onPlazaEntered(); 16 | void onLabStarted(); 17 | void onSectionFinished(); 18 | void onLabExit(); 19 | void onRoomChanged(const QString& name); 20 | void onPortalSpawned(); 21 | void onRoomIsTargetSet(const QString& id, bool isTarget); 22 | void onRoomIdSet(const QString& id); 23 | }; 24 | 25 | #endif // NAVIGATIONCONTROLLER_H 26 | -------------------------------------------------------------------------------- /common/src/global.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_H 2 | #define GLOBAL_H 3 | 4 | #include "stdafx.h" 5 | 6 | static const QString VERSION = "dev-version"; 7 | 8 | using RoomId = QString; 9 | using DirectionCode = QString; // [""(Unknown), "C"(Secret Passage), "N", "NE", "E", "SE", "S", "SW", "W", "NW"] 10 | using RoomConnections = QHash>; 11 | using ConnectionMatrix = QHash; 12 | 13 | using Preset = QVariantMap; 14 | using DoorExitLocationModel = QVariantList; // ["direction": string, "tileRect": rect] 15 | using ContentLocationModel = QVariantList; // ["direction": string, "major": bool, "tileRect": rect] 16 | 17 | #endif // GLOBAL_H 18 | -------------------------------------------------------------------------------- /common/src/helper/directionnormalizer.h: -------------------------------------------------------------------------------- 1 | #ifndef DIRECTIONNORMALIZER_H 2 | #define DIRECTIONNORMALIZER_H 3 | 4 | #include "Hungarian.h" 5 | #include "global.h" 6 | 7 | class DirectionNormalizer { 8 | struct ConnectionDetails { 9 | QList rooms; 10 | QList unknownDirectionRooms; 11 | QList secretPassageRooms; 12 | QList> regularDirectionRooms; 13 | }; 14 | 15 | HungarianAlgorithm hungarian; 16 | 17 | public: 18 | DirectionNormalizer(); 19 | 20 | RoomConnections normalize(const RoomConnections& original, const QList& pattern); 21 | 22 | private: 23 | ConnectionDetails breakdownConnections(const RoomConnections& connections); 24 | RoomConnections reconstructConnections(const ConnectionDetails& breakdown); 25 | qreal costBetweenDirections(const DirectionCode& d1, const DirectionCode& d2); 26 | }; 27 | 28 | #endif // DIRECTIONNORMALIZER_H 29 | -------------------------------------------------------------------------------- /common/src/helper/roompresethelper.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOMPRESETHELPER_H 2 | #define ROOMPRESETHELPER_H 3 | 4 | #include "global.h" 5 | 6 | class RoomPresetHelper { 7 | QHash cacheByAreaCode; // areaCode => preset 8 | QHash, QList>> cacheByNameAndGoldenDoor; // (name, goldenDoor) => [(areaCode, preset)] 9 | 10 | public: 11 | static RoomPresetHelper* instance; 12 | 13 | public: 14 | RoomPresetHelper(); 15 | 16 | Preset getPresetByAreaCode(const QString& areaCode) const; 17 | QList> getPresetListByName(const QString& roomName, bool goldenDoor) const; 18 | 19 | DoorExitLocationModel getDoorExitLocationModel(const Preset& preset) const; 20 | ContentLocationModel getContentLocationModel(const Preset& preset, bool generalLocations = true, bool majorLocations = true, bool minorLocations = true); 21 | 22 | private: 23 | QRectF getTileRect(const Preset& preset, const QString& direction) const; 24 | }; 25 | 26 | #endif // ROOMPRESETHELPER_H 27 | -------------------------------------------------------------------------------- /common/src/model/applicationmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef APPLICATIONMODEL_H 2 | #define APPLICATIONMODEL_H 3 | 4 | #include "model/connectionmodel.h" 5 | #include "model/goldendoormodel.h" 6 | #include "model/instructionmodel.h" 7 | #include "model/labyrinthdata.h" 8 | #include "model/labyrinthmodel.h" 9 | #include "model/navigationdata.h" 10 | #include "model/plandata.h" 11 | #include "model/plannedroutemodel.h" 12 | #include "model/plansummarymodel.h" 13 | #include "model/roommodel.h" 14 | #include "model/roompresetmodel.h" 15 | #include "settings.h" 16 | 17 | class ApplicationModel : public QObject { 18 | Q_OBJECT 19 | 20 | QML_READONLY_UNIQUEPTR_PROPERTY(Settings, settings) 21 | 22 | QML_READONLY_VAR_PROPERTY(bool, newVersionAvailable) 23 | QML_READONLY_CSTREF_PROPERTY(QDate, currentUtcDate) 24 | QML_READONLY_VAR_PROPERTY(bool, logFileOpen) 25 | QML_READONLY_VAR_PROPERTY(bool, atPlaza) 26 | QML_READONLY_VAR_PROPERTY(bool, inLab) 27 | QML_READONLY_VAR_PROPERTY(bool, currentRoomDetermined) 28 | QML_READONLY_VAR_PROPERTY(bool, isValid) 29 | 30 | QML_READONLY_UNIQUEPTR_PROPERTY(LabyrinthModel, labyrinthModel) 31 | QML_READONLY_UNIQUEPTR_PROPERTY(RoomModel, roomModel) 32 | QML_READONLY_UNIQUEPTR_PROPERTY(ConnectionModel, connectionModel) 33 | QML_READONLY_UNIQUEPTR_PROPERTY(GoldenDoorModel, goldenDoorModel) 34 | QML_READONLY_UNIQUEPTR_PROPERTY(PlannedRouteModel, plannedRouteModel) 35 | QML_READONLY_UNIQUEPTR_PROPERTY(InstructionModel, instructionModel) 36 | QML_READONLY_UNIQUEPTR_PROPERTY(PlanSummaryModel, planSummaryModel) 37 | QML_READONLY_UNIQUEPTR_PROPERTY(RoomPresetModel, roomPresetModel) 38 | 39 | public: 40 | LabyrinthData labyrinthData; 41 | PlanData planData; 42 | NavigationData navigationData; 43 | 44 | public: 45 | ApplicationModel(QObject* parent = nullptr); 46 | bool loadFromFile(const QString& file); 47 | void updatePlanData(const PlanData& planData); 48 | void updateNavigationData(const NavigationData& navigationData); 49 | void updateModelOnLoadFile(); 50 | void updateModelOnNavigation(); 51 | void updateModelOnPresetChange(); 52 | }; 53 | 54 | #endif // APPLICATIONMODEL_H 55 | -------------------------------------------------------------------------------- /common/src/model/connectionmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef CONNECTIONMODEL_H 2 | #define CONNECTIONMODEL_H 3 | 4 | #include "model/labyrinthdata.h" 5 | #include "model/listmodel.h" 6 | #include "model/navigationdata.h" 7 | 8 | struct ConnectionModelData { 9 | QString fromRoom; 10 | QString toRoom; 11 | QPoint fromCoordinate; 12 | QPoint toCoordinate; 13 | bool isSecretPassage { false }; 14 | bool isPlanned { false }; 15 | }; 16 | 17 | class ConnectionModel : public ListModel { 18 | Q_OBJECT 19 | 20 | QList d; 21 | enum Roles { 22 | FromCoordinateRole = Qt::UserRole + 1, 23 | ToCoordinateRole, 24 | IsSecretPassgeRole, 25 | IsPlannedRole, 26 | }; 27 | 28 | public: 29 | ConnectionModel(); 30 | void loadFromData(const LabyrinthData& data, const NavigationData& navigation); 31 | void updateFromData(const NavigationData& data); 32 | 33 | public: 34 | int rowCount(const QModelIndex& parent = QModelIndex()) const; 35 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; 36 | 37 | protected: 38 | QHash roleNames() const; 39 | }; 40 | 41 | #endif // CONNECTIONMODEL_H 42 | -------------------------------------------------------------------------------- /common/src/model/goldendoormodel.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "goldendoormodel.h" 4 | 5 | GoldenDoorModel::GoldenDoorModel(QObject* parent) 6 | : QAbstractListModel(parent) 7 | { 8 | } 9 | 10 | void GoldenDoorModel::loadFromData(const LabyrinthData& data) 11 | { 12 | beginResetModel(); 13 | 14 | d.clear(); 15 | foreach (auto& door, data.goldenDoors) { 16 | ModelData modelData; 17 | auto room1 = data.getRoomFromId(door.first); 18 | auto room2 = data.getRoomFromId(door.second); 19 | modelData.coordinate = (room1.coordinate + room2.coordinate) / 2; 20 | d.append(modelData); 21 | } 22 | 23 | endResetModel(); 24 | } 25 | 26 | int GoldenDoorModel::rowCount(const QModelIndex& parent) const 27 | { 28 | Q_UNUSED(parent) 29 | return d.size(); 30 | } 31 | 32 | QVariant GoldenDoorModel::data(const QModelIndex& index, int role) const 33 | { 34 | if (index.row() < 0 || index.row() >= rowCount()) 35 | return QVariant(); 36 | 37 | const auto& data = d[index.row()]; 38 | switch (role) { 39 | case CoordinateRole: 40 | return data.coordinate; 41 | default: 42 | return QVariant(); 43 | } 44 | } 45 | 46 | QHash GoldenDoorModel::roleNames() const 47 | { 48 | QHash roles; 49 | roles[CoordinateRole] = "coordinate"; 50 | return roles; 51 | } 52 | -------------------------------------------------------------------------------- /common/src/model/goldendoormodel.h: -------------------------------------------------------------------------------- 1 | #ifndef GOLDENDOORMODEL_H 2 | #define GOLDENDOORMODEL_H 3 | 4 | #include "model/labyrinthdata.h" 5 | 6 | class GoldenDoorModel : public QAbstractListModel { 7 | Q_OBJECT 8 | 9 | enum Roles { 10 | CoordinateRole = Qt::UserRole + 1, 11 | }; 12 | struct ModelData { 13 | QPoint coordinate; 14 | }; 15 | 16 | QList d; 17 | 18 | public: 19 | GoldenDoorModel(QObject* parent = nullptr); 20 | void loadFromData(const LabyrinthData& data); 21 | 22 | public: 23 | int rowCount(const QModelIndex& parent = QModelIndex()) const; 24 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; 25 | 26 | protected: 27 | QHash roleNames() const; 28 | }; 29 | 30 | #endif // GOLDENDOORMODEL_H 31 | -------------------------------------------------------------------------------- /common/src/model/instructionmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef INSTRUCTIONMODEL_H 2 | #define INSTRUCTIONMODEL_H 3 | 4 | #include "global.h" 5 | #include "model/navigationdata.h" 6 | 7 | class InstructionModel : public QObject { 8 | Q_OBJECT 9 | 10 | QML_READONLY_VAR_PROPERTY(QVariantMap, preset) // Preset 11 | QML_READONLY_VAR_PROPERTY(QStringList, roomLoot) 12 | QML_READONLY_VAR_PROPERTY(QVariantList, doorExitLocations) // DoorExitLocationModel 13 | QML_READONLY_VAR_PROPERTY(QVariantList, contentLocations) // ContentLocationModel 14 | QML_READONLY_VAR_PROPERTY(bool, roomHasPortal) 15 | 16 | QML_READONLY_VAR_PROPERTY(bool, hasNextRoom) 17 | QML_READONLY_VAR_PROPERTY(bool, atTrialRoom) 18 | QML_READONLY_VAR_PROPERTY(bool, nextRoomIsPreviousRoom) 19 | QML_READONLY_VAR_PROPERTY(bool, nextRoomIsUnmarkedOppositeDirection) 20 | QML_READONLY_VAR_PROPERTY(QString, nextRoomName) 21 | QML_READONLY_VAR_PROPERTY(QString, nextRoomConnectionType) // "none" | "door" | "secret" 22 | QML_READONLY_VAR_PROPERTY(QString, nextRoomDirection) 23 | 24 | QML_READONLY_VAR_PROPERTY(int, finishedSections) 25 | QML_READONLY_VAR_PROPERTY(int, currentSection) 26 | QML_READONLY_VAR_PROPERTY(bool, shouldKillIzaro) 27 | QML_READONLY_VAR_PROPERTY(QString, izaroMechanics) 28 | 29 | public: 30 | InstructionModel(QObject* parent = nullptr); 31 | void loadFromData(const NavigationData& data); 32 | 33 | private: 34 | void updateRoomPreset(const NavigationData& data); 35 | void updateExitLocations(const NavigationData& data); 36 | void updateContentsAndLocations(const NavigationData& data); 37 | 38 | QRectF getTileRect(const QString& direction, const QVariantMap& preset) const; 39 | }; 40 | 41 | #endif // INSTRUCTIONMODEL_H 42 | -------------------------------------------------------------------------------- /common/src/model/labyrinthdata.h: -------------------------------------------------------------------------------- 1 | #ifndef LABYRINTHDATA_H 2 | #define LABYRINTHDATA_H 3 | 4 | #include "global.h" 5 | 6 | struct LabyrinthData { 7 | struct Room { 8 | QString name; 9 | QString areaCode; 10 | RoomId id; 11 | QPoint coordinate; 12 | QStringList contents; 13 | int section; 14 | bool isFirstRoomInSection { false }; 15 | }; 16 | struct Section { 17 | QList roomIds; 18 | RoomId firstRoom; 19 | RoomId trialRoom; 20 | }; 21 | 22 | QString difficulty; 23 | QDate date; 24 | 25 | QString weapon; 26 | QString sectionMechanics[2]; 27 | QStringList traps; 28 | 29 | QList rooms; 30 | ConnectionMatrix connections; 31 | ConnectionMatrix normalizedConnections; 32 | Section sections[3]; 33 | QList> goldenDoors; 34 | 35 | QHash roomIdIndex; 36 | 37 | public: 38 | LabyrinthData(); 39 | bool loadFromFile(const QString& fileName); 40 | bool loadFromString(const QByteArray& str); 41 | bool loadFromJson(const QJsonObject& json); 42 | 43 | void normalizeDoorDirections(const RoomId& id); 44 | void normalizeDoorDirectionsForAllRooms(); 45 | 46 | Room getRoomFromId(const RoomId& id) const; 47 | bool hasConnection(const RoomId& from, const RoomId& to) const; 48 | bool hasDoorConnection(const RoomId& from, const RoomId& to) const; 49 | bool roomIsFirstRoomInSection(const RoomId& id) const; 50 | bool roomIsTrial(const RoomId& id) const; 51 | bool roomIsDeadEnd(const RoomId& id) const; 52 | bool roomHasSecretPassage(const RoomId& id) const; 53 | RoomConnections getRoomConnections(const RoomId& id) const; 54 | 55 | qreal roomCost(const RoomId& id) const; 56 | 57 | private: 58 | bool loadRooms(const QJsonArray& array); 59 | void predictRoomAreaCodes(); 60 | bool loadConnectionMatrix(const QJsonArray& array); 61 | bool loadSections(); 62 | bool loadGoldenDoors(); 63 | }; 64 | 65 | #endif // LABYRINTHDATA_H 66 | -------------------------------------------------------------------------------- /common/src/model/labyrinthmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "labyrinthdata.h" 4 | #include "labyrinthmodel.h" 5 | 6 | LabyrinthModel::LabyrinthModel(QObject* parent) 7 | : QObject(parent) 8 | { 9 | } 10 | 11 | void LabyrinthModel::loadFromData(const LabyrinthData& data) 12 | { 13 | update_title(data.date.toString("yyyy-MM-dd") + ' ' + data.difficulty); 14 | update_difficulty(data.difficulty); 15 | update_date(data.date); 16 | } 17 | -------------------------------------------------------------------------------- /common/src/model/labyrinthmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef LABYRINTHMODEL_H 2 | #define LABYRINTHMODEL_H 3 | 4 | #include "model/labyrinthdata.h" 5 | 6 | class LabyrinthModel : public QObject { 7 | Q_OBJECT 8 | 9 | QML_READONLY_VAR_PROPERTY(QString, title) 10 | 11 | QML_READONLY_VAR_PROPERTY(QString, difficulty) 12 | QML_READONLY_VAR_PROPERTY(QDate, date) 13 | 14 | public: 15 | LabyrinthModel(QObject* parent = nullptr); 16 | void loadFromData(const LabyrinthData& data); 17 | }; 18 | 19 | #endif // LABYRINTHMODEL_H 20 | -------------------------------------------------------------------------------- /common/src/model/listmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "listmodel.h" 4 | 5 | int ListModel::size() const 6 | { 7 | return rowCount(); 8 | } 9 | 10 | QVariantMap ListModel::get(int row) const 11 | { 12 | QHash names = roleNames(); 13 | QModelIndex idx = index(row, 0); 14 | QVariantMap r; 15 | 16 | for (auto i = names.constBegin(); i != names.constEnd(); i++) { 17 | auto data = idx.data(i.key()); 18 | r[i.value()] = data; 19 | } 20 | 21 | return r; 22 | } 23 | -------------------------------------------------------------------------------- /common/src/model/listmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef LISTMODEL_H 2 | #define LISTMODEL_H 3 | 4 | class ListModel : public QAbstractListModel { 5 | Q_OBJECT 6 | 7 | public: 8 | ListModel() { } 9 | ~ListModel() { } 10 | 11 | public: 12 | Q_INVOKABLE int size() const; 13 | Q_INVOKABLE QVariantMap get(int row) const; 14 | }; 15 | 16 | #endif // LISTMODEL_H 17 | -------------------------------------------------------------------------------- /common/src/model/navigationdata.h: -------------------------------------------------------------------------------- 1 | #ifndef NAVIGATIONDATA_H 2 | #define NAVIGATIONDATA_H 3 | 4 | #include "model/labyrinthdata.h" 5 | #include "model/plandata.h" 6 | 7 | struct NavigationData { 8 | struct ContentState { 9 | QList goldenKeyLocations; 10 | int goldenKeysInInventory { 0 }; 11 | QList> lockedDoors; 12 | 13 | QList portalLocations; 14 | }; 15 | 16 | const LabyrinthData* lab { nullptr }; 17 | 18 | bool currentRoomDetermined; 19 | RoomId currentRoom; 20 | QSet possibleCurrentRooms; 21 | RoomId previousRoom; 22 | 23 | ContentState contentState; 24 | 25 | QList targetRooms; 26 | QList plannedRoute; 27 | 28 | public: 29 | void loadFromData(const LabyrinthData* lab, const PlanData& plan); 30 | void updatePlannedRouteAndInstructions(); 31 | 32 | private: 33 | QList plannedRouteInsideSection(int section, const RoomId& begin, const RoomId& end, const QList& targetRooms, ContentState* tempGolden); 34 | static bool listContainsAll(const QStringList& l1, const QStringList& l2); 35 | }; 36 | 37 | #endif // NAVIGATIONDATA_H 38 | -------------------------------------------------------------------------------- /common/src/model/plandata.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "plandata.h" 4 | -------------------------------------------------------------------------------- /common/src/model/plandata.h: -------------------------------------------------------------------------------- 1 | #ifndef PLANDATA_H 2 | #define PLANDATA_H 3 | 4 | #include "global.h" 5 | 6 | struct PlanData { 7 | QList targetRooms; 8 | }; 9 | 10 | #endif // PLANDATA_H 11 | -------------------------------------------------------------------------------- /common/src/model/plannedroutemodel.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "plannedroutemodel.h" 4 | 5 | PlannedRouteModel::PlannedRouteModel() 6 | { 7 | } 8 | 9 | void PlannedRouteModel::loadFromData(const NavigationData& data) 10 | { 11 | beginResetModel(); 12 | 13 | d.clear(); 14 | foreach (auto& id, data.plannedRoute) { 15 | if (id != "plaza") { 16 | ModelData modelData; 17 | modelData.id = id; 18 | d.append(modelData); 19 | } 20 | } 21 | 22 | endResetModel(); 23 | } 24 | 25 | int PlannedRouteModel::rowCount(const QModelIndex& parent) const 26 | { 27 | Q_UNUSED(parent) 28 | return d.size(); 29 | } 30 | 31 | QVariant PlannedRouteModel::data(const QModelIndex& index, int role) const 32 | { 33 | if (index.row() < 0 || index.row() >= rowCount()) { 34 | return QVariant(); 35 | } 36 | 37 | const auto& data = d[index.row()]; 38 | switch (role) { 39 | case IdRole: 40 | return data.id; 41 | default: 42 | return QVariant(); 43 | } 44 | } 45 | 46 | QHash PlannedRouteModel::roleNames() const 47 | { 48 | QHash roles; 49 | roles[IdRole] = "id"; 50 | return roles; 51 | } 52 | -------------------------------------------------------------------------------- /common/src/model/plannedroutemodel.h: -------------------------------------------------------------------------------- 1 | #ifndef PLANNEDROUTEMODEL_H 2 | #define PLANNEDROUTEMODEL_H 3 | 4 | #include "model/navigationdata.h" 5 | 6 | class PlannedRouteModel : public QAbstractListModel { 7 | Q_OBJECT 8 | 9 | enum Roles { 10 | IdRole = Qt::UserRole + 1, 11 | }; 12 | struct ModelData { 13 | QString id; 14 | }; 15 | 16 | QList d; 17 | 18 | public: 19 | PlannedRouteModel(); 20 | void loadFromData(const NavigationData& data); 21 | 22 | public: 23 | int rowCount(const QModelIndex& parent = QModelIndex()) const; 24 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; 25 | 26 | protected: 27 | QHash roleNames() const; 28 | }; 29 | 30 | #endif // PLANNEDROUTEMODEL_H 31 | -------------------------------------------------------------------------------- /common/src/model/plansummarymodel.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "plansummarymodel.h" 4 | 5 | static const QStringList TROVE_LIST { 6 | "Switch puzzle", 7 | "Floor puzzle", 8 | "Escort gauntlet", 9 | "Trap gauntlet", 10 | }; 11 | 12 | PlanSummaryModel::PlanSummaryModel(QObject* parent) 13 | : QObject(parent) 14 | { 15 | m_rooms = 0; 16 | m_length = 0; 17 | m_argus = 0; 18 | m_troves = 0; 19 | m_darkshrines = 0; 20 | m_silverCaches = 0; 21 | } 22 | 23 | void PlanSummaryModel::loadFromData(const NavigationData& data) 24 | { 25 | QList rooms; 26 | int argus = 0; 27 | int troves = 0; 28 | int darkshrines = 0; 29 | int silverCaches = 0; 30 | int unusedSilverKeys = 0; 31 | 32 | for (const auto& roomId : data.plannedRoute) { 33 | if (roomId != "plaza" && !rooms.contains(roomId)) { 34 | rooms.append(roomId); 35 | } 36 | } 37 | 38 | for (const auto& roomId : rooms) { 39 | auto room = data.lab->getRoomFromId(roomId); 40 | 41 | for (const auto& content : room.contents) { 42 | if (content == "argus") 43 | argus += 1; 44 | if (content == "darkshrine") 45 | darkshrines += 1; 46 | if (content == "silver-key") 47 | unusedSilverKeys += 1; 48 | if (TROVE_LIST.contains(content)) 49 | troves += 1; 50 | } 51 | 52 | for (const auto& content : room.contents) { 53 | if (content == "silver-door" && unusedSilverKeys > 0) { 54 | silverCaches += 1; 55 | unusedSilverKeys -= 1; 56 | } 57 | } 58 | } 59 | 60 | update_rooms(rooms.size() - 3); // exclude 3 trial rooms 61 | update_length(data.plannedRoute.size() - 1); // exclude plaza 62 | update_argus(argus); 63 | update_troves(troves); 64 | update_darkshrines(darkshrines); 65 | update_silverCaches(silverCaches); 66 | } 67 | -------------------------------------------------------------------------------- /common/src/model/plansummarymodel.h: -------------------------------------------------------------------------------- 1 | #ifndef PLANSUMMARYMODEL_H 2 | #define PLANSUMMARYMODEL_H 3 | 4 | #include "model/navigationdata.h" 5 | 6 | class PlanSummaryModel : public QObject { 7 | Q_OBJECT 8 | 9 | QML_READONLY_VAR_PROPERTY(int, rooms) 10 | QML_READONLY_VAR_PROPERTY(int, length) 11 | QML_READONLY_VAR_PROPERTY(int, argus) 12 | QML_READONLY_VAR_PROPERTY(int, troves) 13 | QML_READONLY_VAR_PROPERTY(int, darkshrines) 14 | QML_READONLY_VAR_PROPERTY(int, silverCaches) 15 | 16 | public: 17 | PlanSummaryModel(QObject* parent = nullptr); 18 | void loadFromData(const NavigationData& data); 19 | }; 20 | 21 | #endif // PLANSUMMARYMODEL_H 22 | -------------------------------------------------------------------------------- /common/src/model/roommodel.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOMMODEL_H 2 | #define ROOMMODEL_H 3 | 4 | #include "model/labyrinthdata.h" 5 | #include "model/navigationdata.h" 6 | 7 | struct RoomModelData { 8 | QString id; 9 | QString name; 10 | QPoint coordinate; 11 | QStringList contents; 12 | bool isTarget; 13 | bool isCurrent; 14 | }; 15 | class RoomModel : public QAbstractListModel { 16 | Q_OBJECT 17 | 18 | enum Roles { 19 | IdRole = Qt::UserRole + 1, 20 | NameRole, 21 | CoordinateRole, 22 | ContentsRole, 23 | IsTargetRole, 24 | IsCurrentRole, 25 | }; 26 | 27 | QList d; 28 | 29 | public: 30 | RoomModel(); 31 | void loadFromData(const LabyrinthData& lab, const NavigationData& navigation); 32 | void updateFromData(const NavigationData& data); 33 | 34 | public: 35 | int rowCount(const QModelIndex& parent = QModelIndex()) const; 36 | QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; 37 | 38 | protected: 39 | QHash roleNames() const; 40 | }; 41 | 42 | #endif // ROOMMODEL_H 43 | -------------------------------------------------------------------------------- /common/src/model/roompresetmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "helper/roompresethelper.h" 4 | #include "roompresetmodel.h" 5 | 6 | RoomPresetModel::RoomPresetModel(QObject* parent) 7 | : QObject(parent) 8 | { 9 | m_current = -1; 10 | } 11 | 12 | void RoomPresetModel::loadFromData(const NavigationData& data) 13 | { 14 | if (!data.currentRoomDetermined) { 15 | update_roomId(QString()); 16 | update_roomName(QString()); 17 | update_current(-1); 18 | update_presets({}); 19 | 20 | } else { 21 | const auto& room = data.lab->getRoomFromId(data.currentRoom); 22 | update_roomId(room.id); 23 | update_roomName(room.name); 24 | 25 | auto helper = RoomPresetHelper::instance; 26 | const auto& presetList = helper->getPresetListByName(room.name, room.contents.contains("golden-door")); 27 | 28 | QVariantList presetsModel; 29 | int current = -1; 30 | 31 | if (!presetList.isEmpty()) { 32 | update_current(current); 33 | for (auto i = presetList.size() - 1; i >= 0; i--) { 34 | const auto& preset = presetList[i].second; 35 | QVariantMap item; 36 | item["areaCode"] = preset["areaCode"]; 37 | item["doorExitLocations"] = helper->getDoorExitLocationModel(preset); 38 | item["contentLocations"] = helper->getContentLocationModel(preset); 39 | presetsModel.append(item); 40 | 41 | if (item["areaCode"].toString() == room.areaCode) { 42 | current = presetList.size() - 1 - i; 43 | } 44 | } 45 | 46 | presetsModel.append(QVariantMap { { "areaCode", "disabled" }, { "doorExitLocations", QVariantList {} }, { "contentLocations", QVariantList {} } }); 47 | if (room.areaCode == "disabled") { 48 | current = presetsModel.size() - 1; 49 | } 50 | } 51 | 52 | update_current(current); 53 | update_presets(presetsModel); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /common/src/model/roompresetmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOMPRESETMODEL_H 2 | #define ROOMPRESETMODEL_H 3 | 4 | #include "model/navigationdata.h" 5 | 6 | class RoomPresetModel : public QObject { 7 | Q_OBJECT 8 | 9 | QML_READONLY_VAR_PROPERTY(QString, roomId) 10 | QML_READONLY_VAR_PROPERTY(QString, roomName) 11 | 12 | QML_READONLY_VAR_PROPERTY(QVariantList, presets) // [{"areaCode": string, "doorExitLocations": DoorExitLocationModel, "contentLocations": ContentLocationModel}] 13 | QML_READONLY_VAR_PROPERTY(int, current) 14 | 15 | public: 16 | RoomPresetModel(QObject* parent = nullptr); 17 | void loadFromData(const NavigationData& data); 18 | }; 19 | 20 | #endif // ROOMPRESETMODEL_H 21 | -------------------------------------------------------------------------------- /common/src/settings.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_H 2 | #define SETTINGS_H 3 | 4 | #include "qtsupermacros.h" 5 | 6 | class Settings : public QObject { 7 | Q_OBJECT 8 | 9 | QML_WRITABLE_VAR_PROPERTY(QPoint, mainWindowPosition) 10 | QML_WRITABLE_VAR_PROPERTY(QString, poeClientPath) 11 | QML_WRITABLE_VAR_PROPERTY(QString, latestVersion) 12 | QML_WRITABLE_VAR_PROPERTY(qint64, lastVersionCheckAttempt) 13 | QML_WRITABLE_VAR_PROPERTY(qint64, lastVersionCheckSuccess) 14 | QML_WRITABLE_VAR_PROPERTY(QDate, lastLoadedMapDate) 15 | QML_WRITABLE_VAR_PROPERTY(QString, importDirectory) 16 | 17 | QML_WRITABLE_VAR_PROPERTY(bool, multiclientSupport) 18 | 19 | QML_WRITABLE_VAR_PROPERTY(bool, portalSkipsSection) 20 | 21 | QML_WRITABLE_VAR_PROPERTY(QString, scaleFactor) 22 | QML_WRITABLE_VAR_PROPERTY(bool, showMinimap) 23 | 24 | QML_WRITABLE_VAR_PROPERTY(QString, toggleHideUiHotkey) 25 | 26 | std::unique_ptr settings; 27 | 28 | public: 29 | Settings(QObject* parent = nullptr); 30 | void load(); 31 | void save(); 32 | 33 | private: 34 | QVariant toVariant() const; 35 | }; 36 | 37 | #endif // SETTINGS_H 38 | -------------------------------------------------------------------------------- /common/src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef STDAFX_H 2 | #define STDAFX_H 3 | 4 | #include "qtsupermacros.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #endif // STDAFX_H 18 | -------------------------------------------------------------------------------- /common/src/worker/datechecker.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "datechecker.h" 4 | 5 | DateChecker::DateChecker(ApplicationModel* model, QObject* parent) 6 | : QObject(parent) 7 | { 8 | this->model = model; 9 | 10 | timer.setInterval(1000); 11 | timer.setSingleShot(false); 12 | timer.start(); 13 | connect(&timer, &QTimer::timeout, 14 | this, &DateChecker::work); 15 | 16 | work(); 17 | } 18 | 19 | void DateChecker::work() 20 | { 21 | model->update_currentUtcDate(QDateTime::currentDateTimeUtc().date()); 22 | } 23 | -------------------------------------------------------------------------------- /common/src/worker/datechecker.h: -------------------------------------------------------------------------------- 1 | #ifndef DATECHECKER_H 2 | #define DATECHECKER_H 3 | 4 | #include "model/applicationmodel.h" 5 | 6 | class DateChecker : public QObject { 7 | Q_OBJECT 8 | 9 | ApplicationModel* model; 10 | QTimer timer; 11 | 12 | public: 13 | DateChecker(ApplicationModel* model, QObject* parent = nullptr); 14 | 15 | private slots: 16 | void work(); 17 | }; 18 | 19 | #endif // DATECHECKER_H 20 | -------------------------------------------------------------------------------- /common/src/worker/logwatcher.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGWATCHER_H 2 | #define LOGWATCHER_H 3 | 4 | #include "model/applicationmodel.h" 5 | 6 | class LogWatcher : public QObject { 7 | Q_OBJECT 8 | 9 | ApplicationModel* model; 10 | QTimer timer; 11 | QString clientPath; 12 | QString activeClientId; 13 | std::unique_ptr file; 14 | 15 | signals: 16 | void plazaEntered(); 17 | void labStarted(); 18 | void labFinished(); 19 | void izaroBattleStarted(); 20 | void sectionFinished(); 21 | void labExit(); 22 | void roomChanged(QString name); 23 | void portalSpawned(); 24 | 25 | public: 26 | LogWatcher(ApplicationModel* model); 27 | 28 | private slots: 29 | void work(); 30 | 31 | private: 32 | void parseLine(const QString line); 33 | QString findGameClientPath(); 34 | void setActiveClient(const QString& clientId); 35 | bool isLogFromValidClient(const QString& clientId) const; 36 | }; 37 | 38 | #endif // LOGWATCHER_H 39 | -------------------------------------------------------------------------------- /common/src/worker/versionchecker.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "global.h" 4 | #include "versionchecker.h" 5 | 6 | VersionChecker::VersionChecker(ApplicationModel* model, QObject* parent) 7 | : QObject(parent) 8 | { 9 | this->model = model; 10 | 11 | nam.get(QNetworkRequest(QUrl("https://api.github.com/"))); 12 | 13 | timer.setInterval(1000); 14 | timer.setSingleShot(false); 15 | timer.start(); 16 | connect(&timer, &QTimer::timeout, 17 | this, &VersionChecker::work); 18 | } 19 | 20 | void VersionChecker::work() 21 | { 22 | auto latestVersion = model->get_settings()->get_latestVersion(); 23 | model->update_newVersionAvailable(!latestVersion.isEmpty() && latestVersion != VERSION); 24 | 25 | auto now = QDateTime::currentSecsSinceEpoch(); 26 | if (now - model->get_settings()->get_lastVersionCheckAttempt() > 600 && now - model->get_settings()->get_lastVersionCheckSuccess() > 86400) { 27 | model->get_settings()->set_lastVersionCheckAttempt(now); 28 | 29 | qInfo() << "Checking github for latest version"; 30 | auto reply = nam.get(QNetworkRequest(QUrl("https://api.github.com/repos/yznpku/LabCompass/releases/latest"))); 31 | connect(reply, &QNetworkReply::finished, 32 | this, &VersionChecker::onReplyFinished); 33 | } 34 | } 35 | 36 | void VersionChecker::onReplyFinished() 37 | { 38 | auto reply = reinterpret_cast(sender()); 39 | 40 | if (reply->error() == QNetworkReply::NoError) { 41 | auto json = QJsonDocument::fromJson(reply->readAll()); 42 | if (json.isObject() && json.object().contains("tag_name")) { 43 | auto latestVersion = json.object()["tag_name"].toString(); 44 | model->get_settings()->set_latestVersion(latestVersion); 45 | model->get_settings()->set_lastVersionCheckSuccess(QDateTime::currentSecsSinceEpoch()); 46 | 47 | qInfo() << "Received version checking response. Latest version:" << latestVersion; 48 | } 49 | } 50 | reply->deleteLater(); 51 | } 52 | -------------------------------------------------------------------------------- /common/src/worker/versionchecker.h: -------------------------------------------------------------------------------- 1 | #ifndef VERSIONCHECKER_H 2 | #define VERSIONCHECKER_H 3 | 4 | #include "model/applicationmodel.h" 5 | 6 | class VersionChecker : public QObject { 7 | Q_OBJECT 8 | 9 | QNetworkAccessManager nam; 10 | 11 | ApplicationModel* model; 12 | QTimer timer; 13 | 14 | public: 15 | VersionChecker(ApplicationModel* model, QObject* parent = nullptr); 16 | 17 | private slots: 18 | void work(); 19 | void onReplyFinished(); 20 | }; 21 | 22 | #endif // VERSIONCHECKER_H 23 | -------------------------------------------------------------------------------- /logsimulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME logsimulator) 2 | 3 | file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS 4 | *.cpp *.h *.ui 5 | ) 6 | 7 | add_executable(${TARGET_NAME} ${SOURCES}) 8 | 9 | target_include_directories(${TARGET_NAME} PRIVATE 10 | src 11 | ) 12 | 13 | target_precompile_headers(${TARGET_NAME} PRIVATE 14 | src/stdafx.h 15 | ) 16 | 17 | target_link_libraries(${TARGET_NAME} PRIVATE 18 | common 19 | Qt5::Widgets 20 | ) 21 | -------------------------------------------------------------------------------- /logsimulator/src/application.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "application.h" 4 | 5 | Application::Application(int& argc, char** argv) 6 | : QApplication(argc, argv) 7 | { 8 | settings.reset(new Settings()); 9 | settings->load(); 10 | 11 | widget.reset(new Widget(settings.get())); 12 | widget->show(); 13 | 14 | connect(widget.get(), &Widget::labStarted, 15 | this, &Application::onLabStarted); 16 | connect(widget.get(), &Widget::izaroBattleStarted, 17 | this, &Application::onIzaroBattleStarted); 18 | connect(widget.get(), &Widget::sectionFinished, 19 | this, &Application::onSectionFinished); 20 | connect(widget.get(), &Widget::labFinished, 21 | this, &Application::onLabFinished); 22 | connect(widget.get(), &Widget::roomChanged, 23 | this, &Application::onRoomChanged); 24 | } 25 | 26 | void Application::onLabStarted() 27 | { 28 | addLogLine("Izaro: Ascend with precision."); 29 | } 30 | 31 | void Application::onIzaroBattleStarted() 32 | { 33 | addLogLine("Izaro: Complex machinations converge to a single act of power."); 34 | } 35 | 36 | void Application::onSectionFinished() 37 | { 38 | addLogLine("Izaro: By the Goddess! What ambition!"); 39 | } 40 | 41 | void Application::onLabFinished() 42 | { 43 | addLogLine("Izaro: I die for the Empire!"); 44 | } 45 | 46 | void Application::onRoomChanged(const QString& roomName) 47 | { 48 | addLogLine(QString(": You have entered %1.").arg(roomName)); 49 | } 50 | 51 | void Application::addLogLine(const QString& s) 52 | { 53 | const auto& clientId = widget->getClientId(); 54 | const auto& line = QString("2018/01/01 00:00:00 0000000000 xxx [INFO Client %1] %2\n").arg(clientId, s); 55 | QFile file(QDir(widget->getClientPath()).absoluteFilePath("logs/Client.txt")); 56 | if (!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) 57 | return; 58 | file.write(line.toUtf8()); 59 | } 60 | -------------------------------------------------------------------------------- /logsimulator/src/application.h: -------------------------------------------------------------------------------- 1 | #ifndef APPLICATION_H 2 | #define APPLICATION_H 3 | 4 | #include "settings.h" 5 | #include "widget.h" 6 | 7 | class Application : public QApplication { 8 | Q_OBJECT 9 | 10 | std::unique_ptr widget; 11 | std::unique_ptr settings; 12 | 13 | public: 14 | Application(int& argc, char** argv); 15 | 16 | private slots: 17 | void onLabStarted(); 18 | void onIzaroBattleStarted(); 19 | void onSectionFinished(); 20 | void onLabFinished(); 21 | void onRoomChanged(const QString& roomName); 22 | 23 | private: 24 | void addLogLine(const QString& s); 25 | }; 26 | 27 | #endif // APPLICATION_H 28 | -------------------------------------------------------------------------------- /logsimulator/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "application.h" 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | Application app(argc, argv); 8 | 9 | return app.exec(); 10 | } 11 | -------------------------------------------------------------------------------- /logsimulator/src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef STDAFX_H 2 | #define STDAFX_H 3 | 4 | #include "qtsupermacros.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #endif // STDAFX_H 18 | -------------------------------------------------------------------------------- /logsimulator/src/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include "settings.h" 5 | 6 | namespace Ui { 7 | class Widget; 8 | } 9 | 10 | class Widget : public QWidget { 11 | Q_OBJECT 12 | 13 | Ui::Widget* ui; 14 | Settings* settings; 15 | 16 | public: 17 | Widget(Settings* settings, QWidget* parent = 0); 18 | ~Widget(); 19 | QString getClientPath() const; 20 | QString getClientId() const; 21 | 22 | signals: 23 | void labStarted(); 24 | void izaroBattleStarted(); 25 | void sectionFinished(); 26 | void labFinished(); 27 | void roomChanged(const QString& room); 28 | 29 | private: 30 | void loadMapFile(const QString& fileName); 31 | }; 32 | 33 | #endif // WIDGET_H 34 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME tests) 2 | 3 | file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS 4 | *.cpp *.h 5 | ) 6 | 7 | add_executable(${TARGET_NAME} WIN32 ${SOURCES}) 8 | 9 | target_include_directories(${TARGET_NAME} PRIVATE 10 | src 11 | ) 12 | 13 | target_link_libraries(${TARGET_NAME} PUBLIC 14 | common 15 | Qt5::Core 16 | Qt5::Gui 17 | Qt5::Widgets 18 | Qt5::Test 19 | ) 20 | 21 | add_custom_command(TARGET ${TARGET_NAME} POST_BUILD 22 | COMMAND ${CMAKE_COMMAND} -E copy_directory 23 | ${CMAKE_CURRENT_SOURCE_DIR}/data/ $/data/) 24 | -------------------------------------------------------------------------------- /tests/data/2018-01-09_cruel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-09_cruel.jpg -------------------------------------------------------------------------------- /tests/data/2018-01-09_merciless.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-09_merciless.jpg -------------------------------------------------------------------------------- /tests/data/2018-01-09_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-09_normal.jpg -------------------------------------------------------------------------------- /tests/data/2018-01-09_normal.json: -------------------------------------------------------------------------------- 1 | {"difficulty": "Normal","date": "2018-01-09","weapon": "SwordAndShield","phase1": "Idols","phase2": "Gargoyles","trap1": "NoTrap","trap2": "NoTrap","section1layout": "single","section2layout": "double_up","section3layout": "compass_west","rooms": [{"name": "estate path","areacode": "1_labyrinth_oh_straight","id": "1","x": "106","y": "128","dangerous": "false","contents": ["Escort gauntlet"],"content_directions": [],"exits": {"NE": "2"}},{"name": "aspirant's trial","areacode": "1_labyrinth_boss_1","id": "2","x": "244","y": "128","dangerous": "false","contents": [],"content_directions": [],"exits": {"NW": "3"}},{"name": "sanitorium halls","areacode": "1_labyrinth_p_branch_bottleneck_2","id": "3","x": "379","y": "128","dangerous": "false","contents": ["darkshrine"],"content_directions": [],"exits": {"NE": "4","NW": "5"}},{"name": "aspirant's trial","areacode": "1_labyrinth_boss_2","id": "4","x": "518","y": "128","dangerous": "false","contents": [],"content_directions": [],"exits": {"NW": "6"}},{"name": "estate path","areacode": "1_labyrinth_oh_straight","id": "5","x": "450","y": "40","dangerous": "false","contents": ["darkshrine"],"content_directions": [],"exits": {"NE": "4"}},{"name": "mansion halls","areacode": "1_labyrinth_eh_block_branch","id": "6","x": "621","y": "128","dangerous": "false","contents": ["Trap gauntlet"],"content_directions": [],"exits": {"NE": "7","NW": "10"}},{"name": "domain walkways","areacode": "1_labyrinth_dg_branch","id": "7","x": "726","y": "40","dangerous": "false","contents": ["Switch puzzle","Trap gauntlet"],"content_directions": [],"exits": {"NE": "8","NW": "9"}},{"name": "basilica passage","areacode": "1_labyrinth_rt_straight","id": "8","x": "691","y": "128","dangerous": "false","contents": ["silver-key","silver-door"],"content_directions": [],"exits": {"SE": "10"}},{"name": "aspirant's trial","areacode": "1_labyrinth_boss_2_end","id": "9","x": "793","y": "128","dangerous": "false","contents": [],"content_directions": [],"exits": {}},{"name": "sepulchre halls","areacode": "1_labyrinth_c_branch_bottleneck_2","id": "10","x": "726","y": "216","dangerous": "false","contents": ["silver-key","silver-door"],"content_directions": [],"exits": {"NE": "9","NW": "8"}}]} -------------------------------------------------------------------------------- /tests/data/2018-01-09_uber.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-09_uber.jpg -------------------------------------------------------------------------------- /tests/data/2018-01-10_cruel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-10_cruel.jpg -------------------------------------------------------------------------------- /tests/data/2018-01-10_merciless.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-10_merciless.jpg -------------------------------------------------------------------------------- /tests/data/2018-01-10_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-10_normal.jpg -------------------------------------------------------------------------------- /tests/data/2018-01-10_normal.json: -------------------------------------------------------------------------------- 1 | {"difficulty": "Normal","date": "2018-01-10","weapon": "TwoSwords","phase1": "Gargoyles","phase2": "Conduits","trap1": "NoTrap","trap2": "NoTrap","section1layout": "single","section2layout": "double_up","section3layout": "compass_west","rooms": [{"name": "estate path","areacode": "1_labyrinth_oh_straight","id": "1","x": "106","y": "128","dangerous": "false","contents": ["Trap gauntlet"],"content_directions": [],"exits": {"NE": "2"}},{"name": "aspirant's trial","areacode": "1_labyrinth_boss_1","id": "2","x": "244","y": "128","dangerous": "false","contents": [],"content_directions": [],"exits": {"NW": "3"}},{"name": "sanitorium halls","areacode": "1_labyrinth_p_branch_bottleneck_2","id": "3","x": "379","y": "128","dangerous": "false","contents": ["Switch puzzle"],"content_directions": [],"exits": {"NW": "5","NE": "4"}},{"name": "aspirant's trial","areacode": "1_labyrinth_boss_2","id": "4","x": "518","y": "128","dangerous": "false","contents": [],"content_directions": [],"exits": {"NW": "6"}},{"name": "mansion passage","areacode": "1_labyrinth_eh_straight_#","id": "5","x": "450","y": "40","dangerous": "false","contents": ["Escort gauntlet","darkshrine"],"content_directions": [],"exits": {"NE": "4"}},{"name": "mansion halls","areacode": "1_labyrinth_eh_block_branch","id": "6","x": "621","y": "128","dangerous": "false","contents": ["Trap gauntlet"],"content_directions": [],"exits": {"NW": "7","NE": "8"}},{"name": "basilica halls","areacode": "1_labyrinth_rt_branch_bottleneck_2","id": "7","x": "726","y": "216","dangerous": "false","contents": ["silver-key","silver-door"],"content_directions": [],"exits": {"NW": "9","NE": "10"}},{"name": "domain walkways","areacode": "1_labyrinth_dg_branch","id": "8","x": "726","y": "40","dangerous": "false","contents": ["darkshrine"],"content_directions": [],"exits": {"NE": "9","NW": "10"}},{"name": "sepulchre passage","areacode": "1_labyrinth_c_straight","id": "9","x": "691","y": "128","dangerous": "false","contents": ["silver-key","silver-door"],"content_directions": [],"exits": {"NE": "8","SE": "7"}},{"name": "aspirant's trial","areacode": "1_labyrinth_boss_2_end","id": "10","x": "793","y": "128","dangerous": "false","contents": [],"content_directions": [],"exits": {}}]} -------------------------------------------------------------------------------- /tests/data/2018-01-10_uber.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yznpku/LabCompass/35c9bad6a60bde6b555c459f6ad4273d18fa6101/tests/data/2018-01-10_uber.jpg -------------------------------------------------------------------------------- /tests/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "helper/roompresethelper.h" 2 | #include "tests/labyrinthdata/labyrinthdataloadtest.h" 3 | #include "tests/labyrinthdata/labyrinthdataroomistrialtest.h" 4 | #include "tests/labyrinthmodel/labyrinthmodelpropertiestest.h" 5 | #include "tests/testdataavailabletest.h" 6 | #include 7 | #include 8 | 9 | int main(int argc, char** argv) 10 | { 11 | Q_INIT_RESOURCE(common); 12 | RoomPresetHelper::instance = new RoomPresetHelper(); 13 | 14 | if (int r = QTest::qExec(std::make_unique().get())) { 15 | return r; 16 | } 17 | 18 | QTest::qExec(std::make_unique().get()); 19 | QTest::qExec(std::make_unique().get()); 20 | QTest::qExec(std::make_unique().get()); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/src/navigation/navigationcontrollerwrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "navigationcontrollerwrapper.h" 2 | 3 | NavigationControllerWrapper::NavigationControllerWrapper(ApplicationModel* model) 4 | { 5 | controller.reset(new NavigationController(model)); 6 | } 7 | 8 | NavigationControllerWrapper* NavigationControllerWrapper::labStarted() 9 | { 10 | controller->onLabStarted(); 11 | return this; 12 | } 13 | 14 | NavigationControllerWrapper* NavigationControllerWrapper::sectionFinished() 15 | { 16 | controller->onSectionFinished(); 17 | return this; 18 | } 19 | 20 | NavigationControllerWrapper* NavigationControllerWrapper::labExit() 21 | { 22 | controller->onLabExit(); 23 | return this; 24 | } 25 | 26 | NavigationControllerWrapper* NavigationControllerWrapper::roomChanged(const QString& name) 27 | { 28 | controller->onRoomChanged(name); 29 | return this; 30 | } 31 | -------------------------------------------------------------------------------- /tests/src/navigation/navigationcontrollerwrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef NAVIGATIONCONTROLLERWRAPPER_H 2 | #define NAVIGATIONCONTROLLERWRAPPER_H 3 | 4 | #include "controller/navigationcontroller.h" 5 | 6 | class NavigationControllerWrapper { 7 | 8 | std::unique_ptr controller; 9 | 10 | public: 11 | NavigationControllerWrapper(ApplicationModel* model); 12 | 13 | public: 14 | NavigationControllerWrapper* labStarted(); 15 | NavigationControllerWrapper* sectionFinished(); 16 | NavigationControllerWrapper* labExit(); 17 | NavigationControllerWrapper* roomChanged(const QString& name); 18 | }; 19 | 20 | #endif // NAVIGATIONCONTROLLERWRAPPER_H 21 | -------------------------------------------------------------------------------- /tests/src/tests/labyrinthdata/labyrinthdataloadtest.cpp: -------------------------------------------------------------------------------- 1 | #include "labyrinthdataloadtest.h" 2 | #include "model/labyrinthdata.h" 3 | 4 | LabyrinthDataLoadTest::LabyrinthDataLoadTest(QObject* parent) 5 | : QObject(parent) 6 | { 7 | } 8 | 9 | void LabyrinthDataLoadTest::test_data() 10 | { 11 | QTest::addColumn("fileName"); 12 | 13 | QTest::newRow("2018-01-09 Normal") << "2018-01-09_normal.json"; 14 | QTest::newRow("2018-01-09 Cruel") << "2018-01-09_cruel.json"; 15 | QTest::newRow("2018-01-09 Merciless") << "2018-01-09_merciless.json"; 16 | QTest::newRow("2018-01-09 Uber") << "2018-01-09_uber.json"; 17 | QTest::newRow("2018-01-10 Normal") << "2018-01-10_normal.json"; 18 | QTest::newRow("2018-01-10 Cruel") << "2018-01-10_cruel.json"; 19 | QTest::newRow("2018-01-10 Merciless") << "2018-01-10_merciless.json"; 20 | QTest::newRow("2018-01-10 Uber") << "2018-01-10_uber.json"; 21 | } 22 | 23 | void LabyrinthDataLoadTest::test() 24 | { 25 | QFETCH(QString, fileName); 26 | LabyrinthData data; 27 | QVERIFY(data.loadFromFile(QDir("data").filePath(fileName))); 28 | } 29 | -------------------------------------------------------------------------------- /tests/src/tests/labyrinthdata/labyrinthdataloadtest.h: -------------------------------------------------------------------------------- 1 | #ifndef LABYRINTHMODELLOADTEST_H 2 | #define LABYRINTHMODELLOADTEST_H 3 | 4 | #include 5 | 6 | class LabyrinthDataLoadTest : public QObject { 7 | Q_OBJECT 8 | 9 | public: 10 | LabyrinthDataLoadTest(QObject* parent = nullptr); 11 | 12 | private slots: 13 | void test_data(); 14 | void test(); 15 | }; 16 | 17 | #endif // LABYRINTHMODELLOADTEST_H 18 | -------------------------------------------------------------------------------- /tests/src/tests/labyrinthdata/labyrinthdataroomistrialtest.cpp: -------------------------------------------------------------------------------- 1 | #include "labyrinthdataroomistrialtest.h" 2 | #include "model/labyrinthdata.h" 3 | 4 | using Set = QSet; 5 | 6 | LabyrinthDataRoomIsTrialTest::LabyrinthDataRoomIsTrialTest(QObject* parent) 7 | : QObject(parent) 8 | { 9 | } 10 | 11 | void LabyrinthDataRoomIsTrialTest::test_data() 12 | { 13 | QTest::addColumn("fileName"); 14 | QTest::addColumn("trials"); 15 | 16 | QTest::newRow("2018-01-09 Normal") << "2018-01-09_normal.json" 17 | << Set { "2", "4", "9" }; 18 | QTest::newRow("2018-01-09 Cruel") << "2018-01-09_cruel.json" 19 | << Set { "2", "7", "12" }; 20 | QTest::newRow("2018-01-09 Merciless") << "2018-01-09_merciless.json" 21 | << Set { "4", "7", "13" }; 22 | QTest::newRow("2018-01-09 Uber") << "2018-01-09_uber.json" 23 | << Set { "4", "10", "15" }; 24 | QTest::newRow("2018-01-10 Normal") << "2018-01-10_normal.json" 25 | << Set { "2", "4", "10" }; 26 | QTest::newRow("2018-01-10 Cruel") << "2018-01-10_cruel.json" 27 | << Set { "3", "7", "11" }; 28 | QTest::newRow("2018-01-10 Merciless") << "2018-01-10_merciless.json" 29 | << Set { "4", "7", "12" }; 30 | QTest::newRow("2018-01-10 Uber") << "2018-01-10_uber.json" 31 | << Set { "5", "10", "15" }; 32 | } 33 | 34 | void LabyrinthDataRoomIsTrialTest::test() 35 | { 36 | QFETCH(QString, fileName); 37 | LabyrinthData data; 38 | data.loadFromFile(QDir("data").filePath(fileName)); 39 | 40 | QFETCH(Set, trials); 41 | Set actualTrials; 42 | for (auto i = data.rooms.begin(); i != data.rooms.end(); i++) 43 | if (data.roomIsTrial(i->id)) 44 | actualTrials.insert(i->id); 45 | QCOMPARE(actualTrials, trials); 46 | } 47 | -------------------------------------------------------------------------------- /tests/src/tests/labyrinthdata/labyrinthdataroomistrialtest.h: -------------------------------------------------------------------------------- 1 | #ifndef LABYRINTHDATAROOMISTRIALTEST_H 2 | #define LABYRINTHDATAROOMISTRIALTEST_H 3 | 4 | #include 5 | 6 | class LabyrinthDataRoomIsTrialTest : public QObject { 7 | Q_OBJECT 8 | 9 | public: 10 | LabyrinthDataRoomIsTrialTest(QObject* parent = nullptr); 11 | 12 | private slots: 13 | void test_data(); 14 | void test(); 15 | }; 16 | 17 | #endif // LABYRINTHDATAROOMISTRIALTEST_H 18 | -------------------------------------------------------------------------------- /tests/src/tests/labyrinthmodel/labyrinthmodelpropertiestest.h: -------------------------------------------------------------------------------- 1 | #ifndef LABYRINTHMODELPROPERTIESTEST_H 2 | #define LABYRINTHMODELPROPERTIESTEST_H 3 | 4 | #include 5 | 6 | class LabyrinthModelPropertiesTest : public QObject { 7 | Q_OBJECT 8 | 9 | public: 10 | LabyrinthModelPropertiesTest(QObject* parent = nullptr); 11 | 12 | private slots: 13 | void test_data(); 14 | void test(); 15 | }; 16 | 17 | #endif // LABYRINTHMODELPROPERTIESTEST_H 18 | -------------------------------------------------------------------------------- /tests/src/tests/testdataavailabletest.cpp: -------------------------------------------------------------------------------- 1 | #include "testdataavailabletest.h" 2 | 3 | TestDataAvailableTest::TestDataAvailableTest(QObject* parent) 4 | : QObject(parent) 5 | { 6 | } 7 | 8 | void TestDataAvailableTest::test_data() 9 | { 10 | QTest::addColumn("fileName"); 11 | 12 | QTest::newRow("2018-01-09_normal.json") << "2018-01-09_normal.json"; 13 | QTest::newRow("2018-01-09_cruel.json") << "2018-01-09_cruel.json"; 14 | QTest::newRow("2018-01-09_merciless.json") << "2018-01-09_merciless.json"; 15 | QTest::newRow("2018-01-09_uber.json") << "2018-01-09_uber.json"; 16 | QTest::newRow("2018-01-10_normal.json") << "2018-01-10_normal.json"; 17 | QTest::newRow("2018-01-10_cruel.json") << "2018-01-10_cruel.json"; 18 | QTest::newRow("2018-01-10_merciless.json") << "2018-01-10_merciless.json"; 19 | QTest::newRow("2018-01-10_uber.json") << "2018-01-10_uber.json"; 20 | } 21 | 22 | void TestDataAvailableTest::test() 23 | { 24 | QFETCH(QString, fileName); 25 | QVERIFY2(QDir("data").exists(fileName), "Test data not found. Run \"make install\" before running this test."); 26 | } 27 | -------------------------------------------------------------------------------- /tests/src/tests/testdataavailabletest.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTDATAAVAILABLETEST_H 2 | #define TESTDATAAVAILABLETEST_H 3 | 4 | #include 5 | 6 | class TestDataAvailableTest : public QObject { 7 | Q_OBJECT 8 | 9 | public: 10 | explicit TestDataAvailableTest(QObject* parent = nullptr); 11 | 12 | private slots: 13 | void test_data(); 14 | void test(); 15 | }; 16 | 17 | #endif // TESTDATAAVAILABLETEST_H 18 | -------------------------------------------------------------------------------- /vendor/HungarianAlgorithm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME HungarianAlgorithm) 2 | 3 | file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS 4 | *.cpp *.h 5 | ) 6 | 7 | add_library(${TARGET_NAME} ${SOURCES}) 8 | 9 | target_include_directories(${TARGET_NAME} PUBLIC 10 | . 11 | ) -------------------------------------------------------------------------------- /vendor/HungarianAlgorithm/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, mcximing 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/HungarianAlgorithm/README.txt: -------------------------------------------------------------------------------- 1 | 2 | Hungarian algorithm, also known as Munkres algorithm or Kuhn-Munkres algorithm, is a method for solving the assignment problem, for example assigning workers to jobs, which goal is to compute the optimal assignment that minimizes the total cost, and the like. 3 | 4 | This is a C++ wrapper with slight modification of a hungarian algorithm implementation by Markus Buehren. 5 | The original code is a few mex-functions for use in MATLAB, found here: 6 | http://www.mathworks.com/matlabcentral/fileexchange/6543-functions-for-the-rectangular-assignment-problem 7 | 8 | -------------------------------------------------------------------------------- /vendor/QHotkey/.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | /.qmake.cache 16 | /.qmake.stash 17 | *.pro.user 18 | *.pro.user.* 19 | *.qbs.user 20 | *.qbs.user.* 21 | *.moc 22 | moc_*.cpp 23 | qrc_*.cpp 24 | ui_*.h 25 | Makefile* 26 | *build-* 27 | 28 | # QtCreator 29 | 30 | *.autosave 31 | 32 | #QtCtreator Qml 33 | *.qmlproject.user 34 | *.qmlproject.user.* 35 | -------------------------------------------------------------------------------- /vendor/QHotkey/HotkeyTest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 2 | 3 | set(CMAKE_AUTOUIC ON) 4 | 5 | add_executable(HotkeyTest 6 | main.cpp 7 | hottestwidget.cpp 8 | hottestwidget.ui) 9 | 10 | find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Widgets REQUIRED) 11 | target_link_libraries(HotkeyTest Qt${QT_DEFAULT_MAJOR_VERSION}::Widgets QHotkey::QHotkey) 12 | -------------------------------------------------------------------------------- /vendor/QHotkey/HotkeyTest/HotkeyTest.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2016-02-05T22:01:03 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = HotkeyTest 12 | TEMPLATE = app 13 | 14 | include(../qhotkey.pri) 15 | 16 | SOURCES += main.cpp\ 17 | hottestwidget.cpp 18 | 19 | HEADERS += hottestwidget.h 20 | 21 | FORMS += hottestwidget.ui 22 | -------------------------------------------------------------------------------- /vendor/QHotkey/HotkeyTest/hottestwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef HOTTESTWIDGET_H 2 | #define HOTTESTWIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Ui { 9 | class HotTestWidget; 10 | } 11 | 12 | class HotTestWidget : public QWidget 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit HotTestWidget(QWidget *parent = 0); 18 | ~HotTestWidget(); 19 | 20 | private slots: 21 | void setShortcut_1(const QKeySequence &sequence); 22 | void setShortcut_2(const QKeySequence &sequence); 23 | void setShortcut_3(const QKeySequence &sequence); 24 | void setShortcut_4(const QKeySequence &sequence); 25 | void setShortcut_5(const QKeySequence &sequence); 26 | 27 | void increase_1(); 28 | void increase_2(); 29 | void increase_3(); 30 | void increase_4(); 31 | void increase_5(); 32 | 33 | void on_resetButton_1_clicked(); 34 | void on_resetButton_2_clicked(); 35 | void on_resetButton_3_clicked(); 36 | void on_resetButton_4_clicked(); 37 | void on_resetButton_5_clicked(); 38 | 39 | void on_groupBox_toggled(bool checked); 40 | void on_threadEnableCheckBox_clicked(); 41 | 42 | void on_registeredCheckBox_toggled(bool checked); 43 | void increase_native(); 44 | 45 | private: 46 | Ui::HotTestWidget *ui; 47 | 48 | QHotkey *hotkey_1; 49 | QHotkey *hotkey_2; 50 | QHotkey *hotkey_3; 51 | QHotkey *hotkey_4; 52 | QHotkey *hotkey_5; 53 | 54 | QThread *thread4; 55 | QThread *thread5; 56 | 57 | QList testHotkeys; 58 | 59 | QHotkey *nativeHotkey; 60 | }; 61 | 62 | #endif // HOTTESTWIDGET_H 63 | -------------------------------------------------------------------------------- /vendor/QHotkey/HotkeyTest/main.cpp: -------------------------------------------------------------------------------- 1 | #include "hottestwidget.h" 2 | #include 3 | 4 | //#define START_BACKGROUND 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication a(argc, argv); 9 | HotTestWidget w; 10 | 11 | #ifdef START_BACKGROUND 12 | auto startKey = new QHotkey(QKeySequence(Qt::MetaModifier | Qt::ControlModifier | Qt::Key_S), true, &w); 13 | QObject::connect(startKey, &QHotkey::activated, 14 | &w, &QWidget::show); 15 | #else 16 | w.show(); 17 | #endif 18 | 19 | return a.exec(); 20 | } 21 | -------------------------------------------------------------------------------- /vendor/QHotkey/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Felix Barz 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of QHotkey nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/QHotkey/QHotkey.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | SUBDIRS += \ 4 | HotkeyTest \ 5 | QHotkey 6 | 7 | DISTFILES += README.md \ 8 | LICENSE \ 9 | doc/qhotkey.doxy \ 10 | doc/qhotkey.dox 11 | -------------------------------------------------------------------------------- /vendor/QHotkey/QHotkey/QHotkey: -------------------------------------------------------------------------------- 1 | #include "qhotkey.h" 2 | -------------------------------------------------------------------------------- /vendor/QHotkey/QHotkey/QHotkey.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | win32: CONFIG += dll 3 | 4 | TARGET = QHotkey 5 | VERSION = 1.5.0 6 | 7 | include(../qhotkey.pri) 8 | 9 | DEFINES += QHOTKEY_SHARED QHOTKEY_LIBRARY 10 | 11 | # use INSTALL_ROOT to modify the install location 12 | headers.files = $$PUBLIC_HEADERS 13 | headers.path = $$[QT_INSTALL_HEADERS] 14 | target.path = $$[QT_INSTALL_LIBS] 15 | INSTALLS += target headers 16 | 17 | -------------------------------------------------------------------------------- /vendor/QHotkey/QHotkey/qhotkey.pri: -------------------------------------------------------------------------------- 1 | message(The pri file has been moved one directory up! use that one instead) 2 | -------------------------------------------------------------------------------- /vendor/QHotkey/QHotkey/qhotkey_p.h: -------------------------------------------------------------------------------- 1 | #ifndef QHOTKEY_P_H 2 | #define QHOTKEY_P_H 3 | 4 | #include "qhotkey.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 11 | #define _NATIVE_EVENT_RESULT qintptr 12 | #else 13 | #define _NATIVE_EVENT_RESULT long 14 | #endif 15 | 16 | class QHOTKEY_EXPORT QHotkeyPrivate : public QObject, public QAbstractNativeEventFilter 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | QHotkeyPrivate();//singleton!!! 22 | ~QHotkeyPrivate(); 23 | 24 | static QHotkeyPrivate *instance(); 25 | static bool isPlatformSupported(); 26 | 27 | QHotkey::NativeShortcut nativeShortcut(Qt::Key keycode, Qt::KeyboardModifiers modifiers); 28 | 29 | bool addShortcut(QHotkey *hotkey); 30 | bool removeShortcut(QHotkey *hotkey); 31 | 32 | protected: 33 | void activateShortcut(QHotkey::NativeShortcut shortcut); 34 | void releaseShortcut(QHotkey::NativeShortcut shortcut); 35 | 36 | virtual quint32 nativeKeycode(Qt::Key keycode, bool &ok) = 0;//platform implement 37 | virtual quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) = 0;//platform implement 38 | 39 | virtual bool registerShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement 40 | virtual bool unregisterShortcut(QHotkey::NativeShortcut shortcut) = 0;//platform implement 41 | 42 | QString error; 43 | 44 | private: 45 | QHash, QHotkey::NativeShortcut> mapping; 46 | QMultiHash shortcuts; 47 | 48 | Q_INVOKABLE void addMappingInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers, QHotkey::NativeShortcut nativeShortcut); 49 | Q_INVOKABLE bool addShortcutInvoked(QHotkey *hotkey); 50 | Q_INVOKABLE bool removeShortcutInvoked(QHotkey *hotkey); 51 | Q_INVOKABLE QHotkey::NativeShortcut nativeShortcutInvoked(Qt::Key keycode, Qt::KeyboardModifiers modifiers); 52 | }; 53 | 54 | #define NATIVE_INSTANCE(ClassName) \ 55 | Q_GLOBAL_STATIC(ClassName, hotkeyPrivate) \ 56 | \ 57 | QHotkeyPrivate *QHotkeyPrivate::instance()\ 58 | {\ 59 | return hotkeyPrivate;\ 60 | } 61 | 62 | #endif // QHOTKEY_P_H 63 | -------------------------------------------------------------------------------- /vendor/QHotkey/qhotkey.prc: -------------------------------------------------------------------------------- 1 | mac: LIBS += -framework Carbon 2 | else:win32: LIBS += -luser32 3 | else:unix { 4 | equals(QT_MAJOR_VERSION, 6) { 5 | lessThan(QT_VERSION, 6.2.0) { 6 | error("Qt 6.2.0 or greater is required when using Qt6") 7 | } 8 | } 9 | else { 10 | lessThan(QT_MAJOR_VERSION, 6) { 11 | QT += x11extras 12 | } 13 | } 14 | LIBS += -lX11 15 | } 16 | -------------------------------------------------------------------------------- /vendor/QHotkey/qhotkey.pri: -------------------------------------------------------------------------------- 1 | CONFIG += C++11 2 | 3 | PUBLIC_HEADERS += $$PWD/QHotkey/qhotkey.h \ 4 | $$PWD/QHotkey/QHotkey 5 | 6 | HEADERS += $$PUBLIC_HEADERS \ 7 | $$PWD/QHotkey/qhotkey_p.h 8 | 9 | SOURCES += $$PWD/QHotkey/qhotkey.cpp 10 | 11 | mac: SOURCES += $$PWD/QHotkey/qhotkey_mac.cpp 12 | else:win32: SOURCES += $$PWD/QHotkey/qhotkey_win.cpp 13 | else:unix: SOURCES += $$PWD/QHotkey/qhotkey_x11.cpp 14 | 15 | INCLUDEPATH += $$PWD/QHotkey 16 | 17 | include($$PWD/qhotkey.prc) 18 | -------------------------------------------------------------------------------- /vendor/QHotkey/qpm.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "email": "skycoder42.de@gmx.de", 4 | "name": "Skycoder" 5 | }, 6 | "dependencies": [ 7 | ], 8 | "description": "A global shortcut/hotkey for Desktop Qt-Applications", 9 | "license": "BSD_3_CLAUSE", 10 | "name": "de.skycoder42.qhotkey", 11 | "pri_filename": "qhotkey.pri", 12 | "repository": { 13 | "type": "GITHUB", 14 | "url": "https://github.com/Skycoder42/QHotkey.git" 15 | }, 16 | "version": { 17 | "fingerprint": "", 18 | "label": "1.2.2", 19 | "revision": "" 20 | }, 21 | "webpage": "https://github.com/Skycoder42/QHotkey" 22 | } 23 | -------------------------------------------------------------------------------- /vendor/QHotkey/qpmx.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | ], 4 | "license": { 5 | "file": "LICENSE", 6 | "name": "BSD_3_CLAUSE" 7 | }, 8 | "prcFile": "qhotkey.prc", 9 | "priFile": "qhotkey.pri", 10 | "priIncludes": [ 11 | ], 12 | "publishers": { 13 | "qpm": { 14 | "author": { 15 | "email": "skycoder42.de@gmx.de", 16 | "name": "Skycoder" 17 | }, 18 | "description": "A global shortcut/hotkey for Desktop Qt-Applications", 19 | "name": "de.skycoder42.qhotkey", 20 | "repository": { 21 | "type": "GITHUB", 22 | "url": "https://github.com/Skycoder42/QHotkey.git" 23 | }, 24 | "webpage": "https://github.com/Skycoder42/QHotkey" 25 | } 26 | }, 27 | "source": false 28 | } 29 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME QtJsonSchema) 2 | 3 | file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS 4 | *.cpp *.h 5 | ) 6 | 7 | add_library(${TARGET_NAME} ${SOURCES}) 8 | 9 | target_link_libraries(${TARGET_NAME} PUBLIC 10 | Qt5::Core 11 | ) 12 | 13 | target_include_directories(${TARGET_NAME} PUBLIC 14 | include 15 | ) -------------------------------------------------------------------------------- /vendor/QtJsonSchema/include/QtJsonSchema: -------------------------------------------------------------------------------- 1 | #include "../src/jsonschema.h" 2 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/error/jsonschemavalidationerror.cpp: -------------------------------------------------------------------------------- 1 | #include "jsonschemavalidationerror.h" 2 | 3 | JsonSchemaValidationError::JsonSchemaValidationError(const JsonPointer& schemaPtr, const JsonPointer& instancePtr, const QString& error) 4 | { 5 | this->schemaPtr = schemaPtr; 6 | this->instancePtr = instancePtr; 7 | this->error = error; 8 | } 9 | 10 | QString JsonSchemaValidationError::toString() const 11 | { 12 | return "#" + schemaPtr.path.join('/') + " => #" + instancePtr.path.join('/') + ": " + error; 13 | } 14 | 15 | QDebug operator<<(QDebug debug, const JsonSchemaValidationError& o) 16 | { 17 | QDebugStateSaver saver(debug); 18 | debug << o.toString(); 19 | return debug; 20 | } 21 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/error/jsonschemavalidationerror.h: -------------------------------------------------------------------------------- 1 | #ifndef JSONSCHEMAVALIDATIONERROR_H 2 | #define JSONSCHEMAVALIDATIONERROR_H 3 | 4 | #include 5 | #include "../pointer/jsonpointer.h" 6 | 7 | class JsonSchemaValidationError 8 | { 9 | JsonPointer schemaPtr; 10 | JsonPointer instancePtr; 11 | QString error; 12 | 13 | public: 14 | JsonSchemaValidationError(const JsonPointer& schemaPtr, const JsonPointer& instancePtr, const QString& error = QString()); 15 | 16 | QString toString() const; 17 | }; 18 | 19 | QDebug operator<<(QDebug debug, const JsonSchemaValidationError& o); 20 | 21 | #endif // JSONSCHEMAVALIDATIONERROR_H 22 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/hashfunctions.cpp: -------------------------------------------------------------------------------- 1 | #include "hashfunctions.h" 2 | #include "pointer/jsonpointer.h" 3 | 4 | uint qHash(const JsonPointer& ptr, uint seed) 5 | { 6 | return qHash(ptr.path, seed); 7 | } 8 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/hashfunctions.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHFUNCTIONS_H 2 | #define HASHFUNCTIONS_H 3 | 4 | #include 5 | 6 | class JsonPointer; 7 | 8 | struct HashCombine { 9 | template 10 | uint operator()(uint seed, const T& t) const 11 | { return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; } 12 | }; 13 | 14 | uint qHash(const JsonPointer& ptr, uint seed = 0); 15 | 16 | #endif // HASHFUNCTIONS_H 17 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/jsonschema.h: -------------------------------------------------------------------------------- 1 | #ifndef JSONSCHEMA_H 2 | #define JSONSCHEMA_H 3 | 4 | #include 5 | #include "jsonschemaversion.h" 6 | 7 | class JsonSchemaPrivate; 8 | class JsonSchema 9 | { 10 | 11 | public: 12 | JsonSchema(const JsonSchema& other) noexcept; 13 | JsonSchema(JsonSchema&& other) noexcept 14 | : d(other.d) { other.d = nullptr; } 15 | JsonSchema& operator=(const JsonSchema& other) noexcept; 16 | JsonSchema& operator=(JsonSchema&& other) noexcept 17 | { swap(other); return *this; } 18 | void swap(JsonSchema& other) noexcept 19 | { qSwap(d, other.d); } 20 | ~JsonSchema(); 21 | 22 | static JsonSchema fromJson(const QJsonValue& json, JsonSchemaVersion::Version version = JsonSchemaVersion::Draft07); 23 | static JsonSchema fromVariant(const QVariant& variant, JsonSchemaVersion::Version version = JsonSchemaVersion::Draft07); 24 | static JsonSchema fromJsonDocument(const QJsonDocument& document, JsonSchemaVersion::Version version = JsonSchemaVersion::Draft07); 25 | static JsonSchema fromJsonString(const QByteArray& json, JsonSchemaVersion::Version version = JsonSchemaVersion::Draft07); 26 | static JsonSchema metaSchema(JsonSchemaVersion::Version version); 27 | 28 | public: 29 | bool validate(const QJsonValue& instance) const; 30 | bool validate(const QVariant& instance) const; 31 | bool validate(const QJsonDocument& instance) const; 32 | bool validate(const QByteArray& instance) const; 33 | bool isValid() const; 34 | 35 | protected: 36 | JsonSchema(JsonSchemaVersion::Version version); 37 | JsonSchemaPrivate* d; 38 | }; 39 | 40 | #endif // JSONSCHEMA_H 41 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/jsonschema_p.h: -------------------------------------------------------------------------------- 1 | #ifndef JSONSCHEMA_P_H 2 | #define JSONSCHEMA_P_H 3 | 4 | #include "jsonschema.h" 5 | #include 6 | #include "validator/jsonschemanodevalidator.h" 7 | 8 | class JsonSchemaPrivate 9 | { 10 | public: 11 | QAtomicInt ref; 12 | 13 | JsonSchemaVersion::Version version; 14 | std::unique_ptr validator; 15 | bool validAgainstMetaSchema {true}; 16 | 17 | public: 18 | JsonSchemaPrivate(JsonSchemaVersion::Version version); 19 | 20 | void setSchema(const QJsonValue& schema); 21 | }; 22 | 23 | #endif // JSONSCHEMA_P_H 24 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/jsonschemaversion.h: -------------------------------------------------------------------------------- 1 | #ifndef JSONSCHEMAVERSION_H 2 | #define JSONSCHEMAVERSION_H 3 | 4 | namespace JsonSchemaVersion 5 | { 6 | enum Version { Draft04, Draft06, Draft07 }; 7 | } 8 | 9 | #endif // JSONSCHEMAVERSION_H 10 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/pointer/jsonpointer.cpp: -------------------------------------------------------------------------------- 1 | #include "jsonpointer.h" 2 | 3 | JsonPointer::JsonPointer(const QJsonValue& root) 4 | { 5 | this->root = root; 6 | this->v = root; 7 | } 8 | 9 | JsonPointer::JsonPointer(const QJsonValue& root, const QJsonValue& v, const QStringList& path) 10 | { 11 | this->root = root; 12 | this->v = v; 13 | this->path = path; 14 | } 15 | 16 | JsonPointer JsonPointer::operator[](const QString& key) const 17 | { 18 | if (v.isObject() && v.toObject().contains(key)) 19 | return JsonPointer(root, v[key], path + QStringList {key}); 20 | 21 | return JsonPointer(); 22 | } 23 | 24 | JsonPointer JsonPointer::operator[](int index) const 25 | { 26 | if (index >= 0 && v.isArray() && index < v.toArray().size()) 27 | return JsonPointer(root, v[index], path + QStringList {QString::number(index)}); 28 | 29 | return JsonPointer(); 30 | } 31 | 32 | bool JsonPointer::operator==(const JsonPointer& o) const 33 | { 34 | return path == o.path && root == o.root && v == o.v; 35 | } 36 | 37 | JsonPointer JsonPointer::resolve(const QString& str) const 38 | { 39 | auto parts = str.split('/'); 40 | parts.pop_front(); 41 | 42 | QJsonValue v = this->v; 43 | 44 | for (const auto& part: parts) { 45 | if (v.isArray()) { 46 | bool isNumber; 47 | int index = part.toInt(&isNumber); 48 | if (isNumber && index >= 0 && index < v.toArray().size()) 49 | v = v[index]; 50 | else 51 | return JsonPointer(); 52 | 53 | } else if (v.isObject()) { 54 | if (v.toObject().contains(part)) 55 | v = v[part]; 56 | else 57 | return JsonPointer(); 58 | 59 | } else { 60 | return JsonPointer(); 61 | } 62 | } 63 | 64 | return JsonPointer(root, v, path + parts); 65 | } 66 | 67 | bool JsonPointer::isValid() const 68 | { 69 | return !root.isNull(); 70 | } 71 | 72 | QString JsonPointer::toString() const 73 | { 74 | if (isValid()) 75 | return "#/" + path.join('/'); 76 | else 77 | return "(Invalid)"; 78 | } 79 | 80 | QDebug operator<<(QDebug debug, const JsonPointer& o) 81 | { 82 | QDebugStateSaver saver(debug); 83 | debug << o.toString(); 84 | return debug; 85 | } 86 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/pointer/jsonpointer.h: -------------------------------------------------------------------------------- 1 | #ifndef JSONPOINTER_H 2 | #define JSONPOINTER_H 3 | 4 | #include 5 | 6 | class JsonPointer 7 | { 8 | public: 9 | QStringList path; 10 | QJsonValue root; 11 | QJsonValue v; 12 | 13 | public: 14 | explicit JsonPointer(const QJsonValue& root = QJsonValue()); 15 | explicit JsonPointer(const QJsonValue& root, const QJsonValue& v, const QStringList& path); 16 | 17 | JsonPointer operator[](const QString& key) const; 18 | JsonPointer operator[](int index) const; 19 | bool operator==(const JsonPointer& o) const; 20 | JsonPointer resolve(const QString& str) const; 21 | 22 | bool isValid() const; 23 | QString toString() const; 24 | }; 25 | 26 | QDebug operator<<(QDebug debug, const JsonPointer& o); 27 | 28 | #endif // JSONPOINTER_H 29 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/reference-resolver/referenceresolver.h: -------------------------------------------------------------------------------- 1 | #ifndef REFERENCERESOLVER_H 2 | #define REFERENCERESOLVER_H 3 | 4 | #include 5 | #include "../pointer/jsonpointer.h" 6 | 7 | class ReferenceResolver 8 | { 9 | protected: 10 | QStringList subschemaKeywordList; 11 | QStringList subschemaArrayKeywordList; 12 | QStringList subschemaObjectKeywordList; 13 | 14 | QUrl rootUrl; 15 | QHash baseUrlCache; 16 | QHash referenceCache; 17 | QList errors; 18 | 19 | public: 20 | ReferenceResolver(); 21 | virtual void parseSchema(const QJsonValue& root); 22 | JsonPointer resolve(const JsonPointer& ptr) const; 23 | bool isValid() const; 24 | 25 | protected: 26 | virtual void traverseForBaseUrl(QUrl baseUrl, const JsonPointer& ptr); 27 | virtual void traverseForReferences(const JsonPointer& ptr); 28 | virtual JsonPointer resolveString(const QString& ref) const; 29 | }; 30 | 31 | #endif // REFERENCERESOLVER_H 32 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | QJsonValue jsonDocumentToValue(const QJsonDocument& document) 4 | { 5 | if (document.isArray()) 6 | return document.array(); 7 | 8 | if (document.isObject()) 9 | return document.object(); 10 | 11 | return QJsonValue(); 12 | } 13 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include 5 | 6 | QJsonValue jsonDocumentToValue(const QJsonDocument& document); 7 | 8 | #endif // UTILS_H 9 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/validator/jsonschemanodevalidator07.cpp: -------------------------------------------------------------------------------- 1 | #include "jsonschemanodevalidator07.h" 2 | #include "../reference-resolver/referenceresolver.h" 3 | 4 | JsonSchemaNodeValidator07::JsonSchemaNodeValidator07() 5 | { 6 | referenceResolver.reset(new ReferenceResolver()); 7 | } 8 | -------------------------------------------------------------------------------- /vendor/QtJsonSchema/src/validator/jsonschemanodevalidator07.h: -------------------------------------------------------------------------------- 1 | #ifndef JSONSCHEMANODEVALIDATOR07_H 2 | #define JSONSCHEMANODEVALIDATOR07_H 3 | 4 | #include "jsonschemanodevalidator.h" 5 | 6 | class JsonSchemaNodeValidator07 : public JsonSchemaNodeValidator 7 | { 8 | public: 9 | JsonSchemaNodeValidator07(); 10 | }; 11 | 12 | #endif // JSONSCHEMANODEVALIDATOR07_H 13 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/.gitignore: -------------------------------------------------------------------------------- 1 | *.user* 2 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | { 2 | "before_script": [], 3 | "stages": [ 4 | "build" 5 | ], 6 | "build_on_linux_qt5.2_clang": { 7 | "stage": "build", 8 | "script": [ 9 | "bash ~/smart-build.sh --build-system=qbs --toolchain=clang64 --qt=5.2 --clean" 10 | ], 11 | "tags": [ 12 | "linux", 13 | "clang", 14 | "qt5.2", 15 | "smart-build" 16 | ] 17 | }, 18 | "build_on_linux_qt5.9_clang": { 19 | "stage": "build", 20 | "script": [ 21 | "bash ~/smart-build.sh --build-system=qbs --toolchain=clang64 --qt=5.9 --clean" 22 | ], 23 | "tags": [ 24 | "linux", 25 | "clang", 26 | "qt5.9", 27 | "smart-build" 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME QtSuperMacros) 2 | 3 | file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS 4 | *.cpp *.h 5 | ) 6 | 7 | add_library(${TARGET_NAME} ${SOURCES}) 8 | 9 | target_link_libraries(${TARGET_NAME} PUBLIC 10 | Qt5::Core 11 | Qt5::Qml 12 | ) 13 | 14 | target_include_directories(${TARGET_NAME} PUBLIC 15 | . 16 | ) -------------------------------------------------------------------------------- /vendor/QtSuperMacros/LICENSE.md: -------------------------------------------------------------------------------- 1 | How can I use this ? 2 | 3 | Well, license here is pretty "super-open", not even copy-left or copy-right, 4 | basically its close to the WTFPL, just use it as you want, 5 | as it's the most practical to you : 6 | 7 | * if you want to use it as GIT submodule and compile it in your app, do it ; 8 | * if you prefer separate project as a shared library, do it ; 9 | * if you need to modify the project to be able to integrate in you app (opensource or not), do it ; 10 | * if you want to share you work on the library, thanks a lot, but if you don't, no problem ; 11 | * if you think about some weird case I didn't talk about, well, do whatever you want, I don't need to know about it ; 12 | * if you like it so much you want to spread the word, thank you, you're welcome. 13 | 14 | Enjoy ! -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QQmlEnumClassHelper.h: -------------------------------------------------------------------------------- 1 | #ifndef QQMLENUMCLASS 2 | #define QQMLENUMCLASS 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #ifdef Q_ENUM 12 | # define QML_EXPORT_ENUM Q_ENUM 13 | #else 14 | # define QML_EXPORT_ENUM Q_ENUMS 15 | #endif 16 | 17 | #define QML_ENUM_CLASS(NAME, ...) \ 18 | struct NAME { \ 19 | Q_GADGET \ 20 | public: \ 21 | enum Type { \ 22 | __VA_ARGS__ \ 23 | }; \ 24 | QML_EXPORT_ENUM (Type) \ 25 | static QString asString (const int value) { \ 26 | return QString::fromLatin1 (staticMetaObject.enumerator (0).valueToKey (value)); \ 27 | } \ 28 | static void registerQmlModule (const char * uri, const int majorVersion, const int minorVersion, const char * name) { \ 29 | qmlRegisterUncreatableType (uri, majorVersion, minorVersion, name, "Enum class, can't be instanciated !"); \ 30 | } \ 31 | private: \ 32 | explicit NAME (void) { } \ 33 | NAME (const NAME &); \ 34 | NAME & operator= (const NAME &); \ 35 | }; \ 36 | Q_DECLARE_METATYPE (NAME::Type) 37 | 38 | QML_ENUM_CLASS (_Test_QmlEnumClass_) // NOTE : to avoid "no suitable class found" MOC note 39 | 40 | #endif // QQMLENUMCLASS 41 | 42 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QQmlHelpersCommon.h: -------------------------------------------------------------------------------- 1 | #ifndef QQMLHELPERSCOMMON_H 2 | #define QQMLHELPERSCOMMON_H 3 | 4 | #include 5 | 6 | // NOTE : SFINAE trickery to find which type is the cheapest between T and const T & 7 | 8 | template struct CheapestType { typedef const T & type_def; }; 9 | template<> struct CheapestType { typedef bool type_def; }; 10 | template<> struct CheapestType { typedef quint8 type_def; }; 11 | template<> struct CheapestType { typedef quint16 type_def; }; 12 | template<> struct CheapestType { typedef quint32 type_def; }; 13 | template<> struct CheapestType { typedef quint64 type_def; }; 14 | template<> struct CheapestType { typedef qint8 type_def; }; 15 | template<> struct CheapestType { typedef qint16 type_def; }; 16 | template<> struct CheapestType { typedef qint32 type_def; }; 17 | template<> struct CheapestType { typedef qint64 type_def; }; 18 | template<> struct CheapestType { typedef float type_def; }; 19 | template<> struct CheapestType { typedef double type_def; }; 20 | template struct CheapestType { typedef T * type_def; }; 21 | 22 | // NOTE : define to add/remove 'get_' prefix on getters 23 | 24 | #ifdef QTQMLTRICKS_NO_PREFIX_ON_GETTERS 25 | # define MAKE_GETTER_NAME(name) name 26 | #else 27 | # define MAKE_GETTER_NAME(name) get_##name 28 | #endif 29 | 30 | #endif // QQMLHELPERSCOMMON_H 31 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QQmlSingletonHelper.h: -------------------------------------------------------------------------------- 1 | #ifndef QQMLSINGLETONHELPER_H 2 | #define QQMLSINGLETONHELPER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define QML_SINGLETON_IMPL(CLASS) \ 10 | public: \ 11 | static CLASS & instance (void) { \ 12 | static CLASS ret; \ 13 | return ret; \ 14 | } \ 15 | static QObject * qmlSingletonFactory (QQmlEngine * qmlEngine, QJSEngine * jsEngine) { \ 16 | Q_UNUSED (jsEngine) \ 17 | Q_UNUSED (qmlEngine) \ 18 | QObject * ret = &instance (); \ 19 | QQmlEngine::setObjectOwnership (ret, QQmlEngine::CppOwnership); \ 20 | return ret; \ 21 | } \ 22 | static void registerQmlModule (const char * uri, const int majorVersion, const int minorVersion, const char * name) { \ 23 | qmlRegisterSingletonType (uri, majorVersion, minorVersion, name, &CLASS::qmlSingletonFactory); \ 24 | } \ 25 | 26 | class _test_QmlSingleton_ : public QObject { 27 | Q_OBJECT 28 | QML_SINGLETON_IMPL (_test_QmlSingleton_) 29 | }; 30 | 31 | #endif // QQMLSINGLETONHELPER_H 32 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QQmlUniquePtrPropertyHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef QQMLUNIQUEPTRPROPERTYHELPERS_H 2 | #define QQMLUNIQUEPTRPROPERTYHELPERS_H 3 | 4 | #include 5 | 6 | #include 7 | #include "QQmlHelpersCommon.h" 8 | 9 | #define QML_READONLY_UNIQUEPTR_PROPERTY(type, name) \ 10 | protected: \ 11 | Q_PROPERTY (type * name READ MAKE_GETTER_NAME (name) NOTIFY name##Changed) \ 12 | private: \ 13 | std::unique_ptr m_##name; \ 14 | public: \ 15 | type * MAKE_GETTER_NAME (name) (void) const { \ 16 | return m_##name.get(); \ 17 | } \ 18 | public Q_SLOTS: \ 19 | bool update_##name (type * name) { \ 20 | bool ret = false; \ 21 | if ((ret = (m_##name.get() != name))) { \ 22 | m_##name.reset(name); \ 23 | emit name##Changed (m_##name.get()); \ 24 | } \ 25 | return ret; \ 26 | } \ 27 | bool update_##name (std::unique_ptr & name) { \ 28 | bool ret = false; \ 29 | if ((ret = (m_##name.get() != name.get()))) { \ 30 | m_##name = std::move(name); \ 31 | emit name##Changed (m_##name.get()); \ 32 | } \ 33 | return ret; \ 34 | } \ 35 | Q_SIGNALS: \ 36 | void name##Changed (type * name); \ 37 | private: 38 | 39 | 40 | 41 | #endif // QQMLUNIQUEPTRPROPERTYHELPERS_H 42 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QQmlVarPropertyHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef QQMLVARPROPERTYHELPERS 2 | #define QQMLVARPROPERTYHELPERS 3 | 4 | #include 5 | 6 | #include "QQmlHelpersCommon.h" 7 | 8 | #define QML_WRITABLE_VAR_PROPERTY(type, name) \ 9 | protected: \ 10 | Q_PROPERTY (type name READ MAKE_GETTER_NAME (name) WRITE set_##name NOTIFY name##Changed) \ 11 | private: \ 12 | type m_##name; \ 13 | public: \ 14 | type MAKE_GETTER_NAME (name) (void) const { \ 15 | return m_##name ; \ 16 | } \ 17 | public Q_SLOTS: \ 18 | bool set_##name (type name) { \ 19 | bool ret = false; \ 20 | if ((ret = (m_##name != name))) { \ 21 | m_##name = name; \ 22 | emit name##Changed (m_##name); \ 23 | } \ 24 | return ret; \ 25 | } \ 26 | Q_SIGNALS: \ 27 | void name##Changed (type name); \ 28 | private: 29 | 30 | #define QML_READONLY_VAR_PROPERTY(type, name) \ 31 | protected: \ 32 | Q_PROPERTY (type name READ MAKE_GETTER_NAME (name) NOTIFY name##Changed) \ 33 | private: \ 34 | type m_##name; \ 35 | public: \ 36 | type MAKE_GETTER_NAME (name) (void) const { \ 37 | return m_##name ; \ 38 | } \ 39 | bool update_##name (type name) { \ 40 | bool ret = false; \ 41 | if ((ret = (m_##name != name))) { \ 42 | m_##name = name; \ 43 | emit name##Changed (m_##name); \ 44 | } \ 45 | return ret; \ 46 | } \ 47 | Q_SIGNALS: \ 48 | void name##Changed (type name); \ 49 | private: 50 | 51 | #define QML_CONSTANT_VAR_PROPERTY(type, name) \ 52 | protected: \ 53 | Q_PROPERTY (type name READ MAKE_GETTER_NAME (name) CONSTANT) \ 54 | private: \ 55 | type m_##name; \ 56 | public: \ 57 | type MAKE_GETTER_NAME (name) (void) const { \ 58 | return m_##name ; \ 59 | } \ 60 | private: 61 | 62 | class _QmlVarProperty_ : public QObject { 63 | Q_OBJECT 64 | QML_WRITABLE_VAR_PROPERTY (int, var1) 65 | QML_READONLY_VAR_PROPERTY (bool, var2) 66 | QML_CONSTANT_VAR_PROPERTY (QString, var3) 67 | }; 68 | 69 | #endif // QQMLVARPROPERTYHELPERS 70 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QtSuperMacros.pri: -------------------------------------------------------------------------------- 1 | 2 | # Qt super-macros 3 | 4 | QT += core qml 5 | 6 | INCLUDEPATH += $$PWD 7 | 8 | HEADERS += \ 9 | $$PWD/QQmlVarPropertyHelpers.h \ 10 | $$PWD/QQmlPtrPropertyHelpers.h \ 11 | $$PWD/QQmlEnumClassHelper.h \ 12 | $$PWD/QQmlConstRefPropertyHelpers.h \ 13 | $$PWD/QQmlListPropertyHelper.h \ 14 | $$PWD/QQmlAutoPropertyHelpers.h \ 15 | $$PWD/QQmlHelpersCommon.h \ 16 | $$PWD/QQmlSingletonHelper.h \ 17 | $$PWD/QQmlUniquePtrPropertyHelpers.h \ 18 | $$PWD/qtsupermacros.h 19 | 20 | SOURCES += \ 21 | $$PWD/QQmlHelpers.cpp 22 | 23 | DISTFILES += \ 24 | $$PWD/README.md \ 25 | $$PWD/LICENSE.md 26 | 27 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QtSuperMacros.pro: -------------------------------------------------------------------------------- 1 | TARGET = QtSuperMacros 2 | TEMPLATE = lib 3 | CONFIG += static c++14 4 | CONFIG -= debug_and_release debug_and_release_target 5 | 6 | include ($$PWD/QtSuperMacros.pri) 7 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/QtSuperMacros.qbs: -------------------------------------------------------------------------------- 1 | import qbs; 2 | 3 | Project { 4 | name: "Qt super-macros"; 5 | 6 | Product { 7 | name: "libqtqmltricks-qtsupermacros"; 8 | type: "staticlibrary"; 9 | targetName: "QtSuperMacros"; 10 | 11 | Export { 12 | cpp.includePaths: "."; 13 | 14 | Depends { name: "cpp"; } 15 | Depends { 16 | name: "Qt"; 17 | submodules: ["core", "qml"]; 18 | } 19 | } 20 | Depends { name: "cpp"; } 21 | Depends { 22 | name: "Qt"; 23 | submodules: ["core", "qml"]; 24 | } 25 | Group { 26 | name: "C++ sources"; 27 | files: [ 28 | "QQmlHelpers.cpp", 29 | ] 30 | } 31 | Group { 32 | name: "C++ headers"; 33 | files: [ 34 | "QQmlConstRefPropertyHelpers.h", 35 | "QQmlEnumClassHelper.h", 36 | "QQmlListPropertyHelper.h", 37 | "QQmlPtrPropertyHelpers.h", 38 | "QQmlSingletonHelper.h", 39 | "QQmlVarPropertyHelpers.h", 40 | ] 41 | } 42 | Group { 43 | qbs.install: (product.type === "dynamiclibrary"); 44 | fileTagsFilter: product.type; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/README.md: -------------------------------------------------------------------------------- 1 | Qt Super-Macros 2 | =============== 3 | 4 | A set of one-line C++ macros to simplify the creation of reccurent things (like Qt Meta Properties) so that doing them in C++ is not harder than in QML, and requires no boilerplate glue-code. 5 | 6 | ## For one-line creation of QML properties 7 | 8 | * `QML_WRITABLE_***_PROPERTY` : a macro that takes a type and a name, and creates automatically the member attribute, the public getter and setter, and the Qt signal for notifier, and allow use in QML by exposing a read/write `Q_PROPERTY`. 9 | 10 | * `QML_READONLY_***_PROPERTY` : another macro that does almost the same as `QML_WRITABLE_PROPERTY` except that the property is not modifiable from the QML side, only C++ can access the setter. 11 | 12 | * `QML_CONSTANT_***_PROPERTY` : a simplified version of the previous macros, that exposes a constant property with no getter and no setter, from C++ or QML side. 13 | 14 | The `***` can be either `VAR`, `PTR`, `CSTREF`, or `AUTO`. The three first are simple macros that you use by simply passing the non-qualified type (`T`) and it'll add the qualifiers for var (none), pointer (`*`), or constant-reference (`const &`) where needed. The last one in the other hand, uses either `T` or `T*` and it's capable of adding constant-reference by deciding itself which type is the cheapest (using some template trickery internally). 15 | 16 | > INFO : by default, getters are named `get_`, but if you want more Qt-compliant naming (no prefix) you can set the `QTQMLTRICKS_NO_PREFIX_ON_GETTERS` flag in QMake or QBS. 17 | 18 | 19 | ## For easier QQmlListProperty from QList 20 | 21 | * `QML_LIST_PROPERTY` : a really handy macro to create a QML list property that maps to an internal `QList` of objects, without having to declare and implement all static function pointers... 22 | 23 | 24 | ## For simple enum class that can be used in C++ and QML 25 | 26 | * `QML_ENUM_CLASS` : a macro to declare a `QObject` class that only contains a `Q_ENUM` and can be exposed as is to QML. 27 | 28 | 29 | > NOTE : If you want to donate, use this link : [![Flattr this](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=thebootroo&url=http://gitlab.unique-conception.org/qt-qml-tricks/qt-supermacros) 30 | -------------------------------------------------------------------------------- /vendor/QtSuperMacros/qtsupermacros.h: -------------------------------------------------------------------------------- 1 | #ifndef QTSUPERMACROS_H 2 | #define QTSUPERMACROS_H 3 | 4 | #include "QQmlAutoPropertyHelpers.h" 5 | #include "QQmlConstRefPropertyHelpers.h" 6 | #include "QQmlEnumClassHelper.h" 7 | #include "QQmlListPropertyHelper.h" 8 | #include "QQmlPtrPropertyHelpers.h" 9 | #include "QQmlSingletonHelper.h" 10 | #include "QQmlUniquePtrPropertyHelpers.h" 11 | #include "QQmlVarPropertyHelpers.h" 12 | 13 | #endif // QTSUPERMACROS_H 14 | --------------------------------------------------------------------------------