Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ file(MAKE_DIRECTORY ${PROJECT_DESTINATION_RESOURCES_FOLDER})
file(MAKE_DIRECTORY ${PROJECT_DESTINATION_BIN_FOLDER})
file(MAKE_DIRECTORY ${PROJECT_DESTINATION_LOGS_FOLDER})

set_property(GLOBAL PROPERTY PROJECT_LIBS_FOLDER "${PROJECT_LIBS_FOLDER}")
set_property(GLOBAL PROPERTY PROJECT_RESOURCE_FOLDER "${PROJECT_RESOURCE_FOLDER}")
set_property(GLOBAL PROPERTY PROJECT_DESTINATION_FOLDER "${PROJECT_DESTINATION_FOLDER}")
set_property(GLOBAL PROPERTY PROJECT_DESTINATION_RESOURCES_FOLDER "${PROJECT_DESTINATION_RESOURCES_FOLDER}")
set_property(GLOBAL PROPERTY PROJECT_DESTINATION_BIN_FOLDER "${PROJECT_DESTINATION_BIN_FOLDER}")
set_property(GLOBAL PROPERTY PROJECT_DESTINATION_LOGS_FOLDER "${PROJECT_DESTINATION_LOGS_FOLDER}")

# TODO: temporary Qt paths
set(CMAKE_PREFIX_PATH "C:/Qt/5.15.2/mingw81_64" "C:/Qt/Tools/mingw_64")

Expand Down
4 changes: 2 additions & 2 deletions docs/TechTreeJson.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Tech Tree File Format

The tech tree for Generals Zero Hour in GenHotkeys UI is built from the information in the `TechTree.json` file, rather than from the game's ini files, due to the simplification of information retrieval and data loading.
The tech tree for Generals Zero Hour in GenHotkeys UI is built from the information in the `Resources\Profiles\GeneralsZH\TechTree.json` file, rather than from the game's ini files, due to the simplification of information retrieval and data loading.

The tech tree description file is a JSON structure containing a list of factions called `TechTree`, each of which consists of the following fields: `ShortName`, `DisplayName`, `DisplayNameDescription`, and the following lists: `Buildings`, `Infantry`, `Vehicles`, `Aircraft`. Each element in these lists is also a structure with fields `Name` (defines which .webp file should be loaded from the `Resources\Icons` directory), `IngameName` (defines which string from the .csf file should be taken as the object name) and a list of lists `KeyboardLayouts`. These layouts represent the possible combinations of the GUI for a unit or building. Each element in a layout is a structure with two fields: `IconName` (which defines which .webp file should be loaded from the `Resources/Icons` directory) and `HotkeyString` (which defines which string from the .csf file should be used for the hotkey of the action).
The tech tree description file is a JSON structure containing a list of factions called `TechTree`, each of which consists of the following fields: `ShortName`, `DisplayName`, `DisplayNameDescription`, and the following lists: `Buildings`, `Infantry`, `Vehicles`, `Aircraft`. Each element in these lists is also a structure with fields `Name` (defines which .webp file should be loaded from the `Resources\Profiles\GeneralsZH\Images` directory), `IngameName` (defines which string from the .csf file should be taken as the object name) and a list of lists `KeyboardLayouts`. These layouts represent the possible combinations of the GUI for a unit or building. Each element in a layout is a structure with two fields: `IconName` (which defines which .webp file should be loaded from the `Resources\Profiles\GeneralsZH\Images` directory) and `HotkeyString` (which defines which string from the .csf file should be used for the hotkey of the action).

Example:

Expand Down
15 changes: 14 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@
# Declare json files
set(
ADDITIONAL_RESOURCES
"${PROJECT_RESOURCE_FOLDER}/TechTree.json"
"${PROJECT_RESOURCE_FOLDER}/Settings.json"
)

Expand All @@ -163,6 +162,20 @@
)
endforeach()

# Copy profiles
file(
REMOVE_RECURSE
"${PROJECT_DESTINATION_RESOURCES_FOLDER}/Profiles"
"${PROJECT_DESTINATION_RESOURCES_FOLDER}/Icons"
"${PROJECT_DESTINATION_RESOURCES_FOLDER}/Theme"
"${PROJECT_DESTINATION_RESOURCES_FOLDER}/TechTree.json"
)

file(
COPY "${PROJECT_RESOURCE_FOLDER}/Profiles"
DESTINATION ${PROJECT_DESTINATION_RESOURCES_FOLDER}
)

# Create hotkey preset directory
file(MAKE_DIRECTORY ${PROJECT_DESTINATION_RESOURCES_FOLDER}/Presets)

Expand Down
18 changes: 2 additions & 16 deletions src/GUI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# General settings
# Definitions from ../CMakeLists.txt
get_property(PROJECT_DESTINATION_RESOURCES_FOLDER GLOBAL PROPERTY PROJECT_DESTINATION_SOURCES_FOLDER)
get_property(PROJECT_DESTINATION_RESOURCES_FOLDER GLOBAL PROPERTY PROJECT_DESTINATION_RESOURCES_FOLDER)
get_property(PROJECT_RESOURCE_FOLDER GLOBAL PROPERTY PROJECT_RESOURCE_FOLDER)
get_property(PROJECT_LIBS_FOLDER GLOBAL PROPERTY PROJECT_LIBS_FOLDER)

Expand Down Expand Up @@ -121,18 +121,4 @@
# Link the libwebp target to the GUI target
target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_WEBP_TARGET_NAME})

# Copying folders with configs, but without update
# Copy icons
file(
COPY "${PROJECT_RESOURCE_FOLDER}/Icons"
DESTINATION ${PROJECT_DESTINATION_RESOURCES_FOLDER}
)

# Copy theme files
file(
COPY "${PROJECT_RESOURCE_FOLDER}/Theme"
DESTINATION ${PROJECT_DESTINATION_RESOURCES_FOLDER}
)

# Copy Styles.css with updates
configure_file("${PROJECT_RESOURCE_FOLDER}/Theme/Styles.css" "${PROJECT_DESTINATION_RESOURCES_FOLDER}/Theme/Styles.css")
# Profile resources are copied by the root src CMakeLists.txt.
25 changes: 15 additions & 10 deletions src/GUI/WindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,23 @@ WindowManager::WindowManager()

qApp->setWindowIcon(QIcon(QPixmap::fromImage(ImageManager::DecodeEditorWebpIcon())));

LOGMSG("Loading \"" + PROGRAM_CONSTANTS->STYLES_SHEET_FILE + "\"...");
QFile css{PROGRAM_CONSTANTS->STYLES_SHEET_FILE};
if (css.open(QIODevice::ReadOnly))
QString styleSheet;
for (const QString& styleSheetFile : {PROGRAM_CONSTANTS->GLOBAL_STYLES_SHEET_FILE, PROGRAM_CONSTANTS->STYLES_SHEET_FILE})
{
qApp->setStyleSheet(css.readAll());
css.close();
LOGMSG("Styles sheet has been loaded");
}
else
{
LOGMSG("Unable to read the style file");
LOGMSG("Loading \"" + styleSheetFile + "\"...");
QFile css{styleSheetFile};
if (css.open(QIODevice::ReadOnly))
{
styleSheet += QString::fromUtf8(css.readAll()) + "\n";
css.close();
LOGMSG("Styles sheet has been loaded");
}
else
{
LOGMSG("Unable to read the style file");
}
}
qApp->setStyleSheet(styleSheet);

LOGMSG("Loading launch window...");
pStartUpWindow = new SetUpWindowsWrapper();
Expand Down
12 changes: 12 additions & 0 deletions src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ int main(int argc, const char** argv)
if (!filesystem::exists(PROGRAM_CONSTANTS->SETTINGS_FILE.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->SETTINGS_NO_FOUND);

if (!filesystem::exists(PROGRAM_CONSTANTS->PROFILES_FOLDER.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->PROFILES_FOLDER_NO_FOUND);

if (!filesystem::exists(PROGRAM_CONSTANTS->PROFILE_FOLDER.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->PROFILE_FOLDER_NO_FOUND);

if (!filesystem::exists(PROGRAM_CONSTANTS->TECH_TREE_FILE.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->TECH_TREE_NO_FOUND);

Expand All @@ -58,6 +64,12 @@ int main(int argc, const char** argv)
if (!filesystem::exists(PROGRAM_CONSTANTS->THEME_FOLDER.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->THEME_FOLDER_NO_FOUND);

if (!filesystem::exists(PROGRAM_CONSTANTS->GLOBAL_STYLES_SHEET_FILE.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->GLOBAL_STYLES_SHEET_NO_FOUND);

if (!filesystem::exists(PROGRAM_CONSTANTS->STYLES_SHEET_FILE.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->STYLES_SHEET_NO_FOUND);

if (!filesystem::exists(PROGRAM_CONSTANTS->TRANSLATIONS_FOLDER.toStdString().c_str()))
return ShowErrorMessage(PROGRAM_CONSTANTS->TRANSLATIONS_NO_FOUND);

Expand Down
26 changes: 17 additions & 9 deletions src/ProgramConstants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,18 @@ class ProgramConstants
const QString RESOURCE_FOLDER = "Resources";
const QString BINARIES_FOLDER = RESOURCE_FOLDER + "\\Binaries";
const QString TRANSLATIONS_FOLDER = RESOURCE_FOLDER + "/Translations";
const QString ICONS_FOLDER = RESOURCE_FOLDER + "/Icons";
const QString THEME_FOLDER = RESOURCE_FOLDER + "/Theme";
const QString PROFILES_FOLDER = RESOURCE_FOLDER + "/Profiles";
const QString DEFAULT_PROFILE_NAME = "GeneralsZH";
const QString PROFILE_FOLDER = PROFILES_FOLDER + "/" + DEFAULT_PROFILE_NAME;
const QString ICONS_FOLDER = PROFILE_FOLDER + "/Images";
const QString THEME_FOLDER = PROFILE_FOLDER + "/Theme";
const QString QT_ICONS_FOLDER = ":/icons";

// Resource files
const QString TECH_TREE_FILE = RESOURCE_FOLDER + "/TechTree.json";
const QString TECH_TREE_FILE = PROFILE_FOLDER + "/TechTree.json";
const QString SETTINGS_FILE = RESOURCE_FOLDER + "/Settings.json";
const QString STYLES_SHEET_FILE = THEME_FOLDER + "/Styles.css";
const QString GLOBAL_STYLES_SHEET_FILE = PROFILES_FOLDER + "/GlobalStyles.css";
const QString STYLES_SHEET_FILE = THEME_FOLDER + "/Styles.css";

// Build-in files
const QString MISSING_ICON_FILE = QT_ICONS_FOLDER + "/NoImageSmall.webp";
Expand Down Expand Up @@ -80,11 +84,15 @@ class ProgramConstants
const QSize EDITOR_INITIAL_WINDOW_SIZE = QSize(1200, 800);

// Error strings
const QString SETTINGS_NO_FOUND = "Unable to find \"Settings.json\" in \"Resource\" folder.";
const QString TECH_TREE_NO_FOUND = "Unable to find \"TechTree.json\" in \"Resource\" folder.";
const QString THEME_FOLDER_NO_FOUND = "Unable to find \"Resource/Theme\" folder.";
const QString ICONS_FOLDER_NO_FOUND = "Unable to find \"Resource/Icons\" folder.";
const QString TRANSLATIONS_NO_FOUND = "Unable to find \"Resource/Translations\" folder.";
const QString SETTINGS_NO_FOUND = "Unable to find \"" + SETTINGS_FILE + "\".";
const QString PROFILES_FOLDER_NO_FOUND = "Unable to find \"" + PROFILES_FOLDER + "\" folder.";
const QString PROFILE_FOLDER_NO_FOUND = "Unable to find default profile folder \"" + PROFILE_FOLDER + "\".";
const QString TECH_TREE_NO_FOUND = "Unable to find \"" + TECH_TREE_FILE + "\".";
const QString THEME_FOLDER_NO_FOUND = "Unable to find \"" + THEME_FOLDER + "\" folder.";
const QString ICONS_FOLDER_NO_FOUND = "Unable to find \"" + ICONS_FOLDER + "\" folder.";
const QString GLOBAL_STYLES_SHEET_NO_FOUND = "Unable to find \"" + GLOBAL_STYLES_SHEET_FILE + "\".";
const QString STYLES_SHEET_NO_FOUND = "Unable to find \"" + STYLES_SHEET_FILE + "\".";
const QString TRANSLATIONS_NO_FOUND = "Unable to find \"" + TRANSLATIONS_FOLDER + "\" folder.";
const QString UNKNOWN_ERROR = "Unknown error has been occured.";

// Translated error strings
Expand Down
1 change: 1 addition & 0 deletions src/Resources/Profiles/Generals/Images/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Keep the empty profile image directory in source control.
3 changes: 3 additions & 0 deletions src/Resources/Profiles/Generals/TechTree.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"TechTree" : []
}
1 change: 1 addition & 0 deletions src/Resources/Profiles/Generals/Theme/Styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* Profile-specific styles for C&C: Generals can be added here. */
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
/* See more about Qt .css support in documentation and questions: */
/* 1. https://doc.qt.io/qt-5/stylesheet-syntax.html */
/* 2. https://doc.qt.io/qt-5/stylesheet-reference.html */
/* 3. https://doc.qt.io/qt-5/stylesheet-examples.html */
/* 4. https://forum.qt.io/topic/40151/solved-scaled-background-image-using-stylesheet/3 */
/* 5. https://www.qtcentre.org/threads/55152-Is-it-possible-to-logically-combine-dynamic-properties-in-a-Qt-Stylesheet */
/* 6. https://stackoverflow.com/questions/9536725/css-multiple-attribute-selectors/9536746#9536746 */

/* Global style setting */
*
{
font-family: Calibri;
font-size: 10pt;
color: black;
}

QComboBox
{
width: 70px;
Expand Down Expand Up @@ -52,8 +36,8 @@ QComboBox::drop-down
padding-left: 10px;
}

QComboBox::down-arrow { image: url(Resources/Theme/ScrollArrowDown.webp); }
QComboBox::up-arrow { image: url(Resources/Theme/ScrollArrowUp.webp); }
QComboBox::down-arrow { image: url(Resources/Profiles/GeneralsZH/Theme/ScrollArrowDown.webp); }
QComboBox::up-arrow { image: url(Resources/Profiles/GeneralsZH/Theme/ScrollArrowUp.webp); }

/* ↓ Doesn't work */
QComboBox#cmbLanguage { height: 25px; }
Expand Down Expand Up @@ -132,14 +116,14 @@ QPushButton#btnOk
/* Start widgets and SettingsWindow style settings */
LoadFromTheFileWindow, SetUpWindowsWrapper, LoadFromTheGameWindow, SettingsWindow, QWidget#pSettingsWindow
{
border-image: url(Resources/Theme/StartMenuBackground.webp) 0 0 0 0 stretch stretch;
border-image: url(Resources/Profiles/GeneralsZH/Theme/StartMenuBackground.webp) 0 0 0 0 stretch stretch;
background-color: black;
}

/* Editor window style settings */
EditorWindow
{
border-image: url(Resources/Theme/EditorBackground.webp) 0 0 0 0 stretch stretch;
border-image: url(Resources/Profiles/GeneralsZH/Theme/EditorBackground.webp) 0 0 0 0 stretch stretch;
background-color: black;
}

Expand Down Expand Up @@ -195,8 +179,8 @@ QTreeWidget::item

QTreeWidget::item:selected, QTreeWidget::item:selected:!active { background-color: #3543e7; color: white; }

QTreeWidget::branch:open:has-children { background-image: url(Resources/Theme/DropArrowDown.webp); }
QTreeWidget::branch:closed:has-children { background-image: url(Resources/Theme/DropArrowRight.webp); }
QTreeWidget::branch:open:has-children { background-image: url(Resources/Profiles/GeneralsZH/Theme/DropArrowDown.webp); }
QTreeWidget::branch:closed:has-children { background-image: url(Resources/Profiles/GeneralsZH/Theme/DropArrowRight.webp); }

QTabWidget QWidget
{
Expand Down Expand Up @@ -273,7 +257,7 @@ QScrollBar::add-page, QScrollBar::sub-page

QDialog
{
border-image: url(Resources/Theme/StartMenuBackground.webp) 0 0 0 0 stretch stretch;
border-image: url(Resources/Profiles/GeneralsZH/Theme/StartMenuBackground.webp) 0 0 0 0 stretch stretch;
background-color: black;
}

Expand Down
15 changes: 15 additions & 0 deletions src/Resources/Profiles/GlobalStyles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* See more about Qt .css support in documentation and questions: */
/* 1. https://doc.qt.io/qt-5/stylesheet-syntax.html */
/* 2. https://doc.qt.io/qt-5/stylesheet-reference.html */
/* 3. https://doc.qt.io/qt-5/stylesheet-examples.html */
/* 4. https://forum.qt.io/topic/40151/solved-scaled-background-image-using-stylesheet/3 */
/* 5. https://www.qtcentre.org/threads/55152-Is-it-possible-to-logically-combine-dynamic-properties-in-a-Qt-Stylesheet */
/* 6. https://stackoverflow.com/questions/9536725/css-multiple-attribute-selectors/9536746#9536746 */

/* Global style setting */
*
{
font-family: Calibri;
font-size: 10pt;
color: black;
}
Loading