[04]コカトリスインターフェース構成
Cockatrice Interface Composition
目次
明示的なMainWindow(QWidget * parent = nullptr)
void setConnectTo(QString url)
void closeEvent(QCloseEvent * event)オーバーライド
void changeEvent(QEvent * event)オーバーライド
QString extractInvalidUsernameMessage(QString&in)
int getNextCustomSetPrefix(QDir dataDir)
インラインQStringgetCardUpdaterBinaryName()
void updateTabMenu(const QList&newMenuList)
void statusChanged(ClientStatus _status)
void processConnectionClosedEvent(const Event_ConnectionClosed&event)
void processServerShutdownEvent(const Event_ServerShutdown&event)
void loginError(Response :: ResponseCode r、QString reasonStr、quint32 endTime、QList MissingFeatures)
void registerError(Response :: ResponseCode r、QString reasonStr、quint32 endTime)
void socketError(const QString&errorStr)
void protocolVersionMismatch(int localVersion、int remoteVersion)
void userInfoReceived(const ServerInfo_User&userInfo)
void registerAcceptedNeedsActivate()
void pixmapCacheSizeChanged(int newSizeInMBs)
void actFullScreen(boolchecked)
void actForgotPasswordRequest()
void promptForgotPasswordReset()
void iconActivated(QSystemTrayIcon :: ActivationReason理由)
void promptForgotPasswordChallenge()
void cardUpdateError(QProcess :: ProcessError err)
void cardUpdateFinished(int exitCode、QProcess :: ExitStatus exitStatus)
void cardDatabaseLoadingFailed()
void cardDatabaseNewSetsFound(int numUnknownSets、QStringList unknownSetsNames)
void cardDatabaseAllNewSetsEnabled()
void actOpenCustomsetsFolder()
void alertForcedOracleRun(const QString&version、bool isUpdate)
static const QStringList fileNameFilters
QAction * aOpenCustomsetsFolder
QMessageBox serverShutdownMessageBox
[1] MainWindowを呼び出す
main()でMainWindowを呼び出してメインインターフェイスを生成し、メインウィンドウとステータスバーのアイコンを設定します。
int main(int argc, char *argv[]) { 。。。 MainWindow ui---->Create MainWindow instance if (parser.isSet('connect')) { ui.setConnectTo(parser.value('connect'))---->Finally, QUrl is used to save the server address to be connected } qDebug('main(): MainWindow constructor finished') ui.setWindowIcon(QPixmap('theme:cockatrice'))---->Set the icon displayed in the main window & status bar of the program 。。。 ui.show()---->Show window qDebug('main(): ui.show() finished') 。。。 }
[2] MainWindowクラス構成
MainWindowクラスはQMainWindowを継承し、主にQMainWindowに基づいて多くのスロット関数を追加します。
class MainWindow : public QMainWindow { Q_OBJECT public slots: void actCheckCardUpdates()---->Start a thread to load the external database 'oracle.exe' to update the card status void actCheckServerUpdates()---->Update the official server list file from the Git mirror address. private slots: void updateTabMenu(const QList &newMenuList)---->Update the menu bar with the content of newMenuList void statusChanged(ClientStatus _status)---->Switch the program running status void processConnectionClosedEvent(const Event_ConnectionClosed &event)---->Process connection close event void processServerShutdownEvent(const Event_ServerShutdown &event)---->Process server disconnection event void serverTimeout()---->Server timeout void loginError(Response::ResponseCode r, QString reasonStr, quint32 endTime, QList missingFeatures)---->Login error void registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime)---->Registration error void activateError()----> void socketError(const QString &errorStr)----> void protocolVersionMismatch(int localVersion, int remoteVersion)---->protocol version does not match void userInfoReceived(const ServerInfo_User &userInfo)---->User Information Receive void registerAccepted()---->Registration allowed void registerAcceptedNeedsActivate()---->Activation is required after registration is allowed void activateAccepted()---->Activation allowed void localGameEnded()---->The local game ends void pixmapCacheSizeChanged(int newSizeInMBs)---->Image cache size changed void notifyUserAboutUpdate()----> void actConnect()----> void actDisconnect()----> void actSinglePlayer()----> void actWatchReplay()----> void actDeckEditor()----> void actFullScreen(bool checked)----> void actRegister()----> void actSettings()----> void actExit()----> void actForgotPasswordRequest()----> void actAbout()----> void actTips()----> void actUpdate()----> void actViewLog()----> void forgotPasswordSuccess()----> void forgotPasswordError()----> void promptForgotPasswordReset()----> void iconActivated(QSystemTrayIcon::ActivationReason reason)----> void promptForgotPasswordChallenge()----> void showWindowIfHidden()----> void cardUpdateError(QProcess::ProcessError err)----> void cardUpdateFinished(int exitCode, QProcess::ExitStatus exitStatus)----> void refreshShortcuts()----> void cardDatabaseLoadingFailed()----> void cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknownSetsNames)----> void cardDatabaseAllNewSetsEnabled()----> void actOpenCustomFolder()----> void actOpenCustomsetsFolder()----> void actAddCustomSet()----> void actManageSets()----> void actEditTokens()----> void startupConfigCheck()----> void alertForcedOracleRun(const QString &version, bool isUpdate)----> private: static const QString appName static const QStringList fileNameFilters void setClientStatusTitle()----> void retranslateUi()----> void createActions()----> void createMenus()----> void createTrayIcon()----> void createTrayActions()----> int getNextCustomSetPrefix(QDir dataDir)----> // TODO: add a preference item to choose updater name for other games inline QString getCardUpdaterBinaryName()----> { return 'oracle' } QList tabMenus QMenu *cockatriceMenu, *dbMenu, *helpMenu, *trayIconMenu QAction *aConnect, *aDisconnect, *aSinglePlayer, *aWatchReplay, *aDeckEditor, *aFullScreen, *aSettings, *aExit, *aAbout, *aTips, *aCheckCardUpdates, *aRegister, *aUpdate, *aViewLog, *closeAction QAction *aManageSets, *aEditTokens, *aOpenCustomFolder, *aOpenCustomsetsFolder, *aAddCustomSet TabSupervisor *tabSupervisor WndSets *wndSets RemoteClient *client QThread *clientThread LocalServer *localServer bool bHasActivated QMessageBox serverShutdownMessageBox QProcess *cardUpdateProcess DlgViewLog *logviewDialog DlgConnect *dlgConnect GameReplay *replay DlgTipOfTheDay *tip QUrl connectTo public: explicit MainWindow(QWidget *parent = nullptr)----> void setConnectTo(QString url)----> { connectTo = QUrl(QString('cockatrice://%1').arg(url)) } ~MainWindow() override----> protected: void closeEvent(QCloseEvent *event) override----> void changeEvent(QEvent *event) override----> QString extractInvalidUsernameMessage(QString &in)----> }
公衆:
明示的なMainWindow(QWidget * parent = nullptr)
コンストラクター、明示的はこれが表示コンストラクターであることを意味します(パラメーターは暗黙的に変換されません)、parent = nullptrはこれが最上位関数であり、すべてのウィンドウの父であり、それを強制終了すると、すべての子ウィンドウ/コントロールが逆になります構造によると破壊します。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), localServer(nullptr), bHasActivated(false), cardUpdateProcess(nullptr), logviewDialog(nullptr) { connect(settingsCache, SIGNAL(pixmapCacheSizeChanged(int)), this, SLOT(pixmapCacheSizeChanged(int))) pixmapCacheSizeChanged(settingsCache->getPixmapCacheSize()) client = new RemoteClient connect(client, SIGNAL(connectionClosedEventReceived(const Event_ConnectionClosed &)), this, SLOT(processConnectionClosedEvent(const Event_ConnectionClosed &))) connect(client, SIGNAL(serverShutdownEventReceived(const Event_ServerShutdown &)), this, SLOT(processServerShutdownEvent(const Event_ServerShutdown &))) connect(client, SIGNAL(loginError(Response::ResponseCode, QString, quint32, QList)), this, SLOT(loginError(Response::ResponseCode, QString, quint32, QList))) connect(client, SIGNAL(socketError(const QString &)), this, SLOT(socketError(const QString &))) connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout())) connect(client, SIGNAL(statusChanged(ClientStatus)), this, SLOT(statusChanged(ClientStatus))) connect(client, SIGNAL(protocolVersionMismatch(int, int)), this, SLOT(protocolVersionMismatch(int, int))) connect(client, SIGNAL(userInfoChanged(const ServerInfo_User &)), this, SLOT(userInfoReceived(const ServerInfo_User &)), Qt::BlockingQueuedConnection) connect(client, SIGNAL(notifyUserAboutUpdate()), this, SLOT(notifyUserAboutUpdate())) connect(client, SIGNAL(registerAccepted()), this, SLOT(registerAccepted())) connect(client, SIGNAL(registerAcceptedNeedsActivate()), this, SLOT(registerAcceptedNeedsActivate())) connect(client, SIGNAL(registerError(Response::ResponseCode, QString, quint32)), this, SLOT(registerError(Response::ResponseCode, QString, quint32))) connect(client, SIGNAL(activateAccepted()), this, SLOT(activateAccepted())) connect(client, SIGNAL(activateError()), this, SLOT(activateError())) connect(client, SIGNAL(sigForgotPasswordSuccess()), this, SLOT(forgotPasswordSuccess())) connect(client, SIGNAL(sigForgotPasswordError()), this, SLOT(forgotPasswordError())) connect(client, SIGNAL(sigPromptForForgotPasswordReset()), this, SLOT(promptForgotPasswordReset())) connect(client, SIGNAL(sigPromptForForgotPasswordChallenge()), this, SLOT(promptForgotPasswordChallenge())) clientThread = new QThread(this) client->moveToThread(clientThread) clientThread->start() createActions() createMenus() tabSupervisor = new TabSupervisor(client) connect(tabSupervisor, SIGNAL(setMenu(QList)), this, SLOT(updateTabMenu(QList))) connect(tabSupervisor, SIGNAL(localGameEnded()), this, SLOT(localGameEnded())) connect(tabSupervisor, SIGNAL(showWindowIfHidden()), this, SLOT(showWindowIfHidden())) tabSupervisor->addDeckEditorTab(nullptr) setCentralWidget(tabSupervisor) retranslateUi() if (!restoreGeometry(settingsCache->getMainWindowGeometry())) { setWindowState(Qt::WindowMaximized) } aFullScreen->setChecked(static_cast(windowState() & Qt::WindowFullScreen)) if (QSystemTrayIcon::isSystemTrayAvailable()) { createTrayActions() createTrayIcon() } connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts())) refreshShortcuts() connect(db, SIGNAL(cardDatabaseLoadingFailed()), this, SLOT(cardDatabaseLoadingFailed())) connect(db, SIGNAL(cardDatabaseNewSetsFound(int, QStringList)), this, SLOT(cardDatabaseNewSetsFound(int, QStringList))) connect(db, SIGNAL(cardDatabaseAllNewSetsEnabled()), this, SLOT(cardDatabaseAllNewSetsEnabled())) tip = new DlgTipOfTheDay() // run startup check async QTimer::singleShot(0, this, &MainWindow::startupConfigCheck) }
void setConnectTo(QString url)
connectTo変数に値を割り当て、サーバーアドレスを指定します。
void setConnectTo(QString url) { connectTo = QUrl(QString('cockatrice://%1').arg(url)) }
〜MainWindow()オーバーライド
デストラクタ、いい隣人になるために〜
MainWindow::~MainWindow() { if (tip != nullptr) { delete tip tip = nullptr } if (trayIcon) { trayIcon->hide() trayIcon->deleteLater() } client->deleteLater() clientThread->wait() }
保護:
void closeEvent(QCloseEvent * event)オーバーライド
QMainWindowのcloseEventを書き直して、QTネイティブcloseEvent()イベントが2回続けてトリガーされるという問題を解決します。
void MainWindow::closeEvent(QCloseEvent *event) { // workaround Qt bug where closeEvent gets called twice static bool bClosingDown = false if (bClosingDown) return bClosingDown = true if (!tabSupervisor->closeRequest()) { event->ignore() bClosingDown = false return } tip->close() event->accept() settingsCache->setMainWindowGeometry(saveGeometry()) tabSupervisor->deleteLater() }
void changeEvent(QEvent * event)オーバーライド
QMainWindowのchangeEventをオーバーライドし、QMainWindowのchangeEventを呼び出す前に、QEvent :: LanguageChangeイベントとQEvent :: ActivationChangeイベントを追加で処理します。
void MainWindow::changeEvent(QEvent *event) { if (event->type() == QEvent::LanguageChange) retranslateUi() else if (event->type() == QEvent::ActivationChange) { if (isActiveWindow() && !bHasActivated) { bHasActivated = true if (!connectTo.isEmpty()) { qDebug() << 'Command line connect to ' servers().getAutoConnect()) { qDebug() QString extractInvalidUsernameMessage(QString&in)
この関数は、ユーザー名が無効な場合にのみ呼び出す必要があります。ユーザー名が無効である理由を検出し、関連するプロンプトメッセージを出力します。
QString MainWindow::extractInvalidUsernameMessage(QString &in) { QString out = tr('Invalid username.') + '
' QStringList rules = in.split(QChar('|')) if (rules.size() == 7 || rules.size() == 9) { out += tr('Your username must respect these rules:') + '' out += '- ' + tr('is %1 - %2 characters long').arg(rules.at(0)).arg(rules.at(1)) + '
' out += '- ' + tr('can %1 contain lowercase characters').arg((rules.at(2).toInt() > 0) ? '' : tr('NOT')) + '
' out += '- ' + tr('can %1 contain uppercase characters').arg((rules.at(3).toInt() > 0) ? '' : tr('NOT')) + '
' out += '- ' + tr('can %1 contain numeric characters').arg((rules.at(4).toInt() > 0) ? '' : tr('NOT')) + '
' if (rules.at(6).size() > 0) out += '- ' + tr('can contain the following punctuation: %1').arg(rules.at(6).toHtmlEscaped()) + '
' out += '- ' + tr('first character can %1 be a punctuation mark').arg((rules.at(5).toInt() > 0) ? '' : tr('NOT')) + '
' if (rules.size() == 9) { if (rules.at(7).size() > 0) out += '- ' + tr('can not contain any of the following words: %1').arg(rules.at(7).toHtmlEscaped()) + '
' if (rules.at(8).size() > 0) out += '- ' + tr('can not match any of the following expressions: %1').arg(rules.at(8).toHtmlEscaped()) + '
' } out += '
' } else { out += tr('You may only use A-Z, a-z, 0-9, _, ., and - in your username.') } return out }
民間:
void setClientStatusTitle()
client-> getStatus()を使用して現在のプログラムの実行ステータスを取得し、プログラムのタイトルバーに対応する説明を表示します。プログラム名は通常動作時に表示されます。
void MainWindow::setClientStatusTitle() { switch (client->getStatus()) { case StatusConnecting: setWindowTitle(appName + ' - ' + tr('Connecting to %1...').arg(client->peerName())) break case StatusRegistering: setWindowTitle(appName + ' - ' + tr('Registering to %1 as %2...').arg(client->peerName()).arg(client->getUserName())) break case StatusDisconnected: setWindowTitle(appName + ' - ' + tr('Disconnected')) break case StatusLoggingIn: setWindowTitle(appName + ' - ' + tr('Connected, logging in at %1').arg(client->peerName())) break case StatusLoggedIn: setWindowTitle(client->getUserName() + '@' + client->peerName()) break case StatusRequestingForgotPassword: setWindowTitle( appName + ' - ' + tr('Requesting forgotten password to %1 as %2...').arg(client->peerName()).arg(client->getUserName())) break case StatusSubmitForgotPasswordChallenge: setWindowTitle( appName + ' - ' + tr('Requesting forgotten password to %1 as %2...').arg(client->peerName()).arg(client->getUserName())) break case StatusSubmitForgotPasswordReset: setWindowTitle( appName + ' - ' + tr('Requesting forgotten password to %1 as %2...').arg(client->peerName()).arg(client->getUserName())) break default: setWindowTitle(appName) } }
void retranslateUi()
setClientStatusTitle()を呼び出して、プログラムの実行ステータスをタイトルバーに更新し(主に表示されるテキスト言語を更新します)、すべてのメニュー(メニューバー)/アクティブ(メニュー項目)/タブ(タブ)の表示テキスト言語を更新します。
void MainWindow::retranslateUi() { setClientStatusTitle() aConnect->setText(tr('&Connect...')) aDisconnect->setText(tr('&Disconnect')) aSinglePlayer->setText(tr('Start &local game...')) aWatchReplay->setText(tr('&Watch replay...')) aDeckEditor->setText(tr('&Deck editor')) aFullScreen->setText(tr('&Full screen')) aRegister->setText(tr('&Register to server...')) aSettings->setText(tr('&Settings...')) aSettings->setIcon(QPixmap('theme:icons/settings')) aExit->setText(tr('&Exit')) #if defined(__APPLE__) /* For OSX */ cockatriceMenu->setTitle(tr('A&ctions')) #else cockatriceMenu->setTitle(tr('&Cockatrice')) #endif dbMenu->setTitle(tr('C&ard Database')) aOpenCustomFolder->setText(tr('Open custom image folder')) aOpenCustomsetsFolder->setText(tr('Open custom sets folder')) aAddCustomSet->setText(tr('Add custom sets/cards')) aManageSets->setText(tr('&Manage sets...')) aEditTokens->setText(tr('Edit custom &tokens...')) aAbout->setText(tr('&About Cockatrice')) aTips->setText(tr('&Tip of the Day')) aUpdate->setText(tr('Check for Client Updates')) aViewLog->setText(tr('View &debug log')) helpMenu->setTitle(tr('&Help')) aCheckCardUpdates->setText(tr('Check for card updates...')) tabSupervisor->retranslateUi() }
void createActions()
すべてのメニュー項目を作成します。
void MainWindow::createActions() { aConnect = new QAction(this) connect(aConnect, SIGNAL(triggered()), this, SLOT(actConnect())) aDisconnect = new QAction(this) aDisconnect->setEnabled(false) connect(aDisconnect, SIGNAL(triggered()), this, SLOT(actDisconnect())) aSinglePlayer = new QAction(this) connect(aSinglePlayer, SIGNAL(triggered()), this, SLOT(actSinglePlayer())) aWatchReplay = new QAction(this) connect(aWatchReplay, SIGNAL(triggered()), this, SLOT(actWatchReplay())) aDeckEditor = new QAction(this) connect(aDeckEditor, SIGNAL(triggered()), this, SLOT(actDeckEditor())) aFullScreen = new QAction(this) aFullScreen->setCheckable(true) connect(aFullScreen, SIGNAL(toggled(bool)), this, SLOT(actFullScreen(bool))) aRegister = new QAction(this) connect(aRegister, SIGNAL(triggered()), this, SLOT(actRegister())) aSettings = new QAction(this) connect(aSettings, SIGNAL(triggered()), this, SLOT(actSettings())) aExit = new QAction(this) connect(aExit, SIGNAL(triggered()), this, SLOT(actExit())) aAbout = new QAction(this) connect(aAbout, SIGNAL(triggered()), this, SLOT(actAbout())) aTips = new QAction(this) connect(aTips, SIGNAL(triggered()), this, SLOT(actTips())) aUpdate = new QAction(this) connect(aUpdate, SIGNAL(triggered()), this, SLOT(actUpdate())) aViewLog = new QAction(this) connect(aViewLog, SIGNAL(triggered()), this, SLOT(actViewLog())) aCheckCardUpdates = new QAction(this) connect(aCheckCardUpdates, SIGNAL(triggered()), this, SLOT(actCheckCardUpdates())) aOpenCustomsetsFolder = new QAction(QString(), this) connect(aOpenCustomsetsFolder, SIGNAL(triggered()), this, SLOT(actOpenCustomsetsFolder())) aOpenCustomFolder = new QAction(QString(), this) connect(aOpenCustomFolder, SIGNAL(triggered()), this, SLOT(actOpenCustomFolder())) aAddCustomSet = new QAction(QString(), this) connect(aAddCustomSet, SIGNAL(triggered()), this, SLOT(actAddCustomSet())) aManageSets = new QAction(QString(), this) connect(aManageSets, SIGNAL(triggered()), this, SLOT(actManageSets())) aEditTokens = new QAction(QString(), this) connect(aEditTokens, SIGNAL(triggered()), this, SLOT(actEditTokens())) #if defined(__APPLE__) /* For OSX */ aSettings->setMenuRole(QAction::PreferencesRole) aExit->setMenuRole(QAction::QuitRole) aAbout->setMenuRole(QAction::AboutRole) Q_UNUSED(QT_TRANSLATE_NOOP('QMenuBar', 'Services')) Q_UNUSED(QT_TRANSLATE_NOOP('QMenuBar', 'Hide %1')) Q_UNUSED(QT_TRANSLATE_NOOP('QMenuBar', 'Hide Others')) Q_UNUSED(QT_TRANSLATE_NOOP('QMenuBar', 'Show All')) Q_UNUSED(QT_TRANSLATE_NOOP('QMenuBar', 'Preferences...')) Q_UNUSED(QT_TRANSLATE_NOOP('QMenuBar', 'Quit %1')) Q_UNUSED(QT_TRANSLATE_NOOP('QMenuBar', 'About %1')) #endif // translate Qt's dialogs 'default button text' list taken from QPlatformTheme::defaultStandardButtonText() Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'OK')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Save')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Save All')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Open')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', '&Yes')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Yes to &All')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', '&No')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'N&o to All')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Abort')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Retry')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Ignore')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Close')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Cancel')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Discard')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Help')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Apply')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Reset')) Q_UNUSED(QT_TRANSLATE_NOOP('QPlatformTheme', 'Restore Defaults')) }
void createMenus()
すべてのメニューバーを作成し、対応するメニューバーに特定のメニュー項目を追加します。
void MainWindow::createMenus() cockatriceMenu = menuBar()->addMenu(QString()) cockatriceMenu->addAction(aConnect) cockatriceMenu->addAction(aDisconnect) cockatriceMenu->addAction(aRegister) cockatriceMenu->addSeparator() cockatriceMenu->addAction(aSinglePlayer) cockatriceMenu->addAction(aWatchReplay) cockatriceMenu->addSeparator() cockatriceMenu->addAction(aDeckEditor) cockatriceMenu->addSeparator() cockatriceMenu->addAction(aFullScreen) cockatriceMenu->addSeparator() cockatriceMenu->addAction(aSettings) cockatriceMenu->addAction(aCheckCardUpdates) cockatriceMenu->addSeparator() cockatriceMenu->addAction(aExit) dbMenu = menuBar()->addMenu(QString()) dbMenu->addAction(aManageSets) dbMenu->addAction(aEditTokens) dbMenu->addSeparator() #if defined(Q_OS_WIN)
void createTrayIcon()
システムトレイアイコン(右下隅のステータスバー)を作成します。
void MainWindow::createTrayIcon() { trayIconMenu = new QMenu(this) trayIconMenu->addAction(closeAction) trayIcon = new QSystemTrayIcon(this) trayIcon->setContextMenu(trayIconMenu) trayIcon->setIcon(QPixmap('theme:cockatrice')) trayIcon->show() connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))) }
void createTrayActions()
システムトレイアイコンのメニュー項目を作成し、現在はプログラムを終了するだけです。
void MainWindow::createTrayActions() { closeAction = new QAction(tr('&Exit'), this) connect(closeAction, SIGNAL(triggered()), this, SLOT(close())) }
int getNextCustomSetPrefix(QDir dataDir)
データベースディレクトリ内のすべてのファイルを読み取り、リストを作成し、トラバースして最大の番号名を検出し、番号+1を新しいファイル名として出力します。
トラバーサルの実装では、非常に古典的なC ++スタイルのトラバーサーを使用します。
int MainWindow::getNextCustomSetPrefix(QDir dataDir) { QStringList files = dataDir.entryList() int maxIndex = 0 QStringList::const_iterator filesIterator for (filesIterator = files.constBegin() filesIterator != files.constEnd() ++filesIterator) { int fileIndex = (*filesIterator).split('.').at(0).toInt() if (fileIndex > maxIndex) maxIndex = fileIndex } return maxIndex + 1 }
インラインQStringgetCardUpdaterBinaryName()
呼び出された外部データベースプログラムの名前を返します。現在、oracleが使用されています。
inlineは、これがインライン関数であることを示します。インライン関数は通常、ヘッダーファイルで定義することをお勧めします。インライン関数は、直接再帰的(自身を呼び出す)または複雑な制御ステートメント(while / switchなど)を含むことはできず、特定の効果はコンパイラーに関連しています。
inline QString getCardUpdaterBinaryName() { return 'oracle' }
パブリックスロット:
void actCheckCardUpdates()
スレッドを開始して外部データベースプログラム「oracle.exe」をロードし、カードのステータスを更新します。データベースプログラム名はgetCardUpdaterBinaryName()を介して取得されます。
/* CARD UPDATER */ void MainWindow::actCheckCardUpdates() { if (cardUpdateProcess) { QMessageBox::information(this, tr('Information'), tr('A card database update is already running.')) return } cardUpdateProcess = new QProcess(this) connect(cardUpdateProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(cardUpdateError(QProcess::ProcessError))) connect(cardUpdateProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(cardUpdateFinished(int, QProcess::ExitStatus))) // full 'run the update' command leave empty if not present QString updaterCmd QString binaryName QDir dir = QDir(QApplication::applicationDirPath()) #if defined(Q_OS_MAC) binaryName = getCardUpdaterBinaryName() // exit from the application bundle dir.cdUp() dir.cdUp() dir.cdUp() dir.cd(binaryName + '.app') dir.cd('Contents') dir.cd('MacOS') #elif defined(Q_OS_WIN) binaryName = getCardUpdaterBinaryName() + '.exe' #else binaryName = getCardUpdaterBinaryName() #endif if (dir.exists(binaryName)) updaterCmd = dir.absoluteFilePath(binaryName) if (updaterCmd.isEmpty()) { QMessageBox::warning(this, tr('Error'), tr('Unable to run the card database updater: ') + dir.absoluteFilePath(binaryName)) return } cardUpdateProcess->start(''' + updaterCmd + ''') }
void actCheckServerUpdates()
Cockatriceの公式サーバーアドレスリストを「https://cockatrice.github.io/public-servers.json」からダウンロードします。独自のサーバーを構築する場合は、このURLを変更するか、独自のサーバーアドレスを公式リストに追加する必要があります。
void MainWindow::actCheckServerUpdates() { auto hps = new HandlePublicServers(this) hps->downloadPublicServers() connect(hps, &HandlePublicServers::sigPublicServersDownloadedSuccessfully, [=]() { hps->deleteLater() }) }
プライベートスロット:
void updateTabMenu(const QList&newMenuList)
newMenuListのコンテンツでメニューバーを更新します。
void MainWindow::updateTabMenu(const QList &newMenuList) { for (auto &tabMenu : tabMenus) menuBar()->removeAction(tabMenu->menuAction()) tabMenus = newMenuList for (auto &tabMenu : tabMenus) menuBar()->insertMenu(helpMenu->menuAction(), tabMenu) }
void statusChanged(ClientStatus _status)
void MainWindow::statusChanged(ClientStatus _status) { setClientStatusTitle() switch (_status) { case StatusDisconnected: tabSupervisor->stop() aSinglePlayer->setEnabled(true) aConnect->setEnabled(true) aRegister->setEnabled(true) aDisconnect->setEnabled(false) break case StatusLoggingIn: aSinglePlayer->setEnabled(false) aConnect->setEnabled(false) aRegister->setEnabled(false) aDisconnect->setEnabled(true) break case StatusConnecting: case StatusRegistering: case StatusLoggedIn: default: break } }
void processConnectionClosedEvent(const Event_ConnectionClosed&event)
void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &event) { client->disconnectFromServer() QString reasonStr switch (event.reason()) { case Event_ConnectionClosed::USER_LIMIT_REACHED: reasonStr = tr('The server has reached its maximum user capacity, please check back later.') break case Event_ConnectionClosed::TOO_MANY_CONNECTIONS: reasonStr = tr('There are too many concurrent connections from your address.') break case Event_ConnectionClosed::BANNED: { reasonStr = tr('Banned by moderator') if (event.has_end_time()) reasonStr.append('
' + tr('Expected end time: %1').arg(QDateTime::fromTime_t(event.end_time()).toString())) else reasonStr.append('
' + tr('This ban lasts indefinitely.')) if (event.has_reason_str()) reasonStr.append('
' + QString::fromStdString(event.reason_str())) break } case Event_ConnectionClosed::SERVER_SHUTDOWN: reasonStr = tr('Scheduled server shutdown.') break case Event_ConnectionClosed::USERNAMEINVALID: reasonStr = tr('Invalid username.') break case Event_ConnectionClosed::LOGGEDINELSEWERE: reasonStr = tr('You have been logged out due to logging in at another location.') break default: reasonStr = QString::fromStdString(event.reason_str()) } QMessageBox::critical(this, tr('Connection closed'), tr('The server has terminated your connection.
Reason: %1').arg(reasonStr)) }
void processServerShutdownEvent(const Event_ServerShutdown&event)
void MainWindow::processServerShutdownEvent(const Event_ServerShutdown &event) { serverShutdownMessageBox.setInformativeText(tr('The server is going to be restarted in %n minute(s).
All running ' 'games will be lost.
Reason for shutdown: %1', '', event.minutes()) .arg(QString::fromStdString(event.reason()))) serverShutdownMessageBox.setIconPixmap(QPixmap('theme:cockatrice').scaled(64, 64)) serverShutdownMessageBox.setText(tr('Scheduled server shutdown')) serverShutdownMessageBox.setWindowModality(Qt::ApplicationModal) serverShutdownMessageBox.setVisible(true) }
void serverTimeout()
void MainWindow::serverTimeout() { QMessageBox::critical(this, tr('Error'), tr('Server timeout')) actConnect() }
void loginError(Response :: ResponseCode r、QString reasonStr、quint32 endTime、QList MissingFeatures)
void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32 endTime, QList missingFeatures) { switch (r) { case Response::RespClientUpdateRequired: { QString formattedMissingFeatures formattedMissingFeatures = 'Missing Features: ' for (int i = 0 i Check for Client Updates'.')) msgBox.setDetailedText(formattedMissingFeatures) msgBox.exec() break } case Response::RespWrongPassword: QMessageBox::critical( this, tr('Error'), tr('Incorrect username or password. Please check your authentication information and try again.')) break case Response::RespWouldOverwriteOldSession: QMessageBox::critical(this, tr('Error'), tr('There is already an active session using this user name.
Please close that ' 'session first and re-login.')) break case Response::RespUserIsBanned: { QString bannedStr if (endTime) bannedStr = tr('You are banned until %1.').arg(QDateTime::fromTime_t(endTime).toString()) else bannedStr = tr('You are banned indefinitely.') if (!reasonStr.isEmpty()) bannedStr.append('
' + reasonStr) QMessageBox::critical(this, tr('Error'), bannedStr) break } case Response::RespUsernameInvalid: { QMessageBox::critical(this, tr('Error'), extractInvalidUsernameMessage(reasonStr)) break } case Response::RespRegistrationRequired: if (QMessageBox::question(this, tr('Error'), tr('This server requires user registration. Do you want to register now?'), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { actRegister() } break case Response::RespClientIdRequired: QMessageBox::critical( this, tr('Error'), tr('This server requires client IDs. Your client is either failing to generate an ID or you are ' 'running a modified client.
Please close and reopen your client to try again.')) break case Response::RespContextError: QMessageBox::critical(this, tr('Error'), tr('An internal error has occurred, please close and reopen Cockatrice before trying ' 'again.
If the error persists, ensure you are running the latest version of the ' 'software and if needed contact the software developers.')) break case Response::RespAccountNotActivated: { bool ok = false QString token = QInputDialog::getText(this, tr('Account activation'), tr('Your account has not been activated yet.
You need to provide ' 'the activation token received in the activation email.'), QLineEdit::Normal, QString(), &ok) if (ok && !token.isEmpty()) { client->activateToServer(token) return } client->disconnectFromServer() break } case Response::RespServerFull: { QMessageBox::critical(this, tr('Server Full'), tr('The server has reached its maximum user capacity, please check back later.')) break } default: QMessageBox::critical(this, tr('Error'), tr('Unknown login error: %1').arg(static_cast(r)) + tr('
This usually means that your client version is out of date, and the server ' 'sent a reply your client doesn't understand.')) break } actConnect() }
void registerError(Response :: ResponseCode r、QString reasonStr、quint32 endTime)
void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime) { switch (r) { case Response::RespRegistrationDisabled: QMessageBox::critical(this, tr('Registration denied'), tr('Registration is currently disabled on this server')) break case Response::RespUserAlreadyExists: QMessageBox::critical(this, tr('Registration denied'), tr('There is already an existing account with the same user name.')) break case Response::RespEmailRequiredToRegister: QMessageBox::critical(this, tr('Registration denied'), tr('It's mandatory to specify a valid email address when registering.')) break case Response::RespEmailBlackListed: QMessageBox::critical( this, tr('Registration denied'), tr('The email address provider used during registration has been blacklisted for use on this server.')) break case Response::RespTooManyRequests: QMessageBox::critical( this, tr('Registration denied'), tr('It appears you are attempting to register a new account on this server yet you already have an ' 'account registered with the email provided. This server restricts the number of accounts a user ' 'can register per address. Please contact the server operator for further assistance or to obtain ' 'your credential information.')) break case Response::RespPasswordTooShort: QMessageBox::critical(this, tr('Registration denied'), tr('Password too short.')) break case Response::RespUserIsBanned: { QString bannedStr if (endTime) bannedStr = tr('You are banned until %1.').arg(QDateTime::fromTime_t(endTime).toString()) else bannedStr = tr('You are banned indefinitely.') if (!reasonStr.isEmpty()) bannedStr.append('
' + reasonStr) QMessageBox::critical(this, tr('Error'), bannedStr) break } case Response::RespUsernameInvalid: { QMessageBox::critical(this, tr('Error'), extractInvalidUsernameMessage(reasonStr)) break } case Response::RespRegistrationFailed: QMessageBox::critical(this, tr('Error'), tr('Registration failed for a technical problem on the server.')) break default: QMessageBox::critical(this, tr('Error'), tr('Unknown registration error: %1').arg(static_cast(r)) + tr('
This usually means that your client version is out of date, and the server ' 'sent a reply your client doesn't understand.')) } actRegister() }
void activateError()
void MainWindow::activateError() { QMessageBox::critical(this, tr('Error'), tr('Account activation failed')) client->disconnectFromServer() actConnect() }
void socketError(const QString&errorStr)
void MainWindow::socketError(const QString &errorStr) { QMessageBox::critical(this, tr('Error'), tr('Socket error: %1').arg(errorStr)) actConnect() }
void protocolVersionMismatch(int localVersion、int remoteVersion)
void MainWindow::protocolVersionMismatch(int localVersion, int remoteVersion) { if (localVersion > remoteVersion) QMessageBox::critical(this, tr('Error'), tr('You are trying to connect to an obsolete server. Please downgrade your Cockatrice ' 'version or connect to a suitable server.
Local version is %1, remote version is %2.') .arg(localVersion) .arg(remoteVersion)) else QMessageBox::critical(this, tr('Error'), tr('Your Cockatrice client is obsolete. Please update your Cockatrice version.
Local ' 'version is %1, remote version is %2.') .arg(localVersion) .arg(remoteVersion)) }
void userInfoReceived(const ServerInfo_User&userInfo)
void MainWindow::userInfoReceived(const ServerInfo_User &info) { tabSupervisor->start(info) }
void registerAccepted()
void MainWindow::registerAccepted() { QMessageBox::information(this, tr('Success'), tr('Registration accepted.
Will now login.')) }
void registerAcceptedNeedsActivate()
void MainWindow::registerAcceptedNeedsActivate() { // nothing }
void activateAccepted()
void MainWindow::activateAccepted() { QMessageBox::information(this, tr('Success'), tr('Account activation accepted.
Will now login.')) }
void localGameEnded()
void MainWindow::localGameEnded() { delete localServer localServer = nullptr aConnect->setEnabled(true) aRegister->setEnabled(true) aSinglePlayer->setEnabled(true) }
void pixmapCacheSizeChanged(int newSizeInMBs)
void MainWindow::pixmapCacheSizeChanged(int newSizeInMBs) { // qDebug() << 'Setting pixmap cache size to ' << value << ' MBs' // translate MBs to KBs QPixmapCache::setCacheLimit(newSizeInMBs * 1024) }
void notifyUserAboutUpdate()
void MainWindow::notifyUserAboutUpdate() { QMessageBox::information( this, tr('Information'), tr('This server supports additional features that your client doesn't have.
This is most likely not a ' 'problem, but this message might mean there is a new version of Cockatrice available or this server is ' 'running a custom or pre-release version.
To update your client, go to Help -> Check for Updates.')) }
void actConnect()
void MainWindow::actConnect() { dlgConnect = new DlgConnect(this) connect(dlgConnect, SIGNAL(sigStartForgotPasswordRequest()), this, SLOT(actForgotPasswordRequest())) if (dlgConnect->exec()) { client->connectToServer(dlgConnect->getHost(), static_cast(dlgConnect->getPort()), dlgConnect->getPlayerName(), dlgConnect->getPassword()) } }
void actDisconnect()
void MainWindow::actDisconnect() { client->disconnectFromServer() }
void actSinglePlayer()
void MainWindow::actSinglePlayer() { bool ok int numberPlayers = QInputDialog::getInt(this, tr('Number of players'), tr('Please enter the number of players.'), 1, 1, 8, 1, &ok) if (!ok) return aConnect->setEnabled(false) aRegister->setEnabled(false) aSinglePlayer->setEnabled(false) localServer = new LocalServer(this) LocalServerInterface *mainLsi = localServer->newConnection() LocalClient *mainClient = new LocalClient(mainLsi, tr('Player %1').arg(1), settingsCache->getClientID(), this) QList localClients localClients.append(mainClient) for (int i = 0 i newConnection() LocalClient *slaveClient = new LocalClient(slaveLsi, tr('Player %1').arg(i + 2), settingsCache->getClientID(), this) localClients.append(slaveClient) } tabSupervisor->startLocal(localClients) Command_CreateGame createCommand createCommand.set_max_players(static_cast(numberPlayers)) mainClient->sendCommand(LocalClient::prepareRoomCommand(createCommand, 0)) }
void actWatchReplay()
void MainWindow::actWatchReplay() { QFileDialog dlg(this, tr('Load replay')) dlg.setDirectory(settingsCache->getReplaysPath()) dlg.setNameFilters(QStringList() openReplay(replay) }
void actDeckEditor()
void MainWindow::actDeckEditor() { tabSupervisor->addDeckEditorTab(nullptr) }
void actFullScreen(boolchecked)
void MainWindow::actFullScreen(bool checked) Qt::WindowFullScreen) else setWindowState(windowState() & ~Qt::WindowFullScreen)
void actRegister()
void MainWindow::actRegister() { DlgRegister dlg(this) if (dlg.exec()) { client->registerToServer(dlg.getHost(), static_cast(dlg.getPort()), dlg.getPlayerName(), dlg.getPassword(), dlg.getEmail(), dlg.getGender(), dlg.getCountry(), dlg.getRealName()) } }
void actSettings()
void MainWindow::actSettings() { DlgSettings dlg(this) dlg.exec() }
void actExit()
void MainWindow::actExit() { close() }
void actForgotPasswordRequest()
void MainWindow::actForgotPasswordRequest() { DlgForgotPasswordRequest dlg(this) if (dlg.exec()) client->requestForgotPasswordToServer(dlg.getHost(), static_cast(dlg.getPort()), dlg.getPlayerName()) }
void actAbout()
void MainWindow::actAbout() { QMessageBox mb( QMessageBox::NoIcon, tr('About Cockatrice'), QString(' Cockatrice (' + QString::fromStdString(BUILD_ARCHITECTURE) + ')
' + tr('Version') + QString(' %1').arg(VERSION_STRING) + '
' + tr('Cockatrice Webpage') + '
' + '
' + tr('Project Manager:') + '
Zach Halpern
' + ' ' + tr('Past Project Managers:') + '
Gavin Bisesi
Max-Wilhelm Bruker
Marcus Schütz
' + ' ' + tr('Developers:') + '
' + ' ' + tr('Our Developers') + '
' + ' ' + tr('Help Develop!') + '
' + ' ' + tr('Translators:') + '
' + ' ' + tr('Our Translators') + '
' + ' ' + tr('Help Translate!') + '
' + ' ' + tr('Support:') + '
' + ' ' + tr('Report an Issue') + '
' + ' ' + tr('Troubleshooting') + '
' + ' ' + tr('F.A.Q.') + '
'), QMessageBox::Ok, this) mb.setIconPixmap(QPixmap('theme:cockatrice').scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)) mb.setTextInteractionFlags(Qt::TextBrowserInteraction) mb.exec() }
void actTips()
void MainWindow::actTips() { if (tip != nullptr) { delete tip tip = nullptr } tip = new DlgTipOfTheDay(this) if (tip->successfulInit) { tip->show() } }
void actUpdate()
void MainWindow::actUpdate() { DlgUpdate dlg(this) dlg.exec() }
void actViewLog()
void MainWindow::actViewLog() { if (logviewDialog == nullptr) { logviewDialog = new DlgViewLog(this) } logviewDialog->show() logviewDialog->raise() logviewDialog->activateWindow() }
void forgotPasswordSuccess()
void MainWindow::forgotPasswordSuccess() { QMessageBox::information( this, tr('Forgot Password'), tr('Your password has been reset successfully, you can now log in using the new credentials.')) settingsCache->servers().setFPHostName('') settingsCache->servers().setFPPort('') settingsCache->servers().setFPPlayerName('') }
void forgotPasswordError()
void MainWindow::forgotPasswordError() { QMessageBox::warning( this, tr('Forgot Password'), tr('Failed to reset user account password, please contact the server operator to reset your password.')) settingsCache->servers().setFPHostName('') settingsCache->servers().setFPPort('') settingsCache->servers().setFPPlayerName('') }
void promptForgotPasswordReset()
void MainWindow::promptForgotPasswordReset() { QMessageBox::information(this, tr('Forgot Password'), tr('Activation request received, please check your email for an activation token.')) DlgForgotPasswordReset dlg(this) if (dlg.exec()) { client->submitForgotPasswordResetToServer(dlg.getHost(), static_cast(dlg.getPort()), dlg.getPlayerName(), dlg.getToken(), dlg.getPassword()) } }
void iconActivated(QSystemTrayIcon :: ActivationReason理由)
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { if (reason == QSystemTrayIcon::DoubleClick) { if (windowState() != Qt::WindowMinimized && windowState() != Qt::WindowMinimized + Qt::WindowMaximized) showMinimized() else { showNormal() QApplication::setActiveWindow(this) } } }
void promptForgotPasswordChallenge()
void MainWindow::promptForgotPasswordChallenge() { DlgForgotPasswordChallenge dlg(this) if (dlg.exec()) client->submitForgotPasswordChallengeToServer(dlg.getHost(), static_cast(dlg.getPort()), dlg.getPlayerName(), dlg.getEmail()) }
void showWindowIfHidden()
void MainWindow::showWindowIfHidden() { // keep the previous window state setWindowState(windowState() & ~Qt::WindowMinimized) show() }
void cardUpdateError(QProcess :: ProcessError err)
void MainWindow::cardUpdateError(QProcess::ProcessError err) { QString error switch (err) { case QProcess::FailedToStart: error = tr('failed to start.') break case QProcess::Crashed: error = tr('crashed.') break case QProcess::Timedout: error = tr('timed out.') break case QProcess::WriteError: error = tr('write error.') break case QProcess::ReadError: error = tr('read error.') break case QProcess::UnknownError: default: error = tr('unknown error.') break } cardUpdateProcess->deleteLater() cardUpdateProcess = nullptr QMessageBox::warning(this, tr('Error'), tr('The card database updater exited with an error: %1').arg(error)) }
void cardUpdateFinished(int exitCode、QProcess :: ExitStatus exitStatus)
void MainWindow::cardUpdateFinished(int, QProcess::ExitStatus) { cardUpdateProcess->deleteLater() cardUpdateProcess = nullptr QtConcurrent::run(db, &CardDatabase::loadCardDatabases) }
void refreshShortcuts()
void MainWindow::refreshShortcuts() { aConnect->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aConnect')) aDisconnect->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aDisconnect')) aSinglePlayer->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aSinglePlayer')) aWatchReplay->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aWatchReplay')) aDeckEditor->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aDeckEditor')) aFullScreen->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aFullScreen')) aRegister->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aRegister')) aSettings->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aSettings')) aExit->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aExit')) aCheckCardUpdates->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aCheckCardUpdates')) aOpenCustomFolder->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aOpenCustomFolder')) aManageSets->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aManageSets')) aEditTokens->setShortcuts(settingsCache->shortcuts().getShortcut('MainWindow/aEditTokens')) }
void cardDatabaseLoadingFailed()
void MainWindow::cardDatabaseLoadingFailed() { QMessageBox msgBox msgBox.setWindowTitle(tr('Card database')) msgBox.setIcon(QMessageBox::Question) msgBox.setText(tr('Cockatrice is unable to load the card database.
' 'Do you want to update your card database now?
' 'If unsure or first time user, choose 'Yes'')) QPushButton *yesButton = msgBox.addButton(tr('Yes'), QMessageBox::YesRole) msgBox.addButton(tr('No'), QMessageBox::NoRole) QPushButton *settingsButton = msgBox.addButton(tr('Open settings'), QMessageBox::ActionRole) msgBox.setDefaultButton(yesButton) msgBox.exec() if (msgBox.clickedButton() == yesButton) { actCheckCardUpdates() } else if (msgBox.clickedButton() == settingsButton) { actSettings() } }
void cardDatabaseNewSetsFound(int numUnknownSets、QStringList unknownSetsNames)
void MainWindow::cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknownSetsNames) { QMessageBox msgBox msgBox.setWindowTitle(tr('New sets found')) msgBox.setIcon(QMessageBox::Question) msgBox.setText(tr('%n new set(s) found in the card database
' 'Set code(s): %1
' 'Do you want to enable it/them?', '', numUnknownSets) .arg(unknownSetsNames.join(', '))) QPushButton *yesButton = msgBox.addButton(tr('Yes'), QMessageBox::YesRole) QPushButton *noButton = msgBox.addButton(tr('No'), QMessageBox::NoRole) QPushButton *settingsButton = msgBox.addButton(tr('View sets'), QMessageBox::ActionRole) msgBox.setDefaultButton(yesButton) msgBox.exec() if (msgBox.clickedButton() == yesButton) { db->enableAllUnknownSets() QtConcurrent::run(db, &CardDatabase::loadCardDatabases) } else if (msgBox.clickedButton() == noButton) { db->markAllSetsAsKnown() } else if (msgBox.clickedButton() == settingsButton) { db->markAllSetsAsKnown() actManageSets() } }
void cardDatabaseAllNewSetsEnabled()
void MainWindow::cardDatabaseAllNewSetsEnabled() { QMessageBox::information( this, tr('Welcome'), tr('Hi! It seems like you're running this version of Cockatrice for the first time.
All the sets in the card ' 'database have been enabled.
Read more about changing the set order or disabling specific sets and ' 'consequent effects in the 'Manage Sets' dialog.')) actManageSets() }
void actOpenCustomFolder()
void MainWindow::actOpenCustomFolder() { QString dir = settingsCache->getCustomPicsPath() #if defined(Q_OS_MAC) QStringList scriptArgs scriptArgs << QLatin1String('-e') scriptArgs << QString::fromLatin1(R'(tell application 'Finder' to open POSIX file '%1')').arg(dir) scriptArgs << QLatin1String('-e') scriptArgs << QLatin1String('tell application 'Finder' to activate') QProcess::execute('/usr/bin/osascript', scriptArgs) #elif defined(Q_OS_WIN) QStringList args args << QDir::toNativeSeparators(dir) QProcess::startDetached('explorer', args) #endif }
void actOpenCustomsetsFolder()
void MainWindow::actOpenCustomsetsFolder() { QString dir = settingsCache->getCustomCardDatabasePath() #if defined(Q_OS_MAC) QStringList scriptArgs scriptArgs << QLatin1String('-e') scriptArgs << QString::fromLatin1(R'(tell application 'Finder' to open POSIX file '%1')').arg(dir) scriptArgs << QLatin1String('-e') scriptArgs << QLatin1String('tell application 'Finder' to activate') QProcess::execute('/usr/bin/osascript', scriptArgs) #elif defined(Q_OS_WIN) QStringList args args << QDir::toNativeSeparators(dir) QProcess::startDetached('explorer', args) #endif }
void actAddCustomSet()
void MainWindow::actAddCustomSet() { QFileDialog dialog(this, tr('Load sets/cards'), QDir::homePath()) dialog.setNameFilters(MainWindow::fileNameFilters) if (!dialog.exec()) { return } QString fullFilePath = dialog.selectedFiles().at(0) if (!QFile::exists(fullFilePath)) { QMessageBox::warning(this, tr('Load sets/cards'), tr('Selected file cannot be found.')) return } if (QFileInfo(fullFilePath).suffix() != 'xml') // fileName = *.xml { QMessageBox::warning(this, tr('Load sets/cards'), tr('You can only import XML databases at this time.')) return } QDir dir = settingsCache->getCustomCardDatabasePath() int nextPrefix = getNextCustomSetPrefix(dir) bool res QString fileName = QFileInfo(fullFilePath).fileName() if (fileName.compare('spoiler.xml', Qt::CaseInsensitive) == 0) { /* * If the file being added is 'spoiler.xml' * then we'll want to overwrite the old version * and replace it with the new one */ if (QFile::exists(dir.absolutePath() + '/spoiler.xml')) { QFile::remove(dir.absolutePath() + '/spoiler.xml') } res = QFile::copy(fullFilePath, dir.absolutePath() + '/spoiler.xml') } else { res = QFile::copy(fullFilePath, dir.absolutePath() + '/' + (nextPrefix > 9 ? '' : '0') + QString::number(nextPrefix) + '.' + fileName) } if (res) { QMessageBox::information( this, tr('Load sets/cards'), tr('The new sets/cards have been added successfully.
Cockatrice will now reload the card database.')) QtConcurrent::run(db, &CardDatabase::loadCardDatabases) } else { QMessageBox::warning(this, tr('Load sets/cards'), tr('Sets/cards failed to import.')) } }
void actManageSets()
void MainWindow::actManageSets() { wndSets = new WndSets(this) wndSets->show() }
void actEditTokens()
void MainWindow::actEditTokens() { DlgEditTokens dlg(this) dlg.exec() db->saveCustomTokensToFile() }
void startupConfigCheck()
void MainWindow::startupConfigCheck() { if (settingsCache->getClientVersion() == CLIENT_INFO_NOT_SET) { // no config found, 99% new clean install qDebug() getClientVersion() != VERSION_STRING) { // config found, from another (presumably older) version qDebug() << 'Startup: old client version' setClientVersion(VERSION_STRING) } else { // previous config from this version found qDebug() getShowTipsOnStartup() && tip->newTipsAvailable) { tip->raise() tip->show() } } }
void alertForcedOracleRun(const QString&version、bool isUpdate)
void MainWindow::alertForcedOracleRun(const QString &version, bool isUpdate) { if (isUpdate) { QMessageBox::information(this, tr('New Version'), tr('Congratulations on updating to Cockatrice %1!
' 'Oracle will now launch to update your card database.') .arg(version)) } else { QMessageBox::information(this, tr('Cockatrice installed'), tr('Congratulations on installing Cockatrice %1!
' 'Oracle will now launch to install the initial card database.') .arg(version)) } actCheckCardUpdates() actCheckServerUpdates() }
民間:
static const QString appName
static const QStringList fileNameFilters
QList tabMenus
QMenu * cockatriceMenu
QMenu * dbMenu
QMenu * helpMenu
QMenu * trailIconMenu
QAction * aConnect
QAction * aDisconnect
QAction * aSinglePlayer
QAction * aWatchReplay
QAction * aDeckEditor
QAction * aFullScreen
QAction * aSettings
QAction * aExit
QAction * aAbout
QAction * aTips
QAction * aCheckCardUpdates
QAction * aRegister
QAction * aUpdate
QAction * aViewLog
QAction * closeAction
QAction * aManageSets
QAction * aEditTokens
QAction * aOpenCustomFolder
QAction * aOpenCustomsetsFolder
QAction * aAddCustomSet
TabSupervisor * tabSupervisor
WndSets * wndSets
RemoteClient * client
QThread * clientThread
LocalServer * localServer
bool bHasActivated
QMessageBox serverShutdownMessageBox
QProcess * cardUpdateProcess
DlgViewLog * logviewDialog
DlgConnect * dlgConnect
GameReplay *リプレイ
DlgTipOfTheDay *ヒント
QUrl connectTo