mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-23 01:55:10 -07:00
Various fixes
Took 14 minutes
This commit is contained in:
parent
4779cc9742
commit
569b531113
15 changed files with 88 additions and 79 deletions
|
|
@ -16,8 +16,8 @@
|
|||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/network/client/remote/remote_client.h>
|
||||
#include <libcockatrice/settings/appearance_settings.h>
|
||||
#include <libcockatrice/settings/interface_settings.h>
|
||||
#include <libcockatrice/settings/paths_settings.h>
|
||||
#include <libcockatrice/utility/qt_utils.h>
|
||||
|
||||
HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
|
||||
: QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice")
|
||||
|
|
@ -50,13 +50,7 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
|
|||
connect(&SettingsCache::instance().appearance(), &AppearanceSettings::homeTabBackgroundShuffleFrequencyChanged,
|
||||
this, &HomeWidget::onBackgroundShuffleFrequencyChanged);
|
||||
|
||||
auto mainWindow = QtUtils::findParentOfType<QMainWindow>(this);
|
||||
|
||||
if (mainWindow) {
|
||||
tutorialController = new TutorialController(mainWindow);
|
||||
} else {
|
||||
tutorialController = new TutorialController(this);
|
||||
}
|
||||
tutorialController = new TutorialController(this);
|
||||
auto sequence = TutorialSequence();
|
||||
sequence.addStep({connectButton, "Connect to a server to play here!"});
|
||||
auto vdeStep = TutorialStep{visualDeckEditorButton, "Create a new deck from cards in the database here!"};
|
||||
|
|
@ -92,7 +86,7 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
|
|||
void HomeWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
QWidget::showEvent(event);
|
||||
if (!tutorialStarted) {
|
||||
if (!tutorialStarted && !SettingsCache::instance().userInterface().getTutorialCompleted()) {
|
||||
tutorialStarted = true;
|
||||
// Start on next event loop iteration so everything is fully painted
|
||||
QTimer::singleShot(3, tutorialController, [this] { tutorialController->start(); });
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include <QWidget>
|
||||
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
||||
|
||||
class TutorialController;
|
||||
|
||||
class HomeWidget : public QWidget
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
#include "tutorial_controller.h"
|
||||
|
||||
#include "../../../../client/settings/cache_settings.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QLineEdit>
|
||||
#include <QMainWindow>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QTextEdit>
|
||||
#include <QTimer>
|
||||
#include <libcockatrice/settings/interface_settings.h>
|
||||
|
||||
TutorialController::TutorialController(QWidget *_tutorializedWidget)
|
||||
: QObject(_tutorializedWidget), tutorializedWidget(_tutorializedWidget)
|
||||
|
|
@ -24,6 +26,18 @@ TutorialController::TutorialController(QWidget *_tutorializedWidget)
|
|||
connect(tutorialOverlay, &TutorialOverlay::targetClicked, this, &TutorialController::handleTargetClicked);
|
||||
}
|
||||
|
||||
TutorialController::~TutorialController()
|
||||
{
|
||||
// The overlay is parented to the top-level window, which outlives the widget
|
||||
// this controller is attached to (e.g. a closed tab), so it must be cleaned
|
||||
// up explicitly when the controller goes away without exitTutorial().
|
||||
if (tutorialOverlay) {
|
||||
tutorialOverlay->hide();
|
||||
tutorialOverlay->deleteLater();
|
||||
}
|
||||
tutorialOverlay = nullptr;
|
||||
}
|
||||
|
||||
void TutorialController::addSequence(const TutorialSequence &seq)
|
||||
{
|
||||
sequences.append(seq);
|
||||
|
|
@ -172,12 +186,15 @@ void TutorialController::prevSequence()
|
|||
void TutorialController::exitTutorial()
|
||||
{
|
||||
cleanupValidationMonitoring();
|
||||
tutorialOverlay->hide();
|
||||
// TODO Maybe not the best idea:
|
||||
tutorialOverlay->deleteLater();
|
||||
if (tutorialOverlay) {
|
||||
tutorialOverlay->hide();
|
||||
tutorialOverlay->deleteLater();
|
||||
}
|
||||
tutorialOverlay = nullptr;
|
||||
currentSequence = -1;
|
||||
currentStep = -1;
|
||||
tutorialCompleted = true;
|
||||
SettingsCache::instance().userInterface().setTutorialCompleted(true);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
|
@ -237,6 +254,7 @@ void TutorialController::showStep()
|
|||
}
|
||||
|
||||
cleanupValidationMonitoring();
|
||||
advanceScheduled = false;
|
||||
|
||||
const auto &step = seq.steps[currentStep];
|
||||
|
||||
|
|
@ -278,13 +296,7 @@ void TutorialController::setupValidationMonitoring()
|
|||
// Handle OnSignal validation - connect to any custom signal
|
||||
if (step.validationTiming == ValidationTiming::OnSignal && step.validator) {
|
||||
if (step.signalSource && step.signalName) {
|
||||
qInfo() << "Setting up signal-based validation for signal:" << step.signalName;
|
||||
validationConnection = connect(step.signalSource, step.signalName, this, SLOT(checkValidation()));
|
||||
if (!validationConnection) {
|
||||
qInfo() << "Warning: Failed to connect to signal" << step.signalName;
|
||||
}
|
||||
} else {
|
||||
qInfo() << "Warning: OnSignal validation timing set but signalSource or signalName is null";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -292,24 +304,17 @@ void TutorialController::setupValidationMonitoring()
|
|||
// Handle OnChange validation - widget-specific
|
||||
if (step.validationTiming == ValidationTiming::OnChange && step.validator) {
|
||||
if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(step.targetWidget)) {
|
||||
qInfo() << "Setting up validation monitoring for QLineEdit";
|
||||
validationConnection =
|
||||
connect(lineEdit, &QLineEdit::textChanged, this, &TutorialController::checkValidation);
|
||||
} else if (QTextEdit *textEdit = qobject_cast<QTextEdit *>(step.targetWidget)) {
|
||||
qInfo() << "Setting up validation monitoring for QTextEdit";
|
||||
validationConnection =
|
||||
connect(textEdit, &QTextEdit::textChanged, this, &TutorialController::checkValidation);
|
||||
} else if (QPlainTextEdit *plainText = qobject_cast<QPlainTextEdit *>(step.targetWidget)) {
|
||||
qInfo() << "Setting up validation monitoring for QPlainTextEdit";
|
||||
validationConnection =
|
||||
connect(plainText, &QPlainTextEdit::textChanged, this, &TutorialController::checkValidation);
|
||||
} else if (QComboBox *combo = qobject_cast<QComboBox *>(step.targetWidget)) {
|
||||
qInfo() << "Setting up validation monitoring for QComboBox";
|
||||
validationConnection = connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&TutorialController::checkValidation);
|
||||
} else {
|
||||
qInfo() << "Warning: OnChange validation timing set but widget type not supported:"
|
||||
<< (step.targetWidget ? step.targetWidget->metaObject()->className() : "null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -317,7 +322,6 @@ void TutorialController::setupValidationMonitoring()
|
|||
void TutorialController::cleanupValidationMonitoring()
|
||||
{
|
||||
if (validationConnection) {
|
||||
qInfo() << "Cleaning up validation connection";
|
||||
disconnect(validationConnection);
|
||||
validationConnection = QMetaObject::Connection();
|
||||
}
|
||||
|
|
@ -325,8 +329,6 @@ void TutorialController::cleanupValidationMonitoring()
|
|||
|
||||
void TutorialController::checkValidation()
|
||||
{
|
||||
qInfo() << "checkValidation() called";
|
||||
|
||||
if (currentSequence < 0 || currentSequence >= sequences.size()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -338,16 +340,18 @@ void TutorialController::checkValidation()
|
|||
|
||||
if (step.validator) {
|
||||
bool isValid = step.validator();
|
||||
qInfo() << "Validation result:" << isValid;
|
||||
|
||||
if (isValid) {
|
||||
// Clear any validation hints
|
||||
tutorialOverlay->showValidationHint("");
|
||||
|
||||
// Auto-advance if enabled
|
||||
if (step.autoAdvanceOnValid) {
|
||||
qInfo() << "Auto-advancing to next step";
|
||||
QTimer::singleShot(500, this, &TutorialController::nextStep);
|
||||
if (step.autoAdvanceOnValid && !advanceScheduled) {
|
||||
advanceScheduled = true;
|
||||
QTimer::singleShot(500, this, [this]() {
|
||||
advanceScheduled = false;
|
||||
nextStep();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class TutorialController : public QObject
|
|||
|
||||
public:
|
||||
explicit TutorialController(QWidget *_tutorializedWidget);
|
||||
~TutorialController() override;
|
||||
|
||||
void addSequence(const TutorialSequence &seq);
|
||||
void start();
|
||||
|
|
@ -95,6 +96,10 @@ private:
|
|||
|
||||
// For OnChange validation monitoring
|
||||
QMetaObject::Connection validationConnection;
|
||||
|
||||
// True while an auto-advance timer is pending, so repeated signal emissions
|
||||
// can't queue more than one advance.
|
||||
bool advanceScheduled = false;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_TUTORIAL_CONTROLLER_H
|
||||
|
|
|
|||
|
|
@ -300,7 +300,9 @@ void TutorialOverlay::recomputeLayout()
|
|||
return;
|
||||
}
|
||||
|
||||
resize(parentWidget()->window()->geometry().size());
|
||||
// The overlay is parented to the top-level window; its client size (rect())
|
||||
// is the visible area, whereas window()->geometry() includes the frame.
|
||||
resize(parentWidget()->size());
|
||||
|
||||
bubble->adjustSize();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue