mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-25 16:13:54 -07:00
Merge 77f595701d into 2a3c4a2455
This commit is contained in:
commit
559d4a2b6d
39 changed files with 1034 additions and 9 deletions
|
|
@ -1,38 +1,118 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||||
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
|
||||||
|
<!-- ========================= -->
|
||||||
|
<!-- CORE BUNDLE METADATA -->
|
||||||
|
<!-- ========================= -->
|
||||||
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>English</string>
|
<string>English</string>
|
||||||
|
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||||
|
|
||||||
<key>CFBundleGetInfoString</key>
|
<key>CFBundleGetInfoString</key>
|
||||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||||
|
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||||
|
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||||
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
|
|
||||||
<key>CFBundleLongVersionString</key>
|
<key>CFBundleLongVersionString</key>
|
||||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||||
|
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||||
|
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
|
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||||
|
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
|
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||||
<key>CSResourcesFileMapped</key>
|
|
||||||
<true/>
|
|
||||||
<key>LSRequiresCarbon</key>
|
|
||||||
<true/>
|
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||||
|
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
|
||||||
|
<!-- ========================= -->
|
||||||
|
<!-- FILE TYPE (.cod) SUPPORT -->
|
||||||
|
<!-- ========================= -->
|
||||||
|
|
||||||
|
<key>UTExportedTypeDeclarations</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>org.cockatrice.deck</string>
|
||||||
|
|
||||||
|
<key>UTTypeDescription</key>
|
||||||
|
<string>Cockatrice Deck</string>
|
||||||
|
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<array>
|
||||||
|
<string>cod</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Cockatrice Deck</string>
|
||||||
|
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Default</string>
|
||||||
|
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>org.cockatrice.deck</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<!-- ========================= -->
|
||||||
|
<!-- URL SCHEME (cockatrice://) -->
|
||||||
|
<!-- ========================= -->
|
||||||
|
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>Cockatrice URL Scheme</string>
|
||||||
|
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>cockatrice</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
@ -294,6 +294,20 @@ Section "Application" SecApplication
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
SetOutPath "$INSTDIR"
|
SetOutPath "$INSTDIR"
|
||||||
|
|
||||||
|
${If} $PortableMode = 0
|
||||||
|
|
||||||
|
; --- Register .cod file type ---
|
||||||
|
WriteRegStr HKCR ".cod" "" "Cockatrice"
|
||||||
|
WriteRegStr HKCR "Cockatrice" "" "Cockatrice Deck File"
|
||||||
|
WriteRegStr HKCR "Cockatrice\shell\open\command" "" '"$INSTDIR\cockatrice.exe" "%1"'
|
||||||
|
|
||||||
|
; --- Register custom URI protocol ---
|
||||||
|
WriteRegStr HKCR "cockatrice" "" "URL: Cockatrice Protocol"
|
||||||
|
WriteRegStr HKCR "cockatrice" "URL Protocol" ""
|
||||||
|
WriteRegStr HKCR "cockatrice\shell\open\command" "" '"$INSTDIR\cockatrice.exe" "%1"'
|
||||||
|
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
${If} $PortableMode = 1
|
${If} $PortableMode = 1
|
||||||
${AndIf} ${FileExists} "$INSTDIR\portable.dat"
|
${AndIf} ${FileExists} "$INSTDIR\portable.dat"
|
||||||
; upgrade portable mode
|
; upgrade portable mode
|
||||||
|
|
@ -402,6 +416,9 @@ Section "un.Application" UnSecApplication
|
||||||
RMDir "$SMPROGRAMS\Cockatrice"
|
RMDir "$SMPROGRAMS\Cockatrice"
|
||||||
|
|
||||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice"
|
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice"
|
||||||
|
DeleteRegKey HKCR ".cod"
|
||||||
|
DeleteRegKey HKCR "Cockatrice"
|
||||||
|
DeleteRegKey HKCR "cockatrice"
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
; unselected because it is /o
|
; unselected because it is /o
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,9 @@ set(cockatrice_SOURCES
|
||||||
src/interface/card_picture_loader/card_picture_loader_worker.cpp
|
src/interface/card_picture_loader/card_picture_loader_worker.cpp
|
||||||
src/interface/card_picture_loader/card_picture_loader_worker_work.cpp
|
src/interface/card_picture_loader/card_picture_loader_worker_work.cpp
|
||||||
src/interface/card_picture_loader/card_picture_to_load.cpp
|
src/interface/card_picture_loader/card_picture_to_load.cpp
|
||||||
|
src/interface/intents/intent.cpp
|
||||||
|
src/interface/intents/intent_open_local_deck.cpp
|
||||||
|
src/interface/intents/intent_wait_for_database_load.cpp
|
||||||
src/interface/layouts/flow_layout.cpp
|
src/interface/layouts/flow_layout.cpp
|
||||||
src/interface/layouts/overlap_layout.cpp
|
src/interface/layouts/overlap_layout.cpp
|
||||||
src/interface/widgets/utility/line_edit_completer.cpp
|
src/interface/widgets/utility/line_edit_completer.cpp
|
||||||
|
|
@ -283,6 +286,7 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
||||||
src/interface/window_main.cpp
|
src/interface/window_main.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
src/single_instance_manager.cpp
|
||||||
src/interface/widgets/tabs/abstract_tab_deck_editor.cpp
|
src/interface/widgets/tabs/abstract_tab_deck_editor.cpp
|
||||||
src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp
|
src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp
|
||||||
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp
|
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp
|
||||||
|
|
@ -349,6 +353,20 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.h
|
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.h
|
||||||
src/interface/widgets/utility/compact_push_button.cpp
|
src/interface/widgets/utility/compact_push_button.cpp
|
||||||
src/interface/widgets/utility/compact_push_button.h
|
src/interface/widgets/utility/compact_push_button.h
|
||||||
|
src/single_instance_manager.cpp
|
||||||
|
src/single_instance_manager.h
|
||||||
|
src/client/url_scheme_event_filter.h
|
||||||
|
src/interface/intents/intent_connect_to_server.cpp
|
||||||
|
src/interface/intents/intent_connect_to_server.h
|
||||||
|
src/interface/intents/intent_disconnect_from_server.cpp
|
||||||
|
src/interface/intents/intent_disconnect_from_server.h
|
||||||
|
src/interface/intents/intent_join_server_game.cpp
|
||||||
|
src/interface/intents/intent_join_server_room.cpp
|
||||||
|
src/interface/intents/intent_join_server_room.h
|
||||||
|
src/interface/intents/url_parser.cpp
|
||||||
|
src/interface/intents/url_parser.h
|
||||||
|
src/interface/intents/intent_login.cpp
|
||||||
|
src/interface/intents/intent_login.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(sounds)
|
add_subdirectory(sounds)
|
||||||
|
|
@ -406,6 +424,11 @@ set(DESKTOPDIR
|
||||||
CACHE STRING "desktop file destination"
|
CACHE STRING "desktop file destination"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(MIMEDIR
|
||||||
|
share/mime/packages
|
||||||
|
CACHE STRING "mime file destination"
|
||||||
|
)
|
||||||
|
|
||||||
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
|
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
|
||||||
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
|
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
|
||||||
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
|
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
|
||||||
|
|
@ -490,6 +513,7 @@ if(UNIX)
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice-cod.xml DESTINATION ${MIMEDIR})
|
||||||
endif()
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
install(TARGETS cockatrice RUNTIME DESTINATION ./)
|
install(TARGETS cockatrice RUNTIME DESTINATION ./)
|
||||||
|
|
|
||||||
7
cockatrice/cockatrice-cod.xml
Normal file
7
cockatrice/cockatrice-cod.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||||
|
<mime-type type="application/x-cockatrice">
|
||||||
|
<comment>Cockatrice Deck File</comment>
|
||||||
|
<glob pattern="*.cod"/>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
||||||
|
|
@ -6,3 +6,5 @@ Name=Cockatrice
|
||||||
Exec=cockatrice
|
Exec=cockatrice
|
||||||
Icon=cockatrice
|
Icon=cockatrice
|
||||||
Categories=Game;CardGame;
|
Categories=Game;CardGame;
|
||||||
|
MimeType=application/x-cockatrice;
|
||||||
|
X-Scheme-Handler/cockatrice=true
|
||||||
65
cockatrice/src/client/url_scheme_event_filter.h
Normal file
65
cockatrice/src/client/url_scheme_event_filter.h
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef COCKATRICE_URL_SCHEME_EVENT_FILTER_H
|
||||||
|
#define COCKATRICE_URL_SCHEME_EVENT_FILTER_H
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QFileOpenEvent>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Event filter that catches QFileOpenEvent URLs matching a scheme
|
||||||
|
* prefix and re-emits them as urlReceived().
|
||||||
|
*
|
||||||
|
* On macOS, when the application is registered as a URL scheme handler, the
|
||||||
|
* OS delivers incoming URLs via QFileOpenEvent on the QApplication object.
|
||||||
|
* Install this filter on QApplication to intercept them:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* UrlSchemeEventFilter filter(QStringLiteral("cockatrice://"));
|
||||||
|
* QObject::connect(&filter, &UrlSchemeEventFilter::urlReceived,
|
||||||
|
* &mainWindow, &MainWindow::handleUrl);
|
||||||
|
* app.installEventFilter(&filter);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
class UrlSchemeEventFilter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit UrlSchemeEventFilter(const QStringList &schemePrefix, QObject *parent = nullptr)
|
||||||
|
: QObject(parent), m_prefixes(schemePrefix)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void urlReceived(const QString &url);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event) override
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::FileOpen) {
|
||||||
|
auto *fileEvent = static_cast<QFileOpenEvent *>(event);
|
||||||
|
|
||||||
|
const QUrl url = fileEvent->url();
|
||||||
|
|
||||||
|
for (auto prefix : m_prefixes) {
|
||||||
|
if (url.scheme() == prefix) {
|
||||||
|
emit urlReceived(url.toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.isLocalFile()) {
|
||||||
|
emit urlReceived(url.toLocalFile());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStringList m_prefixes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_URL_SCHEME_EVENT_FILTER_H
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef COCKATRICE_CONTEXT_CONNECT_TO_SERVER_H
|
||||||
|
#define COCKATRICE_CONTEXT_CONNECT_TO_SERVER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
struct ContextConnectToServer
|
||||||
|
{
|
||||||
|
QString hostname;
|
||||||
|
QString port;
|
||||||
|
QString username;
|
||||||
|
QString password;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_CONTEXT_CONNECT_TO_SERVER_H
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef COCKATRICE_CONTEXT_JOIN_GAME_H
|
||||||
|
#define COCKATRICE_CONTEXT_JOIN_GAME_H
|
||||||
|
#include "context_join_room.h"
|
||||||
|
|
||||||
|
struct ContextJoinGame
|
||||||
|
{
|
||||||
|
ContextJoinRoom roomContext;
|
||||||
|
int gameId;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_CONTEXT_JOIN_GAME_H
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef COCKATRICE_CONTEXT_JOIN_ROOM_H
|
||||||
|
#define COCKATRICE_CONTEXT_JOIN_ROOM_H
|
||||||
|
|
||||||
|
#include "context_connect_to_server.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
struct ContextJoinRoom
|
||||||
|
{
|
||||||
|
ContextConnectToServer serverContext;
|
||||||
|
int roomId;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_CONTEXT_JOIN_ROOM_H
|
||||||
1
cockatrice/src/interface/intents/intent.cpp
Normal file
1
cockatrice/src/interface/intents/intent.cpp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent.h"
|
||||||
49
cockatrice/src/interface/intents/intent.h
Normal file
49
cockatrice/src/interface/intents/intent.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_H
|
||||||
|
#define COCKATRICE_INTENT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class Intent : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Intent(QObject *parent = nullptr) : QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~Intent() = default;
|
||||||
|
|
||||||
|
void execute()
|
||||||
|
{
|
||||||
|
if (checkPrecondition()) {
|
||||||
|
onPreconditionSatisfied();
|
||||||
|
} else {
|
||||||
|
onPreconditionNotSatisfied();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
void failed(QString reason);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// --- Subclasses must implement these ---
|
||||||
|
virtual bool checkPrecondition() const = 0;
|
||||||
|
virtual void onPreconditionSatisfied() = 0;
|
||||||
|
virtual void onPreconditionNotSatisfied() = 0;
|
||||||
|
|
||||||
|
// Helper to chain another intent
|
||||||
|
void runDependency(Intent *dependency)
|
||||||
|
{
|
||||||
|
connect(dependency, &Intent::finished, this, [this]() {
|
||||||
|
// Re-check after dependency finishes
|
||||||
|
this->execute();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(dependency, &Intent::failed, this, &Intent::failed);
|
||||||
|
|
||||||
|
dependency->execute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_H
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent_connect_to_server.h"
|
||||||
54
cockatrice/src/interface/intents/intent_connect_to_server.h
Normal file
54
cockatrice/src/interface/intents/intent_connect_to_server.h
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_CONNECT_TO_SERVER_H
|
||||||
|
#define COCKATRICE_INTENT_CONNECT_TO_SERVER_H
|
||||||
|
|
||||||
|
#include "contexts/context_connect_to_server.h"
|
||||||
|
#include "intent.h"
|
||||||
|
#include "intent_disconnect_from_server.h"
|
||||||
|
#include "remote_client.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
class IntentConnectToServer : public Intent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntentConnectToServer(RemoteClient *_remoteClient, ContextConnectToServer *_context)
|
||||||
|
: Intent(), remoteClient(_remoteClient), context(_context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool checkPrecondition() const override
|
||||||
|
{
|
||||||
|
return remoteClient->getStatus() == ClientStatus::StatusDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionSatisfied() override
|
||||||
|
{
|
||||||
|
remoteClient->connectToServer(context->hostname, context->port.toUInt(), context->username, context->password);
|
||||||
|
connect(remoteClient, &RemoteClient::statusChanged, this, &IntentConnectToServer::onStatusChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionNotSatisfied() override
|
||||||
|
{
|
||||||
|
runDependency(new IntentDisconnectFromServer(remoteClient));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RemoteClient *remoteClient;
|
||||||
|
ContextConnectToServer *context;
|
||||||
|
private slots:
|
||||||
|
void onStatusChanged(ClientStatus status)
|
||||||
|
{
|
||||||
|
if (status == ClientStatus::StatusLoggedIn) {
|
||||||
|
auto timer = new QTimer(this);
|
||||||
|
timer->setSingleShot(true);
|
||||||
|
timer->setInterval(2000);
|
||||||
|
connect(timer, &QTimer::timeout, this, &IntentConnectToServer::finished);
|
||||||
|
timer->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_CONNECT_TO_SERVER_H
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent_disconnect_from_server.h"
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_DISCONNECT_FROM_SERVER_H
|
||||||
|
#define COCKATRICE_INTENT_DISCONNECT_FROM_SERVER_H
|
||||||
|
#include "intent.h"
|
||||||
|
#include "remote_client.h"
|
||||||
|
|
||||||
|
class IntentDisconnectFromServer : public Intent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntentDisconnectFromServer(RemoteClient *_remoteClient) : Intent(), remoteClient(_remoteClient)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool checkPrecondition() const override
|
||||||
|
{
|
||||||
|
return remoteClient->getStatus() == ClientStatus::StatusDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionSatisfied() override
|
||||||
|
{
|
||||||
|
qWarning() << "Client disconnected, disconnect is finished";
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionNotSatisfied() override
|
||||||
|
{
|
||||||
|
qWarning() << "Client not disconnected, hooking up signal and disconnecting." << remoteClient->getStatus();
|
||||||
|
connect(remoteClient, &RemoteClient::statusChanged, this, &IntentDisconnectFromServer::onStatusChanged);
|
||||||
|
remoteClient->disconnectFromServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RemoteClient *remoteClient;
|
||||||
|
private slots:
|
||||||
|
void onStatusChanged(ClientStatus status)
|
||||||
|
{
|
||||||
|
qWarning() << "Client Status changed: " << status;
|
||||||
|
if (status == ClientStatus::StatusDisconnected) {
|
||||||
|
qWarning() << "Client disconnected, finished";
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_DISCONNECT_FROM_SERVER_H
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent_join_server_game.h"
|
||||||
63
cockatrice/src/interface/intents/intent_join_server_game.h
Normal file
63
cockatrice/src/interface/intents/intent_join_server_game.h
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_JOIN_SERVER_GAME_H
|
||||||
|
#define COCKATRICE_INTENT_JOIN_SERVER_GAME_H
|
||||||
|
|
||||||
|
#include "../widgets/server/game_selector.h"
|
||||||
|
#include "../widgets/tabs/tab_room.h"
|
||||||
|
#include "../widgets/tabs/tab_server.h"
|
||||||
|
#include "../widgets/tabs/tab_supervisor.h"
|
||||||
|
#include "contexts/context_join_game.h"
|
||||||
|
#include "contexts/context_join_room.h"
|
||||||
|
#include "intent.h"
|
||||||
|
#include "intent_join_server_room.h"
|
||||||
|
#include "remote_client.h"
|
||||||
|
|
||||||
|
class IntentJoinServerGame : public Intent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntentJoinServerGame(TabSupervisor *_tabSupervisor, RemoteClient *_remoteClient, ContextJoinGame *_context)
|
||||||
|
: Intent(), tabSupervisor(_tabSupervisor), remoteClient(_remoteClient), context(_context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool checkPrecondition() const override
|
||||||
|
{
|
||||||
|
if (remoteClient->getStatus() != ClientStatus::StatusLoggedIn) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (remoteClient->peerName() != context->roomContext.serverContext.hostname) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (QString::number(remoteClient->peerPort()) != context->roomContext.serverContext.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tabSupervisor->getRoomTabs()[context->roomContext.roomId]) {
|
||||||
|
qWarning() << "No room tab";
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionSatisfied() override
|
||||||
|
{
|
||||||
|
qWarning() << "All lights green, joining game";
|
||||||
|
TabRoom *room = tabSupervisor->getRoomTabs()[context->roomContext.roomId];
|
||||||
|
room->getGameSelector()->joinGameById(context->gameId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionNotSatisfied() override
|
||||||
|
{
|
||||||
|
runDependency(new IntentJoinServerRoom(tabSupervisor, remoteClient, &context->roomContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TabSupervisor *tabSupervisor;
|
||||||
|
RemoteClient *remoteClient;
|
||||||
|
ContextJoinGame *context;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_JOIN_SERVER_GAME_H
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent_join_server_room.h"
|
||||||
58
cockatrice/src/interface/intents/intent_join_server_room.h
Normal file
58
cockatrice/src/interface/intents/intent_join_server_room.h
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_JOIN_SERVER_ROOM_H
|
||||||
|
#define COCKATRICE_INTENT_JOIN_SERVER_ROOM_H
|
||||||
|
|
||||||
|
#include "../widgets/tabs/tab_server.h"
|
||||||
|
#include "../widgets/tabs/tab_supervisor.h"
|
||||||
|
#include "contexts/context_connect_to_server.h"
|
||||||
|
#include "contexts/context_join_room.h"
|
||||||
|
#include "intent.h"
|
||||||
|
#include "intent_connect_to_server.h"
|
||||||
|
#include "intent_disconnect_from_server.h"
|
||||||
|
#include "remote_client.h"
|
||||||
|
|
||||||
|
class IntentJoinServerRoom : public Intent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntentJoinServerRoom(TabSupervisor *_tabSupervisor, RemoteClient *_remoteClient, ContextJoinRoom *_context)
|
||||||
|
: Intent(), tabSupervisor(_tabSupervisor), remoteClient(_remoteClient), context(_context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool checkPrecondition() const override
|
||||||
|
{
|
||||||
|
if (remoteClient->getStatus() != ClientStatus::StatusLoggedIn) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (remoteClient->peerName() != context->serverContext.hostname) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (QString::number(remoteClient->peerPort()) != context->serverContext.port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionSatisfied() override
|
||||||
|
{
|
||||||
|
auto tabServer = tabSupervisor->getTabServer();
|
||||||
|
tabServer->joinRoom(context->roomId, true);
|
||||||
|
|
||||||
|
connect(tabServer, &TabServer::roomJoined, this, &IntentJoinServerRoom::finished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionNotSatisfied() override
|
||||||
|
{
|
||||||
|
runDependency(new IntentConnectToServer(remoteClient, &context->serverContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TabSupervisor *tabSupervisor;
|
||||||
|
RemoteClient *remoteClient;
|
||||||
|
ContextJoinRoom *context;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_JOIN_SERVER_ROOM_H
|
||||||
1
cockatrice/src/interface/intents/intent_login.cpp
Normal file
1
cockatrice/src/interface/intents/intent_login.cpp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent_login.h"
|
||||||
52
cockatrice/src/interface/intents/intent_login.h
Normal file
52
cockatrice/src/interface/intents/intent_login.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_LOGIN_H
|
||||||
|
#define COCKATRICE_INTENT_LOGIN_H
|
||||||
|
|
||||||
|
#include "../../client/settings/cache_settings.h"
|
||||||
|
#include "contexts/context_connect_to_server.h"
|
||||||
|
#include "intent.h"
|
||||||
|
#include "remote_client.h"
|
||||||
|
|
||||||
|
class IntentGetLoginCredentials : public Intent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntentGetLoginCredentials(RemoteClient *_remoteClient, ContextConnectToServer *_context)
|
||||||
|
: Intent(), remoteClient(_remoteClient), context(_context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool checkPrecondition() const override
|
||||||
|
{
|
||||||
|
ServersSettings &servers = SettingsCache::instance().servers();
|
||||||
|
return servers.hasLoginData(context->hostname, context->port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionSatisfied() override
|
||||||
|
{
|
||||||
|
ServersSettings &servers = SettingsCache::instance().servers();
|
||||||
|
auto index = servers.findServerIndex(context->hostname, context->port);
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
context->username =
|
||||||
|
servers.getValue(QString("username%1").arg(index), "server", "server_details").toString();
|
||||||
|
context->password =
|
||||||
|
servers.getValue(QString("password%1").arg(index), "server", "server_details").toString();
|
||||||
|
emit finished();
|
||||||
|
qWarning() << "Using saved credentials";
|
||||||
|
} else {
|
||||||
|
qWarning() << "No saved server entry";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionNotSatisfied() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RemoteClient *remoteClient;
|
||||||
|
ContextConnectToServer *context;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_LOGIN_H
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent_open_local_deck.h"
|
||||||
44
cockatrice/src/interface/intents/intent_open_local_deck.h
Normal file
44
cockatrice/src/interface/intents/intent_open_local_deck.h
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_OPEN_LOCAL_DECK_H
|
||||||
|
#define COCKATRICE_INTENT_OPEN_LOCAL_DECK_H
|
||||||
|
#include "../widgets/tabs/tab_supervisor.h"
|
||||||
|
#include "intent.h"
|
||||||
|
#include "intent_wait_for_database_load.h"
|
||||||
|
#include "libcockatrice/card/database/card_database_manager.h"
|
||||||
|
|
||||||
|
class IntentOpenLocalDeck : public Intent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntentOpenLocalDeck(TabSupervisor *_tabSupervisor, const QString &_file)
|
||||||
|
: Intent(), tabSupervisor(_tabSupervisor), file(_file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool checkPrecondition() const override
|
||||||
|
{
|
||||||
|
return CardDatabaseManager::getInstance()->getLoadStatus() == LoadStatus::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionSatisfied() override
|
||||||
|
{
|
||||||
|
std::optional<LoadedDeck> deckOpt =
|
||||||
|
DeckLoader::loadFromFile(file, DeckFileFormat::getFormatFromName(file), true);
|
||||||
|
if (deckOpt) {
|
||||||
|
tabSupervisor->openDeckInNewTab(deckOpt.value());
|
||||||
|
}
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionNotSatisfied() override
|
||||||
|
{
|
||||||
|
runDependency(new IntentWaitForDatabaseLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TabSupervisor *tabSupervisor;
|
||||||
|
QString file;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_OPEN_LOCAL_DECK_H
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "intent_wait_for_database_load.h"
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef COCKATRICE_INTENT_WAIT_FOR_DATABASE_LOAD_H
|
||||||
|
#define COCKATRICE_INTENT_WAIT_FOR_DATABASE_LOAD_H
|
||||||
|
|
||||||
|
#include "intent.h"
|
||||||
|
#include "libcockatrice/card/database/card_database_manager.h"
|
||||||
|
|
||||||
|
class IntentWaitForDatabaseLoad : public Intent
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool checkPrecondition() const override
|
||||||
|
{
|
||||||
|
return CardDatabaseManager::getInstance()->getLoadStatus() == LoadStatus::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionSatisfied() override
|
||||||
|
{
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPreconditionNotSatisfied() override
|
||||||
|
{
|
||||||
|
connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFinished, this,
|
||||||
|
[this]() { emit finished(); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_INTENT_WAIT_FOR_DATABASE_LOAD_H
|
||||||
68
cockatrice/src/interface/intents/url_parser.cpp
Normal file
68
cockatrice/src/interface/intents/url_parser.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "url_parser.h"
|
||||||
|
|
||||||
|
#include "../window_main.h"
|
||||||
|
#include "contexts/context_join_room.h"
|
||||||
|
#include "intent_join_server_game.h"
|
||||||
|
#include "intent_join_server_room.h"
|
||||||
|
#include "intent_login.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
IntentUrlParser::IntentUrlParser(QObject *parent, MainWindow *_mainWindow) : QObject(parent), mainWindow(_mainWindow)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntentUrlParser::handle(const QString &urlStr)
|
||||||
|
{
|
||||||
|
QUrl url(urlStr);
|
||||||
|
|
||||||
|
if (url.scheme() != "cockatrice") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString action = url.host();
|
||||||
|
QUrlQuery query(url);
|
||||||
|
|
||||||
|
if (action == "joingame") {
|
||||||
|
handleJoinGame(query);
|
||||||
|
} else if (action == "opendeck") {
|
||||||
|
// handleOpenDeck(query);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Unknown intent:" << action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntentUrlParser::handleJoinGame(const QUrlQuery &query)
|
||||||
|
{
|
||||||
|
auto ctx = new ContextJoinGame();
|
||||||
|
|
||||||
|
ctx->roomContext.serverContext.hostname = query.queryItemValue("hostname");
|
||||||
|
ctx->roomContext.serverContext.port = query.queryItemValue("port");
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
ctx->roomContext.roomId = query.queryItemValue("roomid").toInt(&ok);
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "Invalid or missing roomId";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = false;
|
||||||
|
ctx->gameId = query.queryItemValue("gameid").toInt(&ok);
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
qWarning() << "Invalid or missing gameId";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto getLoginCredentialsIntent =
|
||||||
|
new IntentGetLoginCredentials(mainWindow->getRemoteClient(), &ctx->roomContext.serverContext);
|
||||||
|
|
||||||
|
auto joinGameIntent = new IntentJoinServerGame(mainWindow->getTabSupervisor(), mainWindow->getRemoteClient(), ctx);
|
||||||
|
|
||||||
|
connect(getLoginCredentialsIntent, &Intent::finished, joinGameIntent, &Intent::execute);
|
||||||
|
|
||||||
|
getLoginCredentialsIntent->execute();
|
||||||
|
}
|
||||||
22
cockatrice/src/interface/intents/url_parser.h
Normal file
22
cockatrice/src/interface/intents/url_parser.h
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef COCKATRICE_URL_PARSER_H
|
||||||
|
#define COCKATRICE_URL_PARSER_H
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class IntentUrlParser : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntentUrlParser(QObject *parent, MainWindow *mainWindow);
|
||||||
|
void handle(const QString &urlStr);
|
||||||
|
void handleJoinGame(const QUrlQuery &query);
|
||||||
|
|
||||||
|
void parse(QString url);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MainWindow *mainWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_URL_PARSER_H
|
||||||
|
|
@ -307,6 +307,7 @@ void GameSelector::customContextMenu(const QPoint &point)
|
||||||
connect(&getGameInfo, &QAction::triggered, this, [=, this]() {
|
connect(&getGameInfo, &QAction::triggered, this, [=, this]() {
|
||||||
const ServerInfo_Game &gameInfo = gameListModel->getGame(index.data(Qt::UserRole).toInt());
|
const ServerInfo_Game &gameInfo = gameListModel->getGame(index.data(Qt::UserRole).toInt());
|
||||||
const QMap<int, QString> &gameTypes = gameListModel->getGameTypes().value(gameInfo.room_id());
|
const QMap<int, QString> &gameTypes = gameListModel->getGameTypes().value(gameInfo.room_id());
|
||||||
|
qWarning() << "Game Id: " << gameInfo.game_id();
|
||||||
|
|
||||||
DlgCreateGame dlg(gameInfo, gameTypes, this);
|
DlgCreateGame dlg(gameInfo, gameTypes, this);
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
|
|
@ -376,6 +377,24 @@ void GameSelector::joinGame(const bool asSpectator, const bool asJudge)
|
||||||
disableButtons();
|
disableButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameSelector::joinGameById(int gameId)
|
||||||
|
{
|
||||||
|
auto *model = gameListView->model();
|
||||||
|
|
||||||
|
for (int row = 0; row < model->rowCount(); ++row) {
|
||||||
|
QModelIndex idx = model->index(row, 0);
|
||||||
|
const ServerInfo_Game &game = gameListModel->getGame(idx.data(Qt::UserRole).toInt());
|
||||||
|
if (game.game_id() == gameId) {
|
||||||
|
gameListView->setCurrentIndex(idx);
|
||||||
|
joinGame();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << "Game" << gameId << "not found";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void GameSelector::disableButtons()
|
void GameSelector::disableButtons()
|
||||||
{
|
{
|
||||||
if (createButton) {
|
if (createButton) {
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,7 @@ public:
|
||||||
* @param info The ServerInfo_Game object containing information about the game to update.
|
* @param info The ServerInfo_Game object containing information about the game to update.
|
||||||
*/
|
*/
|
||||||
void processGameInfo(const ServerInfo_Game &info);
|
void processGameInfo(const ServerInfo_Game &info);
|
||||||
|
bool joinGameById(int gameId);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,10 @@ public:
|
||||||
{
|
{
|
||||||
return ownUser;
|
return ownUser;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] GameSelector *getGameSelector() const
|
||||||
|
{
|
||||||
|
return gameSelector;
|
||||||
|
}
|
||||||
|
|
||||||
PendingCommand *prepareRoomCommand(const ::google::protobuf::Message &cmd);
|
PendingCommand *prepareRoomCommand(const ::google::protobuf::Message &cmd);
|
||||||
void sendRoomCommand(PendingCommand *pend);
|
void sendRoomCommand(PendingCommand *pend);
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ signals:
|
||||||
void roomJoined(const ServerInfo_Room &info, bool setCurrent);
|
void roomJoined(const ServerInfo_Room &info, bool setCurrent);
|
||||||
private slots:
|
private slots:
|
||||||
void processServerMessageEvent(const Event_ServerMessage &event);
|
void processServerMessageEvent(const Event_ServerMessage &event);
|
||||||
void joinRoom(int id, bool setCurrent);
|
|
||||||
void joinRoomFinished(const Response &resp, const CommandContainer &commandContainer, const QVariant &extraData);
|
void joinRoomFinished(const Response &resp, const CommandContainer &commandContainer, const QVariant &extraData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -62,6 +61,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client);
|
TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client);
|
||||||
|
void joinRoom(int id, bool setCurrent);
|
||||||
void retranslateUi() override;
|
void retranslateUi() override;
|
||||||
[[nodiscard]] QString getTabText() const override
|
[[nodiscard]] QString getTabText() const override
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,10 @@ public:
|
||||||
{
|
{
|
||||||
return userListManager;
|
return userListManager;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] TabServer *getTabServer() const
|
||||||
|
{
|
||||||
|
return tabServer;
|
||||||
|
}
|
||||||
[[nodiscard]] const QMap<int, TabRoom *> &getRoomTabs() const
|
[[nodiscard]] const QMap<int, TabRoom *> &getRoomTabs() const
|
||||||
{
|
{
|
||||||
return roomTabs;
|
return roomTabs;
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,11 @@ public:
|
||||||
}
|
}
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
|
RemoteClient *getRemoteClient() const
|
||||||
|
{
|
||||||
|
return connectionController->client();
|
||||||
|
}
|
||||||
|
|
||||||
TabSupervisor *getTabSupervisor() const
|
TabSupervisor *getTabSupervisor() const
|
||||||
{
|
{
|
||||||
return tabSupervisor;
|
return tabSupervisor;
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,17 @@
|
||||||
#include "client/network/update/card_spoiler/spoiler_background_updater.h"
|
#include "client/network/update/card_spoiler/spoiler_background_updater.h"
|
||||||
#include "client/settings/cache_settings.h"
|
#include "client/settings/cache_settings.h"
|
||||||
#include "client/sound_engine.h"
|
#include "client/sound_engine.h"
|
||||||
|
#include "client/url_scheme_event_filter.h"
|
||||||
#include "database/interface/settings_card_preference_provider.h"
|
#include "database/interface/settings_card_preference_provider.h"
|
||||||
|
#include "interface/intents/intent_open_local_deck.h"
|
||||||
|
#include "interface/intents/url_parser.h"
|
||||||
#include "interface/logger.h"
|
#include "interface/logger.h"
|
||||||
#include "interface/pixel_map_generator.h"
|
#include "interface/pixel_map_generator.h"
|
||||||
#include "interface/theme_manager.h"
|
#include "interface/theme_manager.h"
|
||||||
#include "interface/widgets/dialogs/dlg_settings.h"
|
#include "interface/widgets/dialogs/dlg_settings.h"
|
||||||
|
#include "interface/widgets/tabs/tab_supervisor.h"
|
||||||
#include "interface/window_main.h"
|
#include "interface/window_main.h"
|
||||||
|
#include "single_instance_manager.h"
|
||||||
#include "version_string.h"
|
#include "version_string.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
@ -174,6 +179,7 @@ int main(int argc, char *argv[])
|
||||||
SetUnhandledExceptionFilter(CockatriceUnhandledExceptionFilter);
|
SetUnhandledExceptionFilter(CockatriceUnhandledExceptionFilter);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Logging setup
|
||||||
#ifdef Q_OS_APPLE
|
#ifdef Q_OS_APPLE
|
||||||
// <build>/cockatrice/cockatrice.app/Contents/MacOS/cockatrice
|
// <build>/cockatrice/cockatrice.app/Contents/MacOS/cockatrice
|
||||||
const QByteArray configPath = "../../../qtlogging.ini";
|
const QByteArray configPath = "../../../qtlogging.ini";
|
||||||
|
|
@ -191,15 +197,29 @@ int main(int argc, char *argv[])
|
||||||
// Set the QT_LOGGING_CONF environment variable
|
// Set the QT_LOGGING_CONF environment variable
|
||||||
qputenv("QT_LOGGING_CONF", configPath);
|
qputenv("QT_LOGGING_CONF", configPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
qSetMessagePattern(
|
qSetMessagePattern(
|
||||||
"\033[0m[%{time yyyy-MM-dd h:mm:ss.zzz} "
|
"\033[0m[%{time yyyy-MM-dd h:mm:ss.zzz} "
|
||||||
"%{if-debug}\033[36mD%{endif}%{if-info}\033[32mI%{endif}%{if-warning}\033[33mW%{endif}%{if-critical}\033[31mC%{"
|
"%{if-debug}\033[36mD%{endif}%{if-info}\033[32mI%{endif}%{if-warning}\033[33mW%{endif}%{if-critical}\033[31mC%{"
|
||||||
"endif}%{if-fatal}\033[1;31mF%{endif}\033[0m] [%{function}] - %{message} [%{file}:%{line}]");
|
"endif}%{if-fatal}\033[1;31mF%{endif}\033[0m] [%{function}] - %{message} [%{file}:%{line}]");
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
UrlSchemeEventFilter cockatriceFilter(QStringList{QStringLiteral("cockatrice")});
|
||||||
|
|
||||||
|
QStringList pendingMacUrls;
|
||||||
|
|
||||||
|
const auto cocoaBufferConn =
|
||||||
|
QObject::connect(&cockatriceFilter, &UrlSchemeEventFilter::urlReceived,
|
||||||
|
[&pendingMacUrls](const QString &url) { pendingMacUrls.append(url); });
|
||||||
|
|
||||||
|
app.installEventFilter(&cockatriceFilter);
|
||||||
|
#endif
|
||||||
|
|
||||||
QObject::connect(&app, &QApplication::lastWindowClosed, &app, &QApplication::quit);
|
QObject::connect(&app, &QApplication::lastWindowClosed, &app, &QApplication::quit);
|
||||||
|
|
||||||
qInstallMessageHandler(CockatriceLogger);
|
qInstallMessageHandler(CockatriceLogger);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
app.addLibraryPath(app.applicationDirPath() + "/plugins");
|
app.addLibraryPath(app.applicationDirPath() + "/plugins");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -215,6 +235,7 @@ int main(int argc, char *argv[])
|
||||||
qApp->setAttribute(Qt::AA_DontShowIconsInMenus, true);
|
qApp->setAttribute(Qt::AA_DontShowIconsInMenus, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Translations
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
translationPath = qApp->applicationDirPath() + "/../Resources/translations";
|
translationPath = qApp->applicationDirPath() + "/../Resources/translations";
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
|
|
@ -223,6 +244,7 @@ int main(int argc, char *argv[])
|
||||||
translationPath = qApp->applicationDirPath() + "/../share/cockatrice/translations";
|
translationPath = qApp->applicationDirPath() + "/../share/cockatrice/translations";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Command-line parser
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription("Cockatrice");
|
parser.setApplicationDescription("Cockatrice");
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
|
@ -256,6 +278,23 @@ int main(int argc, char *argv[])
|
||||||
qCInfo(MainLog) << "Starting main program";
|
qCInfo(MainLog) << "Starting main program";
|
||||||
|
|
||||||
MainWindow ui;
|
MainWindow ui;
|
||||||
|
|
||||||
|
auto handleActivation = [&ui](const QString &file) {
|
||||||
|
if (file.startsWith("cockatrice://")) {
|
||||||
|
auto urlParser = new IntentUrlParser(&ui, &ui);
|
||||||
|
urlParser->handle(file);
|
||||||
|
} else if (QFileInfo(file).exists()) {
|
||||||
|
auto openDeckIntent = new IntentOpenLocalDeck(ui.getTabSupervisor(), file);
|
||||||
|
openDeckIntent->execute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
QObject::disconnect(cocoaBufferConn);
|
||||||
|
|
||||||
|
QObject::connect(&cockatriceFilter, &UrlSchemeEventFilter::urlReceived,
|
||||||
|
[&handleActivation](const QString &url) { handleActivation(url); });
|
||||||
|
#endif
|
||||||
if (parser.isSet("connect")) {
|
if (parser.isSet("connect")) {
|
||||||
ui.setConnectTo(parser.value("connect"));
|
ui.setConnectTo(parser.value("connect"));
|
||||||
}
|
}
|
||||||
|
|
@ -271,6 +310,34 @@ int main(int argc, char *argv[])
|
||||||
// then reload the DB. otherwise just reload the DB
|
// then reload the DB. otherwise just reload the DB
|
||||||
SpoilerBackgroundUpdater spoilerBackgroundUpdater;
|
SpoilerBackgroundUpdater spoilerBackgroundUpdater;
|
||||||
|
|
||||||
|
// --- Handle files or URLs passed at startup ---
|
||||||
|
QStringList startupFiles;
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
startupFiles.append(QString::fromLocal8Bit(argv[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasActivationFiles = !startupFiles.isEmpty();
|
||||||
|
|
||||||
|
SingleInstanceManager instance;
|
||||||
|
|
||||||
|
if (hasActivationFiles) {
|
||||||
|
// Activation launch: try to forward
|
||||||
|
if (!instance.tryRun(startupFiles)) {
|
||||||
|
// Sent successfully → exit
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// No primary instance → become server
|
||||||
|
qInfo() << "No existing instance found, becoming primary instance";
|
||||||
|
} else {
|
||||||
|
// Plain launch: try to start server, but do not connect to any existing
|
||||||
|
if (!instance.tryRun(QStringList())) {
|
||||||
|
// Server already exists → just run independently
|
||||||
|
qInfo() << "Another instance exists, running independently";
|
||||||
|
} else {
|
||||||
|
qInfo() << "No existing instance found, starting server";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ui.show();
|
ui.show();
|
||||||
qCInfo(MainLog) << "ui.show() finished";
|
qCInfo(MainLog) << "ui.show() finished";
|
||||||
|
|
||||||
|
|
@ -280,7 +347,26 @@ int main(int argc, char *argv[])
|
||||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
#endif
|
#endif
|
||||||
app.exec();
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
for (const QString &url : pendingMacUrls) {
|
||||||
|
handleActivation(url);
|
||||||
|
}
|
||||||
|
pendingMacUrls.clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (const QString &file : startupFiles) {
|
||||||
|
handleActivation(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to future file/URL events from other instances
|
||||||
|
QObject::connect(&instance, &SingleInstanceManager::filesReceived, [&handleActivation](const QStringList &files) {
|
||||||
|
for (const QString &file : files) {
|
||||||
|
handleActivation(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
int ret = app.exec();
|
||||||
|
|
||||||
qCInfo(MainLog) << "Event loop finished, terminating...";
|
qCInfo(MainLog) << "Event loop finished, terminating...";
|
||||||
delete rng;
|
delete rng;
|
||||||
|
|
@ -288,5 +374,5 @@ int main(int argc, char *argv[])
|
||||||
CountryPixmapGenerator::clear();
|
CountryPixmapGenerator::clear();
|
||||||
UserLevelPixmapGenerator::clear();
|
UserLevelPixmapGenerator::clear();
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
93
cockatrice/src/single_instance_manager.cpp
Normal file
93
cockatrice/src/single_instance_manager.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
#include "single_instance_manager.h"
|
||||||
|
|
||||||
|
SingleInstanceManager::SingleInstanceManager(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SingleInstanceManager::tryRun(const QStringList &filesToSend)
|
||||||
|
{
|
||||||
|
serverName = "CockatriceSingleInstance";
|
||||||
|
|
||||||
|
// Attempt to connect only if we have files to send
|
||||||
|
if (!filesToSend.isEmpty()) {
|
||||||
|
QLocalSocket socket;
|
||||||
|
socket.connectToServer(serverName);
|
||||||
|
if (socket.waitForConnected(200)) {
|
||||||
|
// Serialize payload with length prefix
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream out(&payload, QIODevice::WriteOnly);
|
||||||
|
out << filesToSend;
|
||||||
|
|
||||||
|
QByteArray message;
|
||||||
|
QDataStream msgStream(&message, QIODevice::WriteOnly);
|
||||||
|
msgStream << quint32(payload.size());
|
||||||
|
message.append(payload);
|
||||||
|
|
||||||
|
socket.write(message);
|
||||||
|
socket.flush();
|
||||||
|
socket.waitForBytesWritten(1000);
|
||||||
|
|
||||||
|
return false; // Sent successfully → exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, start server
|
||||||
|
server = new QLocalServer(this);
|
||||||
|
connect(server, &QLocalServer::newConnection, this, &SingleInstanceManager::handleNewConnection);
|
||||||
|
|
||||||
|
if (!server->listen(serverName)) {
|
||||||
|
QLocalServer::removeServer(serverName);
|
||||||
|
server->listen(serverName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // This process is now primary server
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleInstanceManager::handleNewConnection()
|
||||||
|
{
|
||||||
|
QLocalSocket *socket = server->nextPendingConnection();
|
||||||
|
|
||||||
|
// Per-connection state
|
||||||
|
auto buffer = new QByteArray();
|
||||||
|
auto expectedSize = new quint32(0);
|
||||||
|
|
||||||
|
connect(socket, &QLocalSocket::readyRead, this, [this, socket, buffer, expectedSize]() {
|
||||||
|
buffer->append(socket->readAll());
|
||||||
|
|
||||||
|
QDataStream stream(buffer, QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// Step 1: read size
|
||||||
|
if (*expectedSize == 0) {
|
||||||
|
if (buffer->size() < static_cast<int>(sizeof(quint32))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream >> *expectedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: wait for full payload
|
||||||
|
if (buffer->size() < static_cast<int>(sizeof(quint32) + *expectedSize)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: extract payload
|
||||||
|
QByteArray payload = buffer->mid(sizeof(quint32), *expectedSize);
|
||||||
|
|
||||||
|
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
|
||||||
|
QStringList files;
|
||||||
|
payloadStream >> files;
|
||||||
|
|
||||||
|
emit filesReceived(files);
|
||||||
|
|
||||||
|
// Reset buffer (single message use-case)
|
||||||
|
buffer->clear();
|
||||||
|
*expectedSize = 0;
|
||||||
|
|
||||||
|
socket->disconnectFromServer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(socket, &QLocalSocket::disconnected, socket, &QLocalSocket::deleteLater);
|
||||||
|
}
|
||||||
28
cockatrice/src/single_instance_manager.h
Normal file
28
cockatrice/src/single_instance_manager.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef COCKATRICE_SINGLE_INSTANCE_MANAGER_H
|
||||||
|
#define COCKATRICE_SINGLE_INSTANCE_MANAGER_H
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
|
||||||
|
class SingleInstanceManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SingleInstanceManager(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
bool tryRun(const QStringList &initialFiles);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void filesReceived(const QStringList &files);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleNewConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString serverName;
|
||||||
|
QLocalServer *server = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_SINGLE_INSTANCE_MANAGER_H
|
||||||
|
|
@ -131,6 +131,14 @@ public:
|
||||||
return socket->peerName();
|
return socket->peerName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
quint16 peerPort() const
|
||||||
|
{
|
||||||
|
if (usingWebSocket) {
|
||||||
|
return websocket->peerPort();
|
||||||
|
} else {
|
||||||
|
return socket->peerPort();
|
||||||
|
}
|
||||||
|
}
|
||||||
void
|
void
|
||||||
connectToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password);
|
connectToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password);
|
||||||
void registerToServer(const QString &hostname,
|
void registerToServer(const QString &hostname,
|
||||||
|
|
|
||||||
|
|
@ -293,3 +293,48 @@ bool ServersSettings::updateExistingServer(QString saveName,
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ServersSettings::findServerIndex(const QString &host, const QString &port) const
|
||||||
|
{
|
||||||
|
int size = getValue("totalServers", "server", "server_details").toInt();
|
||||||
|
|
||||||
|
for (int i = 0; i <= size; ++i) {
|
||||||
|
QString storedHost = getValue(QString("server%1").arg(i), "server", "server_details").toString();
|
||||||
|
QString storedPort = getValue(QString("port%1").arg(i), "server", "server_details").toString();
|
||||||
|
|
||||||
|
if (storedHost == host && storedPort == port) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServersSettings::hasUsername(const QString &host, const QString &port) const
|
||||||
|
{
|
||||||
|
int index = findServerIndex(host, port);
|
||||||
|
if (index < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString user = getValue(QString("username%1").arg(index), "server", "server_details").toString();
|
||||||
|
return !user.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServersSettings::hasCredentials(const QString &host, const QString &port) const
|
||||||
|
{
|
||||||
|
int index = findServerIndex(host, port);
|
||||||
|
if (index < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool save = getValue(QString("savePassword%1").arg(index), "server", "server_details").toBool();
|
||||||
|
QString password = getValue(QString("password%1").arg(index), "server", "server_details").toString();
|
||||||
|
|
||||||
|
return save && !password.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServersSettings::hasLoginData(const QString &host, const QString &port) const
|
||||||
|
{
|
||||||
|
return hasUsername(host, port) && hasCredentials(host, port);
|
||||||
|
}
|
||||||
|
|
@ -61,6 +61,10 @@ public:
|
||||||
QString password,
|
QString password,
|
||||||
bool savePassword,
|
bool savePassword,
|
||||||
QString site = QString());
|
QString site = QString());
|
||||||
|
int findServerIndex(const QString &host, const QString &port) const;
|
||||||
|
bool hasUsername(const QString &host, const QString &port) const;
|
||||||
|
bool hasCredentials(const QString &host, const QString &port) const;
|
||||||
|
bool hasLoginData(const QString &host, const QString &port) const;
|
||||||
|
|
||||||
bool updateExistingServerWithoutLoss(QString saveName,
|
bool updateExistingServerWithoutLoss(QString saveName,
|
||||||
QString serv = QString(),
|
QString serv = QString(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue