List unlocked recipes with tooltips in schematic choice dialog instead of unlocked item names
This commit is contained in:
@@ -315,11 +315,11 @@ Modules in `modules.toml` define a `surface_mask` — a list of strings that des
|
|||||||
|
|
||||||
Each option in the dialog displays: the schematic name (ship `id` from `ships.toml`, module `id` from `modules.toml`, or assembler recipe `id` from `recipes.toml`) and the schematic type (ship, module, or assembler recipe). The artifact option (if present) is displayed as a distinct entry with the name "Artifact".
|
Each option in the dialog displays: the schematic name (ship `id` from `ships.toml`, module `id` from `modules.toml`, or assembler recipe `id` from `recipes.toml`) and the schematic type (ship, module, or assembler recipe). The artifact option (if present) is displayed as a distinct entry with the name "Artifact".
|
||||||
|
|
||||||
Each option additionally displays a vertical list of item names labeled "Unlocks recipes for:", showing which recipes would newly become implicitly unlocked (REQ-LOCK-IMPLICIT) if this option were selected — specifically, the output items of miner recipes and assembler recipes (without `unlock_at_station_level`) that are not currently implicitly unlocked but would become so after applying this option's effect:
|
Each option additionally displays a vertical list of recipe names labeled "Unlocks recipes:", showing which miner and assembler recipes would newly become implicitly unlocked (REQ-LOCK-IMPLICIT) if this option were selected — specifically, the miner recipes and assembler recipes (without `unlock_at_station_level`) that are not currently implicitly unlocked but would become so after applying this option's effect:
|
||||||
- For a ship or module schematic, its `materials` are added to the base set per REQ-LOCK-IMPLICIT step 1a before recomputation.
|
- For a ship or module schematic, its `materials` are added to the base set per REQ-LOCK-IMPLICIT step 1a before recomputation.
|
||||||
- For an assembler recipe schematic, its output item is added to the base set per REQ-LOCK-IMPLICIT step 1b before recomputation.
|
- For an assembler recipe schematic, its output item is added to the base set per REQ-LOCK-IMPLICIT step 1b before recomputation.
|
||||||
|
|
||||||
Item names are deduplicated and sorted alphabetically. If no recipes would be newly unlocked, the list shows "None".
|
Each recipe is listed by its `id` (using the same display convention as the assembler recipe-selection dialog), sorted alphabetically. Hovering a recipe in this list displays the recipe info tooltip described for a recipe in REQ-UI-SELECT-TOOLTIP (the recipe name; the name and quantity of each input item; the completion time; and the name and quantity of the produced output item). If no recipes would be newly unlocked, the list shows "None".
|
||||||
|
|
||||||
The player selects one option by clicking it. If the player selects the artifact option, the player's artifact count is incremented by 1 (REQ-WIN-ARTIFACT-COUNT) and the dialog closes; no schematic is applied. Otherwise, the selected schematic is applied and the dialog closes:
|
The player selects one option by clicking it. If the player selects the artifact option, the player's artifact count is incremented by 1 (REQ-WIN-ARTIFACT-COUNT) and the dialog closes; no schematic is applied. Otherwise, the selected schematic is applied and the dialog closes:
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ struct SchematicChoiceOption
|
|||||||
SchematicType type;
|
SchematicType type;
|
||||||
std::string displayName;
|
std::string displayName;
|
||||||
|
|
||||||
// Display names of items produced by recipes that would newly become
|
// Ids of miner/assembler recipes that would newly become implicitly
|
||||||
// implicitly unlocked (REQ-LOCK-IMPLICIT) if this option is selected.
|
// unlocked (REQ-LOCK-IMPLICIT) if this option is selected. Sorted
|
||||||
// Deduplicated and sorted alphabetically; empty if none.
|
// alphabetically by display name; empty if none.
|
||||||
std::vector<std::string> newlyUnlockedItemNames;
|
std::vector<std::string> newlyUnlockedRecipeIds;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -730,7 +730,7 @@ void Simulation::generateSchematicChoices(int destroyedStationLevel)
|
|||||||
|
|
||||||
const UnlockedSets hypothetical = computeUnlockedSets(
|
const UnlockedSets hypothetical = computeUnlockedSets(
|
||||||
hypotheticalShipIds, hypotheticalModuleIds, hypotheticalRecipeSchematicIds);
|
hypotheticalShipIds, hypotheticalModuleIds, hypotheticalRecipeSchematicIds);
|
||||||
option.newlyUnlockedItemNames = computeNewlyUnlockedItemNames(hypothetical);
|
option.newlyUnlockedRecipeIds = computeNewlyUnlockedRecipeIds(hypothetical);
|
||||||
|
|
||||||
m_pendingSchematicChoices.push_back(option);
|
m_pendingSchematicChoices.push_back(option);
|
||||||
}
|
}
|
||||||
@@ -918,23 +918,20 @@ Simulation::UnlockedSets Simulation::computeUnlockedSets(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Simulation::computeNewlyUnlockedItemNames(const UnlockedSets& hypothetical) const
|
std::vector<std::string> Simulation::computeNewlyUnlockedRecipeIds(const UnlockedSets& hypothetical) const
|
||||||
{
|
{
|
||||||
std::set<std::string> itemNames;
|
std::vector<std::string> recipeIds;
|
||||||
for (const std::string& recipeId : hypothetical.recipeIds)
|
for (const std::string& recipeId : hypothetical.recipeIds)
|
||||||
{
|
{
|
||||||
if (m_unlockedRecipeIds.count(recipeId) > 0) { continue; }
|
if (m_unlockedRecipeIds.count(recipeId) > 0) { continue; }
|
||||||
for (const RecipeDef& def : m_config.recipes.recipes)
|
recipeIds.push_back(recipeId);
|
||||||
|
}
|
||||||
|
std::sort(recipeIds.begin(), recipeIds.end(),
|
||||||
|
[](const std::string& lhs, const std::string& rhs)
|
||||||
{
|
{
|
||||||
if (def.id != recipeId) { continue; }
|
return toDisplayName(lhs) < toDisplayName(rhs);
|
||||||
for (const RecipeOutput& out : def.outputs)
|
});
|
||||||
{
|
return recipeIds;
|
||||||
itemNames.insert(toDisplayName(out.item));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::vector<std::string>(itemNames.begin(), itemNames.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Simulation::isRecipeUnlocked(const std::string& recipeId) const
|
bool Simulation::isRecipeUnlocked(const std::string& recipeId) const
|
||||||
|
|||||||
@@ -233,9 +233,9 @@ private:
|
|||||||
// True if every prerequisite in unlockRequires is explicitly unlocked (REQ-LOCK-PREREQ).
|
// True if every prerequisite in unlockRequires is explicitly unlocked (REQ-LOCK-PREREQ).
|
||||||
bool prerequisitesSatisfied(const std::vector<std::string>& unlockRequires) const;
|
bool prerequisitesSatisfied(const std::vector<std::string>& unlockRequires) const;
|
||||||
|
|
||||||
// Display names (deduplicated, alphabetical) of output items of recipes in
|
// Ids (sorted alphabetically by display name) of the recipes in
|
||||||
// hypothetical.recipeIds that are not yet in m_unlockedRecipeIds.
|
// hypothetical.recipeIds that are not yet in m_unlockedRecipeIds.
|
||||||
std::vector<std::string> computeNewlyUnlockedItemNames(const UnlockedSets& hypothetical) const;
|
std::vector<std::string> computeNewlyUnlockedRecipeIds(const UnlockedSets& hypothetical) const;
|
||||||
|
|
||||||
EntityAdmin m_admin;
|
EntityAdmin m_admin;
|
||||||
BeltSystem m_beltSystem;
|
BeltSystem m_beltSystem;
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ TEST_CASE("RecipeSchematic: reset keeps -1 recipes unlocked and their seed items
|
|||||||
// Unlock dialog: newly-unlocked recipe preview (REQ-DEF-SCHEMATIC-DROP)
|
// Unlock dialog: newly-unlocked recipe preview (REQ-DEF-SCHEMATIC-DROP)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
TEST_CASE("RecipeSchematic: newlyUnlockedItemNames is sorted, deduplicated, and empty for level-ups",
|
TEST_CASE("RecipeSchematic: newlyUnlockedRecipeIds is sorted, deduplicated, and empty for level-ups",
|
||||||
"[recipe_schematic]")
|
"[recipe_schematic]")
|
||||||
{
|
{
|
||||||
Simulation sim(loadConfig());
|
Simulation sim(loadConfig());
|
||||||
@@ -295,10 +295,11 @@ TEST_CASE("RecipeSchematic: newlyUnlockedItemNames is sorted, deduplicated, and
|
|||||||
|
|
||||||
for (const SchematicChoiceOption& opt : sim.getPendingSchematicChoices())
|
for (const SchematicChoiceOption& opt : sim.getPendingSchematicChoices())
|
||||||
{
|
{
|
||||||
// Strictly ascending implies sorted and deduplicated.
|
// Strictly ascending display names imply sorted and deduplicated.
|
||||||
for (std::size_t j = 1; j < opt.newlyUnlockedItemNames.size(); ++j)
|
for (std::size_t j = 1; j < opt.newlyUnlockedRecipeIds.size(); ++j)
|
||||||
{
|
{
|
||||||
CHECK(opt.newlyUnlockedItemNames[j - 1] < opt.newlyUnlockedItemNames[j]);
|
CHECK(toDisplayName(opt.newlyUnlockedRecipeIds[j - 1])
|
||||||
|
< toDisplayName(opt.newlyUnlockedRecipeIds[j]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +307,7 @@ TEST_CASE("RecipeSchematic: newlyUnlockedItemNames is sorted, deduplicated, and
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("RecipeSchematic: newlyUnlockedItemNames matches recipes that actually become unlocked",
|
TEST_CASE("RecipeSchematic: newlyUnlockedRecipeIds matches recipes that actually become unlocked",
|
||||||
"[recipe_schematic]")
|
"[recipe_schematic]")
|
||||||
{
|
{
|
||||||
Simulation sim(loadConfig());
|
Simulation sim(loadConfig());
|
||||||
@@ -336,21 +337,22 @@ TEST_CASE("RecipeSchematic: newlyUnlockedItemNames matches recipes that actually
|
|||||||
|
|
||||||
SimulationTestAccess::applySchematicChoice(sim, 0);
|
SimulationTestAccess::applySchematicChoice(sim, 0);
|
||||||
|
|
||||||
std::set<std::string> expectedNames;
|
std::vector<std::string> expected;
|
||||||
for (const RecipeDef& def : cfg.recipes.recipes)
|
for (const RecipeDef& def : cfg.recipes.recipes)
|
||||||
{
|
{
|
||||||
if ((def.building == BuildingType::Miner || def.building == BuildingType::Assembler)
|
if ((def.building == BuildingType::Miner || def.building == BuildingType::Assembler)
|
||||||
&& sim.isRecipeUnlocked(def.id) && unlockedBefore.count(def.id) == 0)
|
&& sim.isRecipeUnlocked(def.id) && unlockedBefore.count(def.id) == 0)
|
||||||
{
|
{
|
||||||
for (const RecipeOutput& out : def.outputs)
|
expected.push_back(def.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(expected.begin(), expected.end(),
|
||||||
|
[](const std::string& lhs, const std::string& rhs)
|
||||||
{
|
{
|
||||||
expectedNames.insert(toDisplayName(out.item));
|
return toDisplayName(lhs) < toDisplayName(rhs);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
const std::vector<std::string> expected(expectedNames.begin(), expectedNames.end());
|
|
||||||
|
|
||||||
REQUIRE(choice.newlyUnlockedItemNames == expected);
|
REQUIRE(choice.newlyUnlockedRecipeIds == expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ SET(HDRS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipStatsPanel.h
|
${CMAKE_CURRENT_SOURCE_DIR}/ShipStatsPanel.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/SchematicChoiceDialog.h
|
${CMAKE_CURRENT_SOURCE_DIR}/SchematicChoiceDialog.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/RecipeSelectionDialog.h
|
${CMAKE_CURRENT_SOURCE_DIR}/RecipeSelectionDialog.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/RecipeTooltip.h
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,5 +31,6 @@ SET(SRCS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/ShipStatsPanel.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/ShipStatsPanel.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/SchematicChoiceDialog.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/SchematicChoiceDialog.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/RecipeSelectionDialog.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/RecipeSelectionDialog.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/RecipeTooltip.cpp
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ void MainWindow::handleEvent(std::shared_ptr<const SchematicChoicesAvailableEven
|
|||||||
const double prevSpeed = m_gameWorldView->gameSpeed();
|
const double prevSpeed = m_gameWorldView->gameSpeed();
|
||||||
m_gameWorldView->setGameSpeed(0.0);
|
m_gameWorldView->setGameSpeed(0.0);
|
||||||
|
|
||||||
SchematicChoiceDialog dialog(event->choices, this);
|
SchematicChoiceDialog dialog(event->choices, m_sim->config().recipes, this);
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
|
|
||||||
std::shared_ptr<ApplySchematicChoiceCommand> command =
|
std::shared_ptr<ApplySchematicChoiceCommand> command =
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "DisplayName.h"
|
#include "DisplayName.h"
|
||||||
#include "GameConfig.h"
|
#include "GameConfig.h"
|
||||||
#include "RecipesConfig.h"
|
#include "RecipesConfig.h"
|
||||||
|
#include "RecipeTooltip.h"
|
||||||
#include "ShipsConfig.h"
|
#include "ShipsConfig.h"
|
||||||
#include "Simulation.h"
|
#include "Simulation.h"
|
||||||
|
|
||||||
@@ -25,39 +26,6 @@ QString itemLine(const std::string& itemId, int amount)
|
|||||||
+ QStringLiteral(" ×") + QString::number(amount);
|
+ QStringLiteral(" ×") + QString::number(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString recipeTooltip(const RecipeDef& recipe)
|
|
||||||
{
|
|
||||||
QStringList lines;
|
|
||||||
lines << QObject::tr("Recipe: %1")
|
|
||||||
.arg(QString::fromStdString(toDisplayName(recipe.id)));
|
|
||||||
|
|
||||||
if (recipe.inputs.empty())
|
|
||||||
{
|
|
||||||
lines << QObject::tr("Inputs: none");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lines << QObject::tr("Inputs:");
|
|
||||||
for (const RecipeIngredient& ingredient : recipe.inputs)
|
|
||||||
{
|
|
||||||
lines << itemLine(ingredient.item, ingredient.amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lines << QObject::tr("Completion time: %1 s").arg(recipe.durationSeconds);
|
|
||||||
|
|
||||||
if (!recipe.outputs.empty())
|
|
||||||
{
|
|
||||||
lines << QObject::tr("Produces:");
|
|
||||||
for (const RecipeOutput& output : recipe.outputs)
|
|
||||||
{
|
|
||||||
lines << itemLine(output.item, output.amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
QString shipTooltip(const ShipDef& def)
|
QString shipTooltip(const ShipDef& def)
|
||||||
{
|
{
|
||||||
const QString name = QString::fromStdString(toDisplayName(def.id));
|
const QString name = QString::fromStdString(toDisplayName(def.id));
|
||||||
@@ -116,7 +84,7 @@ std::vector<RecipeSelectionOption> buildRecipeSelectionOptions(
|
|||||||
}
|
}
|
||||||
options.push_back({recipe.id,
|
options.push_back({recipe.id,
|
||||||
QString::fromStdString(toDisplayName(recipe.id)),
|
QString::fromStdString(toDisplayName(recipe.id)),
|
||||||
recipeTooltip(recipe)});
|
buildRecipeTooltip(recipe)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
src/ui/RecipeTooltip.cpp
Normal file
52
src/ui/RecipeTooltip.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "RecipeTooltip.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "DisplayName.h"
|
||||||
|
#include "RecipesConfig.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
QString itemLine(const std::string& itemId, int amount)
|
||||||
|
{
|
||||||
|
return QStringLiteral(" ")
|
||||||
|
+ QString::fromStdString(toDisplayName(itemId))
|
||||||
|
+ QStringLiteral(" ×") + QString::number(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
QString buildRecipeTooltip(const RecipeDef& recipe)
|
||||||
|
{
|
||||||
|
QStringList lines;
|
||||||
|
lines << QObject::tr("Recipe: %1")
|
||||||
|
.arg(QString::fromStdString(toDisplayName(recipe.id)));
|
||||||
|
|
||||||
|
if (recipe.inputs.empty())
|
||||||
|
{
|
||||||
|
lines << QObject::tr("Inputs: none");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lines << QObject::tr("Inputs:");
|
||||||
|
for (const RecipeIngredient& ingredient : recipe.inputs)
|
||||||
|
{
|
||||||
|
lines << itemLine(ingredient.item, ingredient.amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines << QObject::tr("Completion time: %1 s").arg(recipe.durationSeconds);
|
||||||
|
|
||||||
|
if (!recipe.outputs.empty())
|
||||||
|
{
|
||||||
|
lines << QObject::tr("Produces:");
|
||||||
|
for (const RecipeOutput& output : recipe.outputs)
|
||||||
|
{
|
||||||
|
lines << itemLine(output.item, output.amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
11
src/ui/RecipeTooltip.h
Normal file
11
src/ui/RecipeTooltip.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
struct RecipeDef;
|
||||||
|
|
||||||
|
// Builds the recipe info tooltip text (REQ-UI-SELECT-TOOLTIP): the recipe name,
|
||||||
|
// each input item name and quantity, the completion time, and the produced
|
||||||
|
// output item name and quantity. Shared by the recipe-selection dialog and the
|
||||||
|
// schematic choice dialog's "Unlocks recipes:" list so both render identically.
|
||||||
|
QString buildRecipeTooltip(const RecipeDef& recipe);
|
||||||
@@ -3,11 +3,29 @@
|
|||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QStringList>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "DisplayName.h"
|
||||||
|
#include "RecipeTooltip.h"
|
||||||
|
#include "RecipesConfig.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
const RecipeDef* findRecipe(const RecipesConfig& recipes, const std::string& id)
|
||||||
|
{
|
||||||
|
for (const RecipeDef& recipe : recipes.recipes)
|
||||||
|
{
|
||||||
|
if (recipe.id == id) { return &recipe; }
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
SchematicChoiceDialog::SchematicChoiceDialog(
|
SchematicChoiceDialog::SchematicChoiceDialog(
|
||||||
const std::vector<SchematicChoiceOption>& options,
|
const std::vector<SchematicChoiceOption>& options,
|
||||||
|
const RecipesConfig& recipes,
|
||||||
QWidget* parent)
|
QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, m_chosenIndex(0)
|
, m_chosenIndex(0)
|
||||||
@@ -70,30 +88,33 @@ SchematicChoiceDialog::SchematicChoiceDialog(
|
|||||||
typeLabel->setAlignment(Qt::AlignCenter);
|
typeLabel->setAlignment(Qt::AlignCenter);
|
||||||
cardLayout->addWidget(typeLabel);
|
cardLayout->addWidget(typeLabel);
|
||||||
|
|
||||||
QLabel* unlocksHeaderLabel = new QLabel(tr("Unlocks recipes for:"), card);
|
QLabel* unlocksHeaderLabel = new QLabel(tr("Unlocks recipes:"), card);
|
||||||
QFont unlocksHeaderFont = unlocksHeaderLabel->font();
|
QFont unlocksHeaderFont = unlocksHeaderLabel->font();
|
||||||
unlocksHeaderFont.setBold(true);
|
unlocksHeaderFont.setBold(true);
|
||||||
unlocksHeaderLabel->setFont(unlocksHeaderFont);
|
unlocksHeaderLabel->setFont(unlocksHeaderFont);
|
||||||
unlocksHeaderLabel->setAlignment(Qt::AlignCenter);
|
unlocksHeaderLabel->setAlignment(Qt::AlignCenter);
|
||||||
cardLayout->addWidget(unlocksHeaderLabel);
|
cardLayout->addWidget(unlocksHeaderLabel);
|
||||||
|
|
||||||
QString unlocksText;
|
if (option.newlyUnlockedRecipeIds.empty())
|
||||||
if (option.newlyUnlockedItemNames.empty())
|
|
||||||
{
|
{
|
||||||
unlocksText = tr("None");
|
QLabel* noneLabel = new QLabel(tr("None"), card);
|
||||||
|
noneLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
cardLayout->addWidget(noneLabel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QStringList itemLines;
|
for (const std::string& recipeId : option.newlyUnlockedRecipeIds)
|
||||||
for (const std::string& itemName : option.newlyUnlockedItemNames)
|
|
||||||
{
|
{
|
||||||
itemLines << QString::fromStdString(itemName);
|
QLabel* recipeLabel = new QLabel(
|
||||||
|
QString::fromStdString(toDisplayName(recipeId)), card);
|
||||||
|
recipeLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
if (const RecipeDef* def = findRecipe(recipes, recipeId))
|
||||||
|
{
|
||||||
|
recipeLabel->setToolTip(buildRecipeTooltip(*def));
|
||||||
|
}
|
||||||
|
cardLayout->addWidget(recipeLabel);
|
||||||
}
|
}
|
||||||
unlocksText = itemLines.join("\n");
|
|
||||||
}
|
}
|
||||||
QLabel* unlocksLabel = new QLabel(unlocksText, card);
|
|
||||||
unlocksLabel->setAlignment(Qt::AlignCenter);
|
|
||||||
cardLayout->addWidget(unlocksLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPushButton* selectButton = new QPushButton(tr("Select"), card);
|
QPushButton* selectButton = new QPushButton(tr("Select"), card);
|
||||||
|
|||||||
@@ -6,12 +6,15 @@
|
|||||||
|
|
||||||
#include "SchematicChoiceOption.h"
|
#include "SchematicChoiceOption.h"
|
||||||
|
|
||||||
|
struct RecipesConfig;
|
||||||
|
|
||||||
class SchematicChoiceDialog : public QDialog
|
class SchematicChoiceDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SchematicChoiceDialog(const std::vector<SchematicChoiceOption>& options,
|
SchematicChoiceDialog(const std::vector<SchematicChoiceOption>& options,
|
||||||
|
const RecipesConfig& recipes,
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
|
|
||||||
int getChosenIndex() const;
|
int getChosenIndex() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user