mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 09:05:10 -07:00
[Tabs] Add a setting to define startup tab on application launch (#7121)
* [Tabs] Add a setting to define startup tab on application launch. Took 29 minutes * Naming and sizing Took 4 minutes --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
parent
fbe5c4ade0
commit
16b6132701
14 changed files with 599 additions and 3 deletions
|
|
@ -396,6 +396,8 @@ set(cockatrice_SOURCES
|
|||
src/interface/intents/intent_join_server_room.h
|
||||
src/interface/intents/intent_login.cpp
|
||||
src/interface/intents/intent_login.h
|
||||
src/interface/intents/intent_open_server_room_by_name.cpp
|
||||
src/interface/intents/intent_open_server_room_by_name.h
|
||||
src/interface/intents/url_parser.cpp
|
||||
src/interface/intents/url_parser.h
|
||||
src/interface/widgets/server/user/user_info_popup.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,183 @@
|
|||
#include "intent_open_server_room_by_name.h"
|
||||
|
||||
#include "../widgets/tabs/tab_room.h"
|
||||
#include "../widgets/tabs/tab_supervisor.h"
|
||||
#include "intent_connect_to_server.h"
|
||||
|
||||
#include <libcockatrice/protocol/pb/event_list_rooms.pb.h>
|
||||
#include <libcockatrice/protocol/pb/response_join_room.pb.h>
|
||||
#include <libcockatrice/protocol/pb/session_commands.pb.h>
|
||||
#include <libcockatrice/protocol/pending_command.h>
|
||||
|
||||
IntentOpenServerRoomByName::IntentOpenServerRoomByName(TabSupervisor *_tabSupervisor,
|
||||
RemoteClient *_remoteClient,
|
||||
std::unique_ptr<ContextJoinRoom> _context,
|
||||
const QString &_roomName)
|
||||
: Intent(), tabSupervisor(_tabSupervisor), remoteClient(_remoteClient), context(_context.release()),
|
||||
roomName(_roomName)
|
||||
{
|
||||
checkTimer.setInterval(250);
|
||||
connect(&checkTimer, &QTimer::timeout, this, [this]() {
|
||||
if (selectOpenRoom()) {
|
||||
checkTimer.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool IntentOpenServerRoomByName::checkPrecondition() const
|
||||
{
|
||||
if (remoteClient->getStatus() != ClientStatus::StatusLoggedIn) {
|
||||
return false;
|
||||
}
|
||||
// peerPort() reflects the actual TCP peer, which may differ from the
|
||||
// configured server port (e.g. when connecting through a proxy), so only
|
||||
// the hostname is compared here.
|
||||
if (remoteClient->peerName() != context->serverContext.hostname) {
|
||||
return false;
|
||||
}
|
||||
if (QString::number(remoteClient->peerPort()) != context->serverContext.port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IntentOpenServerRoomByName::onPreconditionSatisfied()
|
||||
{
|
||||
if (listening) {
|
||||
return;
|
||||
}
|
||||
listening = true;
|
||||
|
||||
if (selectOpenRoom()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The room selector is the component that requests the room list, so the
|
||||
// server tab must exist for the room to be resolved by name.
|
||||
if (!tabSupervisor->getTabServer()) {
|
||||
tabSupervisor->openTabServer();
|
||||
}
|
||||
if (!tabSupervisor->getTabServer()) {
|
||||
emitFailed(tr("No server tab available"));
|
||||
return;
|
||||
}
|
||||
|
||||
connect(remoteClient, &RemoteClient::listRoomsEventReceived, this, &IntentOpenServerRoomByName::processListRooms);
|
||||
connect(remoteClient, &RemoteClient::statusChanged, this, &IntentOpenServerRoomByName::onClientStatusChanged);
|
||||
|
||||
// The room tab may be opened by our own join, by the room selector's auto-join, or by a
|
||||
// join that was already in flight. Poll until it shows up.
|
||||
checkTimer.start();
|
||||
|
||||
// While no join has been sent yet, keep the room list fresh: the list may have been
|
||||
// requested before we subscribed to it, or a response may have been dropped during a
|
||||
// busy login burst. A stale list would otherwise leave the room unresolved forever.
|
||||
connect(&refreshTimer, &QTimer::timeout, this, [this]() {
|
||||
if (!joinPending) {
|
||||
remoteClient->sendCommand(remoteClient->prepareSessionCommand(Command_ListRooms()));
|
||||
}
|
||||
});
|
||||
refreshTimer.setInterval(5000);
|
||||
refreshTimer.start();
|
||||
|
||||
// Last-resort failure for "the room genuinely is not in a fresh list". This must NOT
|
||||
// fire while a join is in flight: a loaded server may take longer than that to answer
|
||||
// during a login burst, and killing the intent early would leave the connection
|
||||
// registered in the room with no tab to display it and every later join attempt
|
||||
// would then be rejected with RespContextError.
|
||||
QTimer::singleShot(20000, this, [this]() {
|
||||
if (!joinPending) {
|
||||
emitFailed(tr("Timed out while looking for the server room %1").arg(roomName));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IntentOpenServerRoomByName::onPreconditionNotSatisfied()
|
||||
{
|
||||
runDependency(new IntentConnectToServer(remoteClient, &context->serverContext));
|
||||
}
|
||||
|
||||
void IntentOpenServerRoomByName::onClientStatusChanged(ClientStatus status)
|
||||
{
|
||||
if (status != ClientStatus::StatusLoggedIn) {
|
||||
emitFailed(tr("Disconnected while looking for the server room %1").arg(roomName));
|
||||
}
|
||||
}
|
||||
|
||||
bool IntentOpenServerRoomByName::selectOpenRoom()
|
||||
{
|
||||
const auto &roomTabs = tabSupervisor->getRoomTabs();
|
||||
for (auto i = roomTabs.cbegin(), end = roomTabs.cend(); i != end; ++i) {
|
||||
TabRoom *room = i.value();
|
||||
if (room->getRoomName() == roomName) {
|
||||
tabSupervisor->setCurrentWidget(room);
|
||||
emitFinished();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IntentOpenServerRoomByName::processListRooms(const Event_ListRooms &event)
|
||||
{
|
||||
if (selectOpenRoom()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < event.room_list_size(); ++i) {
|
||||
const ServerInfo_Room &room = event.room_list(i);
|
||||
if (room.has_name() && QString::fromStdString(room.name()) == roomName) {
|
||||
openRoom(room);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntentOpenServerRoomByName::openRoom(const ServerInfo_Room &roomInfo)
|
||||
{
|
||||
if (joinPending) {
|
||||
return;
|
||||
}
|
||||
joinPending = true;
|
||||
|
||||
// Rooms flagged auto_join are joined by the room selector automatically. Sending our own
|
||||
// Command_JoinRoom on top of that would be answered with RespContextError.
|
||||
if (roomInfo.has_auto_join() && roomInfo.auto_join()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Command_JoinRoom cmd;
|
||||
cmd.set_room_id(roomInfo.room_id());
|
||||
PendingCommand *pend = remoteClient->prepareSessionCommand(cmd);
|
||||
connect(pend, &PendingCommand::finished, this,
|
||||
[this](const Response &r, const CommandContainer &, const QVariant &) { handleJoinResponse(r); });
|
||||
remoteClient->sendCommand(pend);
|
||||
}
|
||||
|
||||
void IntentOpenServerRoomByName::handleJoinResponse(const Response &response)
|
||||
{
|
||||
switch (response.response_code()) {
|
||||
case Response::RespOk: {
|
||||
const Response_JoinRoom &resp = response.GetExtension(Response_JoinRoom::ext);
|
||||
if (!tabSupervisor->getRoomTabs().contains(resp.room_info().room_id())) {
|
||||
tabSupervisor->addRoomTab(resp.room_info(), true);
|
||||
}
|
||||
emitFinished();
|
||||
return;
|
||||
}
|
||||
case Response::RespNameNotFound:
|
||||
emitFailed(tr("Failed to join the server room %1: it doesn't exist on the server.").arg(roomName));
|
||||
return;
|
||||
case Response::RespUserLevelTooLow:
|
||||
emitFailed(tr("You do not have the required permission to join the server room %1.").arg(roomName));
|
||||
return;
|
||||
case Response::RespContextError:
|
||||
// The room was already joined by someone else (e.g. the room selector's
|
||||
// auto-join). It will show up in the room tabs shortly, so keep waiting.
|
||||
return;
|
||||
default:
|
||||
emitFailed(tr("Failed to join the server room %1 due to an unknown error.").arg(roomName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef COCKATRICE_INTENT_OPEN_SERVER_ROOM_BY_NAME_H
|
||||
#define COCKATRICE_INTENT_OPEN_SERVER_ROOM_BY_NAME_H
|
||||
|
||||
#include "contexts/context_join_room.h"
|
||||
#include "intent.h"
|
||||
#include "remote_client.h"
|
||||
|
||||
#include <QScopedPointer>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
|
||||
class TabRoom;
|
||||
class TabSupervisor;
|
||||
class Event_ListRooms;
|
||||
class ServerInfo_Room;
|
||||
|
||||
/**
|
||||
* @brief Connects to the configured server and opens a room identified by its name.
|
||||
*
|
||||
* Room ids are assigned by the server per session, so the room is resolved by name from the
|
||||
* room list once the client is logged in. If the room is already open it is simply selected.
|
||||
*
|
||||
* The join itself is sent directly through the client instead of `TabServer::joinRoom`, so a
|
||||
* failed join only fails the intent silently instead of popping a modal error box during
|
||||
* startup. Success is routed to `TabSupervisor::addRoomTab`, the same tab-creation machinery
|
||||
* the normal join flow uses.
|
||||
*/
|
||||
class IntentOpenServerRoomByName : public Intent
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IntentOpenServerRoomByName(TabSupervisor *_tabSupervisor,
|
||||
RemoteClient *_remoteClient,
|
||||
std::unique_ptr<ContextJoinRoom> _context,
|
||||
const QString &_roomName);
|
||||
|
||||
protected:
|
||||
bool checkPrecondition() const override;
|
||||
void onPreconditionSatisfied() override;
|
||||
void onPreconditionNotSatisfied() override;
|
||||
|
||||
private:
|
||||
void processListRooms(const Event_ListRooms &event);
|
||||
void openRoom(const ServerInfo_Room &roomInfo);
|
||||
void handleJoinResponse(const Response &response);
|
||||
void onClientStatusChanged(ClientStatus status);
|
||||
bool selectOpenRoom();
|
||||
|
||||
TabSupervisor *tabSupervisor;
|
||||
RemoteClient *remoteClient;
|
||||
QScopedPointer<ContextJoinRoom> context;
|
||||
QString roomName;
|
||||
bool listening = false;
|
||||
bool joinPending = false;
|
||||
QTimer checkTimer;
|
||||
QTimer refreshTimer;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_INTENT_OPEN_SERVER_ROOM_BY_NAME_H
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "../../../client/settings/cache_settings.h"
|
||||
#include "../main.h"
|
||||
#include "../server/user/user_info_connection.h"
|
||||
#include "update/client/release_channel.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
|
@ -11,6 +12,7 @@
|
|||
#include <QTranslator>
|
||||
#include <libcockatrice/settings/paths_settings.h>
|
||||
#include <libcockatrice/settings/personal_settings.h>
|
||||
#include <libcockatrice/settings/tabs_settings.h>
|
||||
#include <libcockatrice/settings/updates_settings.h>
|
||||
#include <libcockatrice/utility/macros.h>
|
||||
|
||||
|
|
@ -121,8 +123,61 @@ GeneralSettingsPage::GeneralSettingsPage()
|
|||
|
||||
connect(&showTipsOnStartup, &QCheckBox::clicked, &settings.personal(), &PersonalSettings::setShowTipsOnStartup);
|
||||
|
||||
// startup destination
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
startupTabSelector.addItem(""); // texts set in retranslateUi
|
||||
}
|
||||
startupTabSelector.setCurrentIndex(settings.tabs().getStartupTabIndex());
|
||||
|
||||
connect(&startupTabSelector, qOverload<int>(&QComboBox::currentIndexChanged), &settings.tabs(),
|
||||
&TabsSettings::setStartupTabIndex);
|
||||
connect(&startupTabSelector, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&GeneralSettingsPage::updateStartupServerControlsVisibility);
|
||||
|
||||
const QString savedHost = settings.tabs().getStartupServerHost();
|
||||
const QString savedPort = settings.tabs().getStartupServerPort();
|
||||
int startupServerIndex = -1;
|
||||
UserConnection_Information uci;
|
||||
for (const auto &savedServer : uci.getServerInfo()) {
|
||||
const UserConnection_Information &info = savedServer.second;
|
||||
const QString saveName = info.getSaveName();
|
||||
if (saveName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
startupServerSelector.addItem(saveName, QVariantList{info.getServer(), info.getPort()});
|
||||
if (startupServerIndex == -1 && info.getServer() == savedHost && info.getPort() == savedPort) {
|
||||
startupServerIndex = startupServerSelector.count() - 1;
|
||||
}
|
||||
}
|
||||
startupServerSelector.setCurrentIndex(startupServerIndex);
|
||||
|
||||
connect(&startupServerSelector, qOverload<int>(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
const QVariantList serverInfo = startupServerSelector.itemData(index).toList();
|
||||
if (serverInfo.size() != 2) {
|
||||
return;
|
||||
}
|
||||
TabsSettings &tabs = SettingsCache::instance().tabs();
|
||||
tabs.setStartupServerHost(serverInfo[0].toString());
|
||||
tabs.setStartupServerPort(serverInfo[1].toString());
|
||||
});
|
||||
|
||||
startupRoomNameEdit = new QLineEdit(settings.tabs().getStartupRoomName());
|
||||
// Default (Expanding) would stretch the whole controls column when this row becomes visible,
|
||||
// so size it like the combo boxes instead: fills the column, never widens it.
|
||||
startupRoomNameEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
connect(startupRoomNameEdit, &QLineEdit::editingFinished, this,
|
||||
[this] { SettingsCache::instance().tabs().setStartupRoomName(startupRoomNameEdit->text().trimmed()); });
|
||||
|
||||
auto *startupGrid = new QGridLayout;
|
||||
startupGrid->addWidget(&showTipsOnStartup, 0, 0, 1, 2);
|
||||
startupGrid->addWidget(&startupTabLabel, 1, 0);
|
||||
startupGrid->addWidget(&startupTabSelector, 1, 1);
|
||||
startupGrid->addWidget(&startupServerLabel, 2, 0);
|
||||
startupGrid->addWidget(&startupServerSelector, 2, 1);
|
||||
startupGrid->addWidget(&startupRoomLabel, 3, 0);
|
||||
startupGrid->addWidget(startupRoomNameEdit, 3, 1);
|
||||
|
||||
updateStartupServerControlsVisibility();
|
||||
|
||||
startupGroupBox = new QGroupBox;
|
||||
startupGroupBox->setLayout(startupGrid);
|
||||
|
|
@ -357,6 +412,17 @@ void GeneralSettingsPage::languageBoxChanged(int index)
|
|||
SettingsCache::instance().personal().setLang(languageBox.itemData(index).toString());
|
||||
}
|
||||
|
||||
void GeneralSettingsPage::updateStartupServerControlsVisibility()
|
||||
{
|
||||
const int index = startupTabSelector.currentIndex();
|
||||
const bool serverNeeded = index == StartupTab::StartupTabServer || index == StartupTab::StartupTabServerRoom;
|
||||
const bool roomNeeded = index == StartupTab::StartupTabServerRoom;
|
||||
startupServerLabel.setVisible(serverNeeded);
|
||||
startupServerSelector.setVisible(serverNeeded);
|
||||
startupRoomLabel.setVisible(roomNeeded);
|
||||
startupRoomNameEdit->setVisible(roomNeeded);
|
||||
}
|
||||
|
||||
void GeneralSettingsPage::retranslateUi()
|
||||
{
|
||||
languageGroupBox->setTitle(tr("Language settings"));
|
||||
|
|
@ -393,6 +459,20 @@ void GeneralSettingsPage::retranslateUi()
|
|||
updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client"));
|
||||
newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice"));
|
||||
showTipsOnStartup.setText(tr("Show tips on startup"));
|
||||
startupTabLabel.setText(tr("Startup tab:"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabHome, tr("Home"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabVisualDeckStorage, tr("Visual Deck Storage"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabDeckStorage, tr("Deck Storage"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabReplays, tr("Game Replays"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabDeckEditor, tr("Deck Editor"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabVisualDeckEditor, tr("Visual Deck Editor"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabServer, tr("Server"));
|
||||
startupTabSelector.setItemText(StartupTab::StartupTabServerRoom, tr("Server Room"));
|
||||
startupTabSelector.setToolTip(
|
||||
tr("The tab shown when Cockatrice starts. If the chosen tab is not open yet, it is opened."));
|
||||
startupServerLabel.setText(tr("Server:"));
|
||||
startupRoomLabel.setText(tr("Room:"));
|
||||
startupRoomNameEdit->setPlaceholderText(tr("Room name"));
|
||||
resetAllPathsButton->setText(tr("Reset all paths"));
|
||||
|
||||
const auto &settings = SettingsCache::instance();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ private slots:
|
|||
void tokenDatabasePathButtonClicked();
|
||||
void resetAllPathsClicked();
|
||||
void languageBoxChanged(int index);
|
||||
void updateStartupServerControlsVisibility();
|
||||
|
||||
private:
|
||||
QStringList findQmFiles();
|
||||
|
|
@ -71,6 +72,12 @@ private:
|
|||
QLabel updateReleaseChannelLabel;
|
||||
QLabel advertiseTranslationPageLabel;
|
||||
QCheckBox showTipsOnStartup;
|
||||
QLabel startupTabLabel;
|
||||
QComboBox startupTabSelector;
|
||||
QLabel startupServerLabel;
|
||||
QComboBox startupServerSelector;
|
||||
QLabel startupRoomLabel;
|
||||
QLineEdit *startupRoomNameEdit;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_GENERAL_SETTINGS_PAGE_H
|
||||
|
|
|
|||
|
|
@ -114,6 +114,10 @@ public:
|
|||
{
|
||||
return roomId;
|
||||
}
|
||||
[[nodiscard]] QString getRoomName() const
|
||||
{
|
||||
return roomName;
|
||||
}
|
||||
[[nodiscard]] const QMap<int, QString> &getGameTypes() const
|
||||
{
|
||||
return gameTypes;
|
||||
|
|
|
|||
|
|
@ -335,7 +335,12 @@ static void checkAndTrigger(QAction *checkableAction, bool checked)
|
|||
}
|
||||
|
||||
/**
|
||||
* Opens the always-available tabs, depending on settings.
|
||||
* Opens the always-available tabs, depending on settings, and lands on the configured startup tab.
|
||||
*
|
||||
* The startup destination is a request: tabs that were not open before (deck editors, storage
|
||||
* tabs disabled in the Tabs menu) are opened as part of the startup flow. Destinations that
|
||||
* require a server connection (Server, Server Room) are handled asynchronously by MainWindow
|
||||
* through the intent system, since this class has no RemoteClient.
|
||||
*/
|
||||
void TabSupervisor::initStartupTabs()
|
||||
{
|
||||
|
|
@ -351,6 +356,42 @@ void TabSupervisor::initStartupTabs()
|
|||
if (SettingsCache::instance().tabs().getTabReplaysOpen()) {
|
||||
openTabReplays();
|
||||
}
|
||||
|
||||
switch (SettingsCache::instance().tabs().getStartupTabIndex()) {
|
||||
case StartupTab::StartupTabVisualDeckStorage:
|
||||
if (!tabVisualDeckStorage) {
|
||||
openTabVisualDeckStorage();
|
||||
}
|
||||
setCurrentWidget(tabVisualDeckStorage);
|
||||
break;
|
||||
case StartupTab::StartupTabDeckStorage:
|
||||
if (!tabDeckStorage) {
|
||||
openTabDeckStorage();
|
||||
}
|
||||
setCurrentWidget(tabDeckStorage);
|
||||
break;
|
||||
case StartupTab::StartupTabReplays:
|
||||
if (!tabReplays) {
|
||||
openTabReplays();
|
||||
}
|
||||
setCurrentWidget(tabReplays);
|
||||
break;
|
||||
case StartupTab::StartupTabDeckEditor:
|
||||
addDeckEditorTab(LoadedDeck());
|
||||
break;
|
||||
case StartupTab::StartupTabVisualDeckEditor:
|
||||
addVisualDeckEditorTab(LoadedDeck());
|
||||
break;
|
||||
case StartupTab::StartupTabServer:
|
||||
case StartupTab::StartupTabServerRoom:
|
||||
// Handled asynchronously by MainWindow::applyStartupDestination(); Home stays selected
|
||||
// until the server connection succeeds.
|
||||
break;
|
||||
case StartupTab::StartupTabHome:
|
||||
default:
|
||||
setCurrentWidget(tabHome);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ public slots:
|
|||
void actTabVisualDeckStorage(bool checked);
|
||||
void actTabReplays(bool checked);
|
||||
void openTabServer();
|
||||
void addRoomTab(const ServerInfo_Room &info, bool setCurrent);
|
||||
private slots:
|
||||
void refreshShortcuts();
|
||||
|
||||
|
|
@ -209,7 +210,6 @@ private slots:
|
|||
void gameJoined(const Event_GameJoined &event);
|
||||
void localGameJoined(const Event_GameJoined &event);
|
||||
void gameLeft(TabGame *tab);
|
||||
void addRoomTab(const ServerInfo_Room &info, bool setCurrent);
|
||||
void roomLeft(TabRoom *tab);
|
||||
TabMessage *addMessageTab(const QString &userName, bool focus);
|
||||
void replayLeft(TabGame *tab);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,14 @@
|
|||
#include "../interface/widgets/dialogs/dlg_update.h"
|
||||
#include "../interface/widgets/dialogs/dlg_view_log.h"
|
||||
#include "../interface/widgets/tabs/tab_game.h"
|
||||
#include "../interface/widgets/tabs/tab_server.h"
|
||||
#include "../interface/widgets/tabs/tab_supervisor.h"
|
||||
#include "../main.h"
|
||||
#include "intents/contexts/context_connect_to_server.h"
|
||||
#include "intents/contexts/context_join_room.h"
|
||||
#include "intents/intent_connect_to_server.h"
|
||||
#include "intents/intent_login.h"
|
||||
#include "intents/intent_open_server_room_by_name.h"
|
||||
#include "logger.h"
|
||||
#include "version_string.h"
|
||||
#include "widgets/dialogs/dlg_connect.h"
|
||||
|
|
@ -77,6 +83,7 @@
|
|||
#include <libcockatrice/settings/paths_settings.h>
|
||||
#include <libcockatrice/settings/personal_settings.h>
|
||||
#include <libcockatrice/settings/servers_settings.h>
|
||||
#include <libcockatrice/settings/tabs_settings.h>
|
||||
#include <libcockatrice/settings/updates_settings.h>
|
||||
|
||||
#define GITHUB_PAGES_URL "https://cockatrice.github.io"
|
||||
|
|
@ -540,6 +547,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
|
||||
// run startup check async
|
||||
QTimer::singleShot(0, this, &MainWindow::startupConfigCheck);
|
||||
QTimer::singleShot(0, this, &MainWindow::applyStartupDestination);
|
||||
}
|
||||
|
||||
void MainWindow::startupConfigCheck()
|
||||
|
|
@ -648,6 +656,82 @@ void MainWindow::startupConfigCheck()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drives the server-based startup destinations (Server lobby, Server Room) through the intent
|
||||
* system: fetch saved credentials, connect to the configured server, then land on the Lobby or
|
||||
* join the configured room by name.
|
||||
*/
|
||||
void MainWindow::applyStartupDestination()
|
||||
{
|
||||
// An explicit command-line connect takes precedence over the startup destination.
|
||||
if (!connectTo.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int destination = SettingsCache::instance().tabs().getStartupTabIndex();
|
||||
if (destination != StartupTab::StartupTabServer && destination != StartupTab::StartupTabServerRoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString host = SettingsCache::instance().tabs().getStartupServerHost();
|
||||
const QString port = SettingsCache::instance().tabs().getStartupServerPort();
|
||||
if (host.isEmpty() || port.isEmpty()) {
|
||||
qCWarning(WindowMainStartupLog) << "Startup destination needs a configured server";
|
||||
return;
|
||||
}
|
||||
|
||||
auto serverContext = std::make_shared<ContextConnectToServer>();
|
||||
serverContext->hostname = host;
|
||||
serverContext->port = port;
|
||||
|
||||
auto *credentials = new IntentGetLoginCredentials(serverContext.get());
|
||||
auto *connector = new IntentConnectToServer(getRemoteClient(), serverContext.get());
|
||||
|
||||
connect(credentials, &Intent::finished, connector, &Intent::execute);
|
||||
connect(credentials, &Intent::failed, this, &MainWindow::startupDestinationFailed);
|
||||
connect(connector, &Intent::finished, this,
|
||||
[this, destination, serverContext]() { onStartupDestinationConnected(destination, *serverContext); });
|
||||
connect(connector, &Intent::failed, this, &MainWindow::startupDestinationFailed);
|
||||
|
||||
credentials->execute();
|
||||
}
|
||||
|
||||
void MainWindow::onStartupDestinationConnected(int destination, const ContextConnectToServer &serverContext)
|
||||
{
|
||||
// The server tab must exist: it is what requests the room list.
|
||||
if (!tabSupervisor->getTabServer()) {
|
||||
tabSupervisor->openTabServer();
|
||||
}
|
||||
|
||||
if (destination == StartupTab::StartupTabServerRoom) {
|
||||
auto roomContext = std::make_unique<ContextJoinRoom>();
|
||||
roomContext->serverContext = serverContext;
|
||||
auto *roomIntent = new IntentOpenServerRoomByName(tabSupervisor, getRemoteClient(), std::move(roomContext),
|
||||
SettingsCache::instance().tabs().getStartupRoomName());
|
||||
roomIntent->setParent(this);
|
||||
connect(roomIntent, &Intent::failed, this, &MainWindow::startupDestinationFailed);
|
||||
roomIntent->execute();
|
||||
return;
|
||||
}
|
||||
|
||||
if (tabSupervisor->getTabServer()) {
|
||||
tabSupervisor->setCurrentWidget(tabSupervisor->getTabServer());
|
||||
} else {
|
||||
qCWarning(WindowMainStartupLog) << "Startup destination: server tab could not be opened";
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::startupDestinationFailed(const QString &reason)
|
||||
{
|
||||
qCWarning(WindowMainStartupLog) << "Startup destination failed:" << reason;
|
||||
}
|
||||
|
||||
bool MainWindow::startupDestinationConnectsToServer() const
|
||||
{
|
||||
const int destination = SettingsCache::instance().tabs().getStartupTabIndex();
|
||||
return destination == StartupTab::StartupTabServer || destination == StartupTab::StartupTabServerRoom;
|
||||
}
|
||||
|
||||
void MainWindow::alertForcedOracleRun(const QString &version, bool isUpdate)
|
||||
{
|
||||
if (isUpdate) {
|
||||
|
|
@ -750,7 +834,8 @@ void MainWindow::changeEvent(QEvent *event)
|
|||
connectionController->connectToServerDirect(connectTo.host(), connectTo.port(), connectTo.userName(),
|
||||
connectTo.password());
|
||||
} else if (SettingsCache::instance().servers().getAutoConnect() &&
|
||||
!SettingsCache::instance().debug().getLocalGameOnStartup()) {
|
||||
!SettingsCache::instance().debug().getLocalGameOnStartup() &&
|
||||
!startupDestinationConnectsToServer()) {
|
||||
qCInfo(WindowMainStartupAutoconnectLog) << "Attempting auto-connect...";
|
||||
DlgConnect dlg(this);
|
||||
connectionController->connectToServerDirect(dlg.getHost(), static_cast<unsigned int>(dlg.getPort()),
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class ServerInfo_User;
|
|||
class TabSupervisor;
|
||||
class WndSets;
|
||||
class DlgTipOfTheDay;
|
||||
struct ContextConnectToServer;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
|
|
@ -105,6 +106,11 @@ private slots:
|
|||
void startupConfigCheck();
|
||||
void alertForcedOracleRun(const QString &version, bool isUpdate);
|
||||
|
||||
void applyStartupDestination();
|
||||
void onStartupDestinationConnected(int destination, const ContextConnectToServer &serverContext);
|
||||
void startupDestinationFailed(const QString &reason);
|
||||
[[nodiscard]] bool startupDestinationConnectsToServer() const;
|
||||
|
||||
private:
|
||||
static const QString appName;
|
||||
static const QStringList fileNameFilters;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue