Skip to content

Commit 5711fff

Browse files
committed
Add a Qt-based GUI
There are a few notable differences vs. the CEF-based GUI (aside from general look and feel): - The plugin metadata editor supports editing message content vectors. The string displayed in the message content vector's table cell is (in order of preference) the current language's string, the English text, or an empty string. With this capability, Detail columns have been added for File and dirty info tabs. - It's not possible to select card text to copy it to the clipboard, so instead there's a "Copy Card Content" action in the Plugin menu. - Notifications are displayed in the status bar rather than in a pop-up toast widget. - The toolbar overflow menu items have been moved into menu bar menus. - Plugin cards don't have menus: instead there's a Plugin menu that contains the same actions, which operate on the plugin that's currently selected in the sidebar. - When copying content, it is copied as Markdown equivalent to what is displayed instead of raw JSON data. - The First Time Tips dialog doesn't run if auto-sort is enabled. - Bash Tags are displayed below messages because they're generally of less interest to users, and they're grouped together to hopefully make it more obvious what they are. - Themes are loaded from resources/ui/qss/<theme name>.theme.qss files, instead of resources/ui/css/<theme name>.theme.css files. - Game settings tabs now include an input for setting the game's minimum header version. - Clicking on a plugin in the sidebar selects it, and double-clicking scrolls to its card, instead of single-clicking scrolling to its card and double-clicking opening it in the metadata editor. - The game selection dropdown only lists games that LOOT detects are installed. The icons are the same as used in the CEF GUI. The third-party icons were downloaded as individual SVG files from <https://fonts.google.com/icons>. There are some startup inefficiencies due to sharing code with the CEF-based GUI, when the CEF code is removed the relevant code can be improved.
1 parent 43aa11a commit 5711fff

File tree

110 files changed

+13204
-17
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+13204
-17
lines changed

.github/workflows/ci.yml

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ jobs:
7474
with:
7575
node-version: '16'
7676

77+
- uses: actions/setup-python@v2
78+
with:
79+
python-version: '3.10'
80+
7781
- name: pip cache
7882
uses: actions/cache@v2
7983
with:
@@ -128,20 +132,29 @@ jobs:
128132
libasound2-dev \
129133
libxtst-dev \
130134
libicu-dev \
131-
g++-8
135+
g++-8 \
136+
build-essential \
137+
libgl1-mesa-dev
132138
133139
- name: Download & build Boost
134140
run: |
135141
wget https://raw.githubusercontent.com/Ortham/ci-scripts/2.1.2/install_boost.py
136142
python install_boost.py --directory ~ --boost-version 1.77.0 -a 64 -t gcc-8 locale system
137143
if: steps.boost-cache.outputs.cache-hit != 'true'
138144

145+
- name: Download Qt
146+
id: qt-metadata
147+
run: |
148+
python -m pip install aqtinstall
149+
aqt install-qt linux desktop 6.2.1 gcc_64
150+
echo "::set-output name=root::${{ github.workspace }}/6.2.1/gcc_64"
151+
139152
- name: Run CMake
140153
run: |
141154
mkdir build
142155
cd build
143156
export CXX="g++-8" CC="gcc-8"
144-
cmake .. -DBOOST_ROOT=${{ steps.boost-metadata.outputs.root }} -DBOOST_LIBRARYDIR=${{ steps.boost-metadata.outputs.librarydir }}
157+
cmake .. -DBOOST_ROOT=${{ steps.boost-metadata.outputs.root }} -DBOOST_LIBRARYDIR=${{ steps.boost-metadata.outputs.librarydir }} -DCMAKE_PREFIX_PATH="${{ steps.qt-metadata.outputs.root }}/lib/cmake"
145158
make all
146159
147160
- name: Run C++ tests
@@ -151,10 +164,6 @@ jobs:
151164
git config --global user.name "GitHub"
152165
./loot_gui_tests
153166
154-
- uses: actions/setup-python@v2
155-
with:
156-
python-version: '3.10'
157-
158167
- name: Install packages for building docs
159168
run: |
160169
python -m pip install -r docs/requirements.txt
@@ -203,6 +212,10 @@ jobs:
203212
with:
204213
node-version: '16'
205214

215+
- uses: actions/setup-python@v2
216+
with:
217+
python-version: '3.10'
218+
206219
- name: Get pip cache dir
207220
id: pip-cache-dir-path
208221
run: echo "::set-output name=dir::$(pip cache dir)"
@@ -263,10 +276,17 @@ jobs:
263276
python install_boost.py --directory ${{ github.workspace }} --boost-version 1.77.0 -a 64 locale system
264277
if: steps.boost-cache.outputs.cache-hit != 'true'
265278

279+
- name: Download Qt
280+
id: qt-metadata
281+
run: |
282+
python -m pip install aqtinstall
283+
aqt install-qt windows desktop 6.2.1 win64_msvc2019_64
284+
echo "::set-output name=root::${{ github.workspace }}/6.2.1/msvc2019_64"
285+
266286
- name: Run CMake
267287
run: |
268288
cd build
269-
cmake .. -G "Visual Studio 16 2019" -A x64 -DBOOST_ROOT="${{ steps.boost-metadata.outputs.root }}" -DBOOST_LIBRARYDIR="${{ steps.boost-metadata.outputs.librarydir }}"
289+
cmake .. -G "Visual Studio 16 2019" -A x64 -DBOOST_ROOT="${{ steps.boost-metadata.outputs.root }}" -DBOOST_LIBRARYDIR="${{ steps.boost-metadata.outputs.librarydir }}" -DCMAKE_PREFIX_PATH="${{ steps.qt-metadata.outputs.root }}/lib/cmake"
270290
cmake --build . --config Release
271291
272292
- name: Run C++ tests
@@ -276,10 +296,6 @@ jobs:
276296
git config --global user.name "GitHub"
277297
.\loot_gui_tests.exe
278298
279-
- uses: actions/setup-python@v2
280-
with:
281-
python-version: '3.10'
282-
283299
- name: Install packages for building docs
284300
run: |
285301
python -m pip install -r docs/requirements.txt

.github/workflows/release.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ jobs:
4343
with:
4444
node-version: '16'
4545

46+
- uses: actions/setup-python@v2
47+
with:
48+
python-version: '3.10'
49+
4650
- name: Get Boost metadata
4751
id: boost-metadata
4852
run: |
@@ -75,15 +79,19 @@ jobs:
7579
python install_boost.py --directory ${{ github.workspace }} --boost-version 1.77.0 -a 64 locale system
7680
if: steps.boost-cache.outputs.cache-hit != 'true'
7781

82+
- name: Download Qt
83+
id: qt-metadata
84+
run: |
85+
python -m pip install aqtinstall
86+
aqt install-qt windows desktop 6.2.1 win64_msvc2019_64
87+
echo "::set-output name=root::${{ github.workspace }}/6.2.1/msvc2019_64"
88+
7889
- name: Run CMake
7990
run: |
8091
cd build
81-
cmake .. -G "Visual Studio 16 2019" -A x64 -DBOOST_ROOT="${{ steps.boost-metadata.outputs.root }}" -DBOOST_LIBRARYDIR="${{ steps.boost-metadata.outputs.librarydir }}"
92+
cmake .. -G "Visual Studio 16 2019" -A x64 -DBOOST_ROOT="${{ steps.boost-metadata.outputs.root }}" -DBOOST_LIBRARYDIR="${{ steps.boost-metadata.outputs.librarydir }}" -DCMAKE_PREFIX_PATH="${{ steps.qt-metadata.outputs.root }}/lib/cmake"
8293
cmake --build . --config Release
8394
84-
- uses: actions/setup-python@v2
85-
with:
86-
python-version: '3.10'
8795
8896
- name: Install packages for building docs
8997
run: |

CMakeLists.txt

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required (VERSION 3.6)
1+
cmake_minimum_required (VERSION 3.16)
22
cmake_policy(SET CMP0015 NEW)
33
project (LOOT)
44
include(ExternalProject)
@@ -7,6 +7,10 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
77
set(CMAKE_CXX_STANDARD 17)
88
set(CMAKE_CXX_STANDARD_REQUIRED ON)
99

10+
set(CMAKE_AUTOMOC ON)
11+
set(CMAKE_AUTORCC ON)
12+
set(CMAKE_AUTOUIC ON)
13+
1014
##############################
1115
# Get Build Revision
1216
##############################
@@ -44,6 +48,8 @@ if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
4448
link_directories($ICU_LIBRARY_DIRS)
4549
endif()
4650

51+
find_package(Qt6 COMPONENTS Widgets Network REQUIRED)
52+
4753
ExternalProject_Add(GTest
4854
PREFIX "external"
4955
URL "https://github.com/google/googletest/archive/release-1.11.0.tar.gz"
@@ -164,6 +170,105 @@ set(SPDLOG_INCLUDE_DIRS "${SOURCE_DIR}/include")
164170
# General Settings
165171
##############################
166172

173+
set (LOOT_QT_GUI_SRC "${CMAKE_BINARY_DIR}/generated/version.cpp"
174+
"${CMAKE_SOURCE_DIR}/resources/resources.qrc"
175+
"${CMAKE_SOURCE_DIR}/src/gui/helpers.cpp"
176+
"${CMAKE_SOURCE_DIR}/src/gui/qt/counters.cpp"
177+
"${CMAKE_SOURCE_DIR}/src/gui/qt/filters_states.cpp"
178+
"${CMAKE_SOURCE_DIR}/src/gui/qt/filters_widget.cpp"
179+
"${CMAKE_SOURCE_DIR}/src/gui/qt/general_info.cpp"
180+
"${CMAKE_SOURCE_DIR}/src/gui/qt/general_info_card.cpp"
181+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/edge.cpp"
182+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/groups_editor_dialog.cpp"
183+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/graph_view.cpp"
184+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/node.cpp"
185+
"${CMAKE_SOURCE_DIR}/src/gui/qt/helpers.cpp"
186+
"${CMAKE_SOURCE_DIR}/src/gui/qt/icon_factory.cpp"
187+
"${CMAKE_SOURCE_DIR}/src/gui/qt/main.cpp"
188+
"${CMAKE_SOURCE_DIR}/src/gui/qt/main_window.cpp"
189+
"${CMAKE_SOURCE_DIR}/src/gui/qt/messages_widget.cpp"
190+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_card.cpp"
191+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/delegates.cpp"
192+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/group_tab.cpp"
193+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/message_content_editor.cpp"
194+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/cleaning_data_table_model.cpp"
195+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/file_table_model.cpp"
196+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/location_table_model.cpp"
197+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/message_content_table_model.cpp"
198+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/message_table_model.cpp"
199+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/tag_table_model.cpp"
200+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/plugin_editor_widget.cpp"
201+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/table_tabs.cpp"
202+
"${CMAKE_SOURCE_DIR}/src/gui/plugin_item.cpp"
203+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_item_model.cpp"
204+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_item_filter_model.cpp"
205+
"${CMAKE_SOURCE_DIR}/src/gui/qt/search_dialog.cpp"
206+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/game_tab.cpp"
207+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/general_tab.cpp"
208+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/new_game_dialog.cpp"
209+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/settings_dialog.cpp"
210+
"${CMAKE_SOURCE_DIR}/src/gui/qt/sidebar_plugin_name_delegate.cpp"
211+
"${CMAKE_SOURCE_DIR}/src/gui/qt/style.cpp"
212+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/game.cpp"
213+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/game_settings.cpp"
214+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/helpers.cpp"
215+
"${CMAKE_SOURCE_DIR}/src/gui/state/logging.cpp"
216+
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.cpp"
217+
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_settings.cpp"
218+
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_state.cpp"
219+
"${CMAKE_SOURCE_DIR}/src/gui/resource.rc")
220+
221+
set (LOOT_QT_GUI_HEADERS "${CMAKE_SOURCE_DIR}/src/gui/application_mutex.h"
222+
"${CMAKE_SOURCE_DIR}/src/gui/helpers.h"
223+
"${CMAKE_SOURCE_DIR}/src/gui/qt/counters.h"
224+
"${CMAKE_SOURCE_DIR}/src/gui/qt/filters_states.h"
225+
"${CMAKE_SOURCE_DIR}/src/gui/qt/filters_widget.h"
226+
"${CMAKE_SOURCE_DIR}/src/gui/qt/general_info.h"
227+
"${CMAKE_SOURCE_DIR}/src/gui/qt/general_info_card.h"
228+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/edge.h"
229+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/groups_editor_dialog.h"
230+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/graph_view.h"
231+
"${CMAKE_SOURCE_DIR}/src/gui/qt/groups_editor/node.h"
232+
"${CMAKE_SOURCE_DIR}/src/gui/qt/helpers.h"
233+
"${CMAKE_SOURCE_DIR}/src/gui/qt/icon_factory.h"
234+
"${CMAKE_SOURCE_DIR}/src/gui/qt/main_window.h"
235+
"${CMAKE_SOURCE_DIR}/src/gui/qt/messages_widget.h"
236+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_card.h"
237+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/delegates.h"
238+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/group_tab.h"
239+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/message_content_editor.h"
240+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/cleaning_data_table_model.h"
241+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/file_table_model.h"
242+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/location_table_model.h"
243+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/message_content_table_model.h"
244+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/message_table_model.h"
245+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/models/tag_table_model.h"
246+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/plugin_editor_widget.h"
247+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_editor/table_tabs.h"
248+
"${CMAKE_SOURCE_DIR}/src/gui/plugin_item.h"
249+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_item_model.h"
250+
"${CMAKE_SOURCE_DIR}/src/gui/qt/plugin_item_filter_model.h"
251+
"${CMAKE_SOURCE_DIR}/src/gui/qt/query_worker_thread.h"
252+
"${CMAKE_SOURCE_DIR}/src/gui/qt/search_dialog.h"
253+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/game_tab.h"
254+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/general_tab.h"
255+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/new_game_dialog.h"
256+
"${CMAKE_SOURCE_DIR}/src/gui/qt/settings/settings_dialog.h"
257+
"${CMAKE_SOURCE_DIR}/src/gui/qt/sidebar_plugin_name_delegate.h"
258+
"${CMAKE_SOURCE_DIR}/src/gui/qt/style.h"
259+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/game.h"
260+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/game_detection_error.h"
261+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/game_settings.h"
262+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/games_manager.h"
263+
"${CMAKE_SOURCE_DIR}/src/gui/state/game/helpers.h"
264+
"${CMAKE_SOURCE_DIR}/src/gui/state/logging.h"
265+
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.h"
266+
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_settings.h"
267+
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_state.h"
268+
"${CMAKE_SOURCE_DIR}/src/gui/state/unapplied_change_counter.h"
269+
"${CMAKE_SOURCE_DIR}/src/gui/resource.h"
270+
"${CMAKE_SOURCE_DIR}/src/gui/version.h")
271+
167272
set (LOOT_GUI_SRC "${CMAKE_BINARY_DIR}/generated/version.cpp"
168273
"${CMAKE_SOURCE_DIR}/src/gui/main.cpp"
169274
"${CMAKE_SOURCE_DIR}/src/gui/helpers.cpp"
@@ -308,6 +413,8 @@ IF (CMAKE_COMPILER_IS_GNUCXX)
308413
ENDIF ()
309414

310415
IF (MSVC)
416+
list(APPEND LOOT_QT_GUI_SRC "${CMAKE_SOURCE_DIR}/resources/resources.windows.qrc")
417+
311418
# Turn off permissive mode to be more standards-compliant and avoid compiler errors.
312419
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive-")
313420

@@ -327,6 +434,11 @@ add_executable (LOOT ${LOOT_GUI_SRC} ${LOOT_GUI_HEADERS})
327434
add_dependencies (LOOT cef cpptoml json libloot spdlog)
328435
target_link_libraries(LOOT ${Boost_LIBRARIES} ${CEF_LIBRARIES} ${LIBLOOT_LINK_LIBRARY} ${LOOT_GUI_LIBS} ${ICU_LIBRARIES})
329436

437+
# Build Qt application.
438+
add_executable(LOOT_qt ${LOOT_QT_GUI_SRC} ${LOOT_QT_GUI_HEADERS})
439+
add_dependencies (LOOT_qt cpptoml json libloot spdlog)
440+
target_link_libraries(LOOT_qt PRIVATE Qt6::Widgets Qt6::Network ${Boost_LIBRARIES} ${LIBLOOT_LINK_LIBRARY} ${LOOT_GUI_LIBS} ${ICU_LIBRARIES})
441+
330442
# Build application tests.
331443
add_executable (loot_gui_tests ${LOOT_GUI_TESTS_SRC} ${LOOT_GUI_TESTS_HEADERS})
332444
add_dependencies (loot_gui_tests cpptoml json libloot spdlog GTest testing-plugins)
@@ -343,6 +455,8 @@ IF (MSVC)
343455
set (LOOT_LINK_FLAGS "${EXISTING_LINK_FLAGS} ${LOOT_LINK_FLAGS}")
344456
ENDIF ()
345457
set_target_properties (LOOT PROPERTIES LINK_FLAGS ${LOOT_LINK_FLAGS})
458+
459+
set_target_properties(LOOT_qt PROPERTIES WIN32_EXECUTABLE TRUE)
346460
ENDIF ()
347461

348462
##############################
@@ -356,6 +470,11 @@ IF (CMAKE_SYSTEM_NAME MATCHES "Windows")
356470
COMMAND "mt.exe" -manifest \"${CMAKE_SOURCE_DIR}/src/gui/LOOT.exe.manifest\" -inputresource:"$(TargetDir)$(TargetFileName)"\;\#1 -outputresource:"$(TargetDir)$(TargetFileName)"\;\#1
357471
COMMENT "Adding manifest..."
358472
)
473+
474+
# Copy Qt binaries and resources.
475+
add_custom_command(TARGET LOOT_qt POST_BUILD
476+
COMMAND ${Qt6_DIR}/../../../bin/windeployqt --release $<TARGET_FILE:LOOT_qt>
477+
COMMENT "Running windeployqt...")
359478
ENDIF ()
360479

361480
# Copy CEF binaries.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Parameter | Values | Default |Description
5656
----------|--------|---------|-----------
5757
`LIBLOOT_URL` | A URL | A GitHub release archive URL | The URL to get the libloot release archive from. By default, this is the URL of a libloot release archive hosted on GitHub. Specifying this is useful if you want to link to a libloot that was built and packaged locally.
5858

59-
You may also need to set `BOOST_ROOT` if CMake cannot find Boost.
59+
You may also need to set `BOOST_ROOT` if CMake cannot find Boost, and include Qt's `cmake` directory (e.g. `C:/Qt/6.2.1/msvc2019_64/lib/cmake`) in `CMAKE_PREFIX_PATH` if CMake cannot find Qt.
6060

6161
### Rebuilding the HTML UI
6262

0 commit comments

Comments
 (0)