From fd7593edc177c8d37ef505c2cf61b5705d64d720 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 17:55:20 +0100 Subject: [PATCH 01/87] improved logging, improved server multithreading --- common/server_protocolhandler.cpp | 13 ++++++--- common/server_protocolhandler.h | 1 + common/server_room.cpp | 10 ++++--- common/server_room.h | 5 +++- servatrice/servatrice.pro | 2 ++ servatrice/src/main.cpp | 25 ++++++++++++++--- servatrice/src/servatrice.cpp | 31 ++++++++++++++------- servatrice/src/servatrice.h | 22 +++++++++++++-- servatrice/src/server_logger.cpp | 34 +++++++++++++++++++----- servatrice/src/server_logger.h | 2 +- servatrice/src/serversocketinterface.cpp | 14 ++++++++++ 11 files changed, 128 insertions(+), 31 deletions(-) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 36cb48319..942d45080 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -353,6 +353,7 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC return RespNameNotFound; r->addClient(this); + connect(r, SIGNAL(gameCreated(Server_Game *)), this, SLOT(gameCreated(Server_Game *))); rooms.insert(r->getId(), r); enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage())); @@ -420,13 +421,17 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm for (int i = 0; i < gameTypeList.size(); ++i) gameTypes.append(gameTypeList[i]->getData()); - Server_Game *game = room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); + room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); + return RespOk; +} + +void Server_ProtocolHandler::gameCreated(Server_Game *game) +{ Server_Player *creator = game->getPlayers().values().first(); games.insert(game->getGameId(), QPair(game, creator)); - enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); - enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId())); - return RespOk; + sendProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); + sendProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId())); } ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandContainer * /*cont*/, Server_Room *room) diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 677ba0956..e8b4dfac6 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -91,6 +91,7 @@ private: ResponseCode processCommandHelper(Command *command, CommandContainer *cont); private slots: void pingClockTimeout(); + void gameCreated(Server_Game *game); public: Server_ProtocolHandler(Server *_server, QObject *parent = 0); ~Server_ProtocolHandler(); diff --git a/common/server_room.cpp b/common/server_room.cpp index fe7b83ee9..4e9182186 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -6,6 +6,7 @@ Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) : QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes) { + connect(this, SIGNAL(sigCreateGame(const QString &, const QString &, int, const QList &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *)), this, SLOT(doCreateGame(const QString &, const QString &, int, const QList &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *))); } Server *Server_Room::getServer() const @@ -68,7 +69,7 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game) delete event; } -Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) +void Server_Room::doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) { Server_Game *newGame = new Server_Game(creator, static_cast(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); games.insert(newGame->getGameId(), newGame); @@ -78,8 +79,11 @@ Server_Game *Server_Room::createGame(const QString &description, const QString & emit gameCreated(newGame); emit roomInfoChanged(); - - return newGame; +} + +void Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) +{ + emit sigCreateGame(description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, creator); } void Server_Room::removeGame() diff --git a/common/server_room.h b/common/server_room.h index 8571f04ea..0cd2b8b4e 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -19,6 +19,8 @@ signals: void roomInfoChanged(); void gameCreated(Server_Game *game); void gameClosing(int gameId); + + void sigCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); private: int id; QString name; @@ -28,6 +30,7 @@ private: QStringList gameTypes; QMap games; private slots: + void doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); void removeGame(); public: Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent); @@ -44,7 +47,7 @@ public: void removeClient(Server_ProtocolHandler *client); void say(Server_ProtocolHandler *client, const QString &s); void broadcastGameListUpdate(Server_Game *game); - Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); + void createGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); void sendRoomEvent(RoomEvent *event); }; diff --git a/servatrice/servatrice.pro b/servatrice/servatrice.pro index 86f1d960a..a8de8ad32 100755 --- a/servatrice/servatrice.pro +++ b/servatrice/servatrice.pro @@ -17,6 +17,7 @@ HEADERS += src/main.h \ src/servatrice.h \ src/serversocketinterface.h \ src/server_logger.h \ + src/serversocketthread.h \ ../common/color.h \ ../common/serializable_item.h \ ../common/decklist.h \ @@ -40,6 +41,7 @@ SOURCES += src/main.cpp \ src/servatrice.cpp \ src/serversocketinterface.cpp \ src/server_logger.cpp \ + src/serversocketthread.cpp \ ../common/serializable_item.cpp \ ../common/decklist.cpp \ ../common/protocol.cpp \ diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index 8dcd95fb4..9c4c25e5f 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "servatrice.h" #include "server_logger.h" #include "rng_sfmt.h" @@ -65,14 +67,27 @@ void testRNG() std::cerr << std::endl << std::endl; } +void myMessageOutput(QtMsgType /*type*/, const char *msg) +{ + logger->logMessage(msg); +} + int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); app.setOrganizationName("Cockatrice"); app.setApplicationName("Servatrice"); + QStringList args = app.arguments(); + bool testRandom = args.contains("--test-random"); + + qRegisterMetaType >("QList"); + QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); - logger = new ServerLogger; + + QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat); + logger = new ServerLogger(settings->value("server/logfile").toString()); + qInstallMsgHandler(myMessageOutput); #ifdef Q_OS_UNIX struct sigaction hup; hup.sa_handler = ServerLogger::hupSignalHandler; @@ -85,10 +100,11 @@ int main(int argc, char *argv[]) std::cerr << "Servatrice " << Servatrice::versionString.toStdString() << " starting." << std::endl; std::cerr << "-------------------------" << std::endl; - - testRNG(); - Servatrice server; + if (testRandom) + testRNG(); + + Servatrice server(settings); std::cerr << "-------------------------" << std::endl; std::cerr << "Server initialized." << std::endl; @@ -96,6 +112,7 @@ int main(int argc, char *argv[]) int retval = app.exec(); delete rng; + delete settings; return retval; } diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 8558de405..5eb45bbd1 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -24,10 +24,18 @@ #include "servatrice.h" #include "server_room.h" #include "serversocketinterface.h" +#include "serversocketthread.h" #include "protocol.h" -Servatrice::Servatrice(QObject *parent) - : Server(parent), uptime(0) +void Servatrice_TcpServer::incomingConnection(int socketDescriptor) +{ + ServerSocketThread *sst = new ServerSocketThread(socketDescriptor, server, this); + connect(sst, SIGNAL(clientAdded(ServerSocketInterface *)), this, SIGNAL(clientAdded(ServerSocketInterface *))); + sst->start(); +} + +Servatrice::Servatrice(QSettings *_settings, QObject *parent) + : Server(parent), dbMutex(QMutex::Recursive), settings(_settings), uptime(0) { pingClock = new QTimer(this); connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); @@ -38,7 +46,6 @@ Servatrice::Servatrice(QObject *parent) banTimeoutClock->start(60000); ProtocolItem::initializeHash(); - settings = new QSettings("servatrice.ini", QSettings::IniFormat, this); int statusUpdateTime = settings->value("server/statusupdate").toInt(); statusUpdateClock = new QTimer(this); @@ -48,8 +55,8 @@ Servatrice::Servatrice(QObject *parent) statusUpdateClock->start(statusUpdateTime); } - tcpServer = new QTcpServer(this); - connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + tcpServer = new Servatrice_TcpServer(this); + connect(tcpServer, SIGNAL(clientAdded(ServerSocketInterface *)), this, SLOT(newConnection(ServerSocketInterface *))); int port = settings->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << port; tcpServer->listen(QHostAddress::Any, port); @@ -133,6 +140,7 @@ bool Servatrice::openDatabase() void Servatrice::checkSql() { + QMutexLocker locker(&dbMutex); if (!QSqlDatabase::database().exec("select 1").isActive()) openDatabase(); } @@ -145,15 +153,14 @@ bool Servatrice::execSqlQuery(QSqlQuery &query) return false; } -void Servatrice::newConnection() +void Servatrice::newConnection(ServerSocketInterface *client) { - QTcpSocket *socket = tcpServer->nextPendingConnection(); - ServerSocketInterface *ssi = new ServerSocketInterface(this, socket); - addClient(ssi); + addClient(client); } AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QString &password) { + QMutexLocker locker(&dbMutex); const QString method = settings->value("authentication/method").toString(); if (method == "none") return UnknownUser; @@ -181,6 +188,7 @@ AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QS bool Servatrice::userExists(const QString &user) { + QMutexLocker locker(&dbMutex); const QString method = settings->value("authentication/method").toString(); if (method == "sql") { checkSql(); @@ -219,6 +227,7 @@ ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool co ServerInfo_User *Servatrice::getUserData(const QString &name) { + QMutexLocker locker(&dbMutex); const QString method = settings->value("authentication/method").toString(); if (method == "sql") { checkSql(); @@ -248,6 +257,7 @@ int Servatrice::getUsersWithAddress(const QHostAddress &address) const QMap Servatrice::getBuddyList(const QString &name) { + QMutexLocker locker(&dbMutex); QMap result; const QString method = settings->value("authentication/method").toString(); @@ -270,6 +280,7 @@ QMap Servatrice::getBuddyList(const QString &name) QMap Servatrice::getIgnoreList(const QString &name) { + QMutexLocker locker(&dbMutex); QMap result; const QString method = settings->value("authentication/method").toString(); @@ -318,6 +329,7 @@ void Servatrice::updateBanTimer() void Servatrice::updateLoginMessage() { + QMutexLocker locker(&dbMutex); checkSql(); QSqlQuery query; query.prepare("select message from " + dbPrefix + "_servermessages order by timest desc limit 1"); @@ -336,6 +348,7 @@ void Servatrice::updateLoginMessage() void Servatrice::statusUpdate() { + QMutexLocker locker(&dbMutex); uptime += statusUpdateClock->interval() / 1000; checkSql(); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index c53b5338d..5ac3afecb 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -21,6 +21,7 @@ #define SERVATRICE_H #include +#include #include "server.h" class QSqlDatabase; @@ -28,16 +29,33 @@ class QSettings; class QSqlQuery; class QTimer; +class Servatrice; +class ServerSocketInterface; + +class Servatrice_TcpServer : public QTcpServer { + Q_OBJECT +private: + Servatrice *server; +public: + Servatrice_TcpServer(Servatrice *_server, QObject *parent = 0) + : QTcpServer(parent), server(_server) { } +protected: + void incomingConnection(int socketDescriptor); +signals: + void clientAdded(ServerSocketInterface *client); +}; + class Servatrice : public Server { Q_OBJECT private slots: - void newConnection(); + void newConnection(ServerSocketInterface *client); void statusUpdate(); void updateBanTimer(); public: + QMutex dbMutex; static const QString versionString; - Servatrice(QObject *parent = 0); + Servatrice(QSettings *_settings, QObject *parent = 0); ~Servatrice(); bool openDatabase(); void checkSql(); diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index 60a056af3..b06652792 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -2,19 +2,27 @@ #include #include #include +#include +#include +#include +#ifdef Q_OS_UNIX #include #include +#endif -ServerLogger::ServerLogger(QObject *parent) +ServerLogger::ServerLogger(const QString &logFileName, QObject *parent) : QObject(parent) { - logFile = new QFile("server.log", this); - logFile->open(QIODevice::Append); + if (!logFileName.isEmpty()) { + logFile = new QFile(logFileName, this); + logFile->open(QIODevice::Append); #ifdef Q_OS_UNIX - ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); + ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); #endif - snHup = new QSocketNotifier(sigHupFD[1], QSocketNotifier::Read, this); - connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup())); + snHup = new QSocketNotifier(sigHupFD[1], QSocketNotifier::Read, this); + connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup())); + } else + logFile = 0; } ServerLogger::~ServerLogger() @@ -23,18 +31,30 @@ ServerLogger::~ServerLogger() void ServerLogger::logMessage(QString message) { + if (!logFile) + return; + + static QMutex mutex; + mutex.lock(); QTextStream stream(logFile); - stream << message << "\n"; + stream << QDateTime::currentDateTime().toString() << " " << ((void *) QThread::currentThread()) << " " << message << "\n"; + mutex.unlock(); } void ServerLogger::hupSignalHandler(int /*unused*/) { + if (!logFile) + return; + char a = 1; ::write(sigHupFD[0], &a, sizeof(a)); } void ServerLogger::handleSigHup() { + if (!logFile) + return; + snHup->setEnabled(false); char tmp; ::read(sigHupFD[1], &tmp, sizeof(tmp)); diff --git a/servatrice/src/server_logger.h b/servatrice/src/server_logger.h index a9bd3eec1..c1fb7872e 100644 --- a/servatrice/src/server_logger.h +++ b/servatrice/src/server_logger.h @@ -9,7 +9,7 @@ class QFile; class ServerLogger : public QObject { Q_OBJECT public: - ServerLogger(QObject *parent = 0); + ServerLogger(const QString &logFileName, QObject *parent = 0); ~ServerLogger(); static void hupSignalHandler(int unused); public slots: diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 115457b4c..2a65e8b69 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -101,14 +101,18 @@ void ServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socket void ServerSocketInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) { + static QMutex mutex; + mutex.lock(); item->write(xmlWriter); socket->flush(); + mutex.unlock(); if (deleteItem) delete item; } int ServerSocketInterface::getUserIdInDB(const QString &name) const { + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("select id from " + servatrice->getDbPrefix() + "_users where name = :name"); query.bindValue(":name", name); @@ -142,6 +146,7 @@ ResponseCode ServerSocketInterface::cmdAddToList(Command_AddToList *cmd, Command if (id1 == id2) return RespContextError; + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("insert into " + servatrice->getDbPrefix() + "_" + list + "list (id_user1, id_user2) values(:id1, :id2)"); query.bindValue(":id1", id1); @@ -180,6 +185,7 @@ ResponseCode ServerSocketInterface::cmdRemoveFromList(Command_RemoveFromList *cm if (id2 < 0) return RespNameNotFound; + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("delete from " + servatrice->getDbPrefix() + "_" + list + "list where id_user1 = :id1 and id_user2 = :id2"); query.bindValue(":id1", id1); @@ -206,6 +212,7 @@ int ServerSocketInterface::getDeckPathId(int basePathId, QStringList path) if (path[0].isEmpty()) return 0; + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent and name = :name and user = :user"); query.bindValue(":id_parent", basePathId); @@ -229,6 +236,7 @@ int ServerSocketInterface::getDeckPathId(const QString &path) bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder) { + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("select id, name from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent and user = :user"); query.bindValue(":id_parent", folder->getId()); @@ -288,6 +296,7 @@ ResponseCode ServerSocketInterface::cmdDeckNewDir(Command_DeckNewDir *cmd, Comma if (folderId == -1) return RespNameNotFound; + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_folders (id_parent, user, name) values(:id_parent, :user, :name)"); query.bindValue(":id_parent", folderId); @@ -302,6 +311,7 @@ void ServerSocketInterface::deckDelDirHelper(int basePathId) { servatrice->checkSql(); + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent"); @@ -340,6 +350,7 @@ ResponseCode ServerSocketInterface::cmdDeckDel(Command_DeckDel *cmd, CommandCont servatrice->checkSql(); + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user"); @@ -379,6 +390,7 @@ ResponseCode ServerSocketInterface::cmdDeckUpload(Command_DeckUpload *cmd, Comma if (deckName.isEmpty()) deckName = "Unnamed deck"; + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_files (id_folder, user, name, upload_time, content) values(:id_folder, :user, :name, NOW(), :content)"); query.bindValue(":id_folder", folderId); @@ -395,6 +407,7 @@ DeckList *ServerSocketInterface::getDeckFromDatabase(int deckId) { servatrice->checkSql(); + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("select content from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user"); @@ -447,6 +460,7 @@ ResponseCode ServerSocketInterface::cmdBanFromServer(Command_BanFromServer *cmd, if (user->getUserInfo()->getUserLevel() & ServerInfo_User::IsRegistered) { // Registered users can be banned by name. if (minutes == 0) { + QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("update " + servatrice->getDbPrefix() + "_users set banned=1 where name = :name"); query.bindValue(":name", userName); From 1b996fa0f8ea2c84874742794e4ed396b2429725 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 18:02:11 +0100 Subject: [PATCH 02/87] introduced server id for status update --- servatrice/src/servatrice.cpp | 4 +++- servatrice/src/servatrice.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 5eb45bbd1..511525c2a 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -47,6 +47,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) ProtocolItem::initializeHash(); + serverId = settings->value("server/id", 0).toInt(); int statusUpdateTime = settings->value("server/statusupdate").toInt(); statusUpdateClock = new QTimer(this); connect(statusUpdateClock, SIGNAL(timeout()), this, SLOT(statusUpdate())); @@ -354,7 +355,8 @@ void Servatrice::statusUpdate() checkSql(); QSqlQuery query; - query.prepare("insert into " + dbPrefix + "_uptime (timest, uptime, users_count, games_count) values(NOW(), :uptime, :users_count, :games_count)"); + query.prepare("insert into " + dbPrefix + "_uptime (id_server, timest, uptime, users_count, games_count) values(:id, NOW(), :uptime, :users_count, :games_count)"); + query.bindValue(":id", serverId); query.bindValue(":uptime", uptime); query.bindValue(":users_count", users.size()); query.bindValue(":games_count", games.size()); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 5ac3afecb..c4be3ec71 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -86,6 +86,7 @@ private: QString loginMessage; QString dbPrefix; QSettings *settings; + int serverId; int uptime; QList > addressBanList; QList > nameBanList; From d96f6d8b910150f50e5a4a65df179afd2af8a137 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 18:02:35 +0100 Subject: [PATCH 03/87] updated servatrice.ini.example --- servatrice/servatrice.ini.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 956ca0dfc..37e88a75e 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -1,6 +1,8 @@ [server] port=4747 statusupdate=15000 +logfile=server.log +id=1 [authentication] method=none From 3f5035c38c1004614b872ef0ef05346197a23f0f Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 18:03:26 +0100 Subject: [PATCH 04/87] added missing files --- servatrice/src/serversocketthread.cpp | 29 +++++++++++++++++++++++++++ servatrice/src/serversocketthread.h | 24 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 servatrice/src/serversocketthread.cpp create mode 100644 servatrice/src/serversocketthread.h diff --git a/servatrice/src/serversocketthread.cpp b/servatrice/src/serversocketthread.cpp new file mode 100644 index 000000000..4bb7129ae --- /dev/null +++ b/servatrice/src/serversocketthread.cpp @@ -0,0 +1,29 @@ +#include "serversocketthread.h" +#include "serversocketinterface.h" +#include "server_logger.h" +#include "main.h" + +ServerSocketThread::ServerSocketThread(int _socketDescriptor, Servatrice *_server, QObject *parent) + : QThread(parent), server(_server), socketDescriptor(_socketDescriptor) +{ +} + +ServerSocketThread::~ServerSocketThread() +{ + quit(); + wait(); +} + +void ServerSocketThread::run() +{ + QTcpSocket *socket = new QTcpSocket; + socket->setSocketDescriptor(socketDescriptor); + logger->logMessage(QString("incoming connection: %1").arg(socket->peerAddress().toString())); + + ssi = new ServerSocketInterface(server, socket); + connect(ssi, SIGNAL(destroyed()), this, SLOT(deleteLater())); + + emit clientAdded(ssi); + + exec(); +} diff --git a/servatrice/src/serversocketthread.h b/servatrice/src/serversocketthread.h new file mode 100644 index 000000000..867756b5b --- /dev/null +++ b/servatrice/src/serversocketthread.h @@ -0,0 +1,24 @@ +#ifndef SERVERSOCKETTHREAD_H +#define SERVERSOCKETTHREAD_H + +#include + +class Servatrice; +class ServerSocketInterface; + +class ServerSocketThread : public QThread { + Q_OBJECT +private: + Servatrice *server; + ServerSocketInterface *ssi; + int socketDescriptor; +public: + ServerSocketThread(int _socketDescriptor, Servatrice *_server, QObject *parent = 0); + ~ServerSocketThread(); +protected: + void run(); +signals: + void clientAdded(ServerSocketInterface *client); +}; + +#endif From 4548841a93c3a1a47d370e721a8466b6c195beba Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 18:31:26 +0100 Subject: [PATCH 05/87] server crash fix --- common/server_protocolhandler.cpp | 1 - common/server_protocolhandler.h | 2 +- common/server_room.cpp | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 942d45080..c5948bf5d 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -353,7 +353,6 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC return RespNameNotFound; r->addClient(this); - connect(r, SIGNAL(gameCreated(Server_Game *)), this, SLOT(gameCreated(Server_Game *))); rooms.insert(r->getId(), r); enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage())); diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index e8b4dfac6..075ba0cfb 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -91,7 +91,6 @@ private: ResponseCode processCommandHelper(Command *command, CommandContainer *cont); private slots: void pingClockTimeout(); - void gameCreated(Server_Game *game); public: Server_ProtocolHandler(Server *_server, QObject *parent = 0); ~Server_ProtocolHandler(); @@ -104,6 +103,7 @@ public: const QMap &getBuddyList() const { return buddyList; } const QMap &getIgnoreList() const { return ignoreList; } + void gameCreated(Server_Game *game); int getLastCommandTime() const { return timeRunning - lastDataReceived; } void processCommandContainer(CommandContainer *cont); virtual void sendProtocolItem(ProtocolItem *item, bool deleteItem = true) = 0; diff --git a/common/server_room.cpp b/common/server_room.cpp index 4e9182186..a80856923 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -77,6 +77,7 @@ void Server_Room::doCreateGame(const QString &description, const QString &passwo broadcastGameListUpdate(newGame); + creator->gameCreated(newGame); emit gameCreated(newGame); emit roomInfoChanged(); } From 81a5d58d70b8b71d459de4611b173341ea4a17ef Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 19:37:56 +0100 Subject: [PATCH 06/87] more mutexes --- common/server_cardzone.cpp | 21 ++++++++++++++++ common/server_game.cpp | 35 ++++++++++++++++++++++++++- common/server_game.h | 2 ++ common/server_player.cpp | 40 +++++++++++++++++++++++++++++++ common/server_player.h | 5 +++- common/server_protocolhandler.cpp | 4 ++++ common/server_room.cpp | 16 ++++++++++++- common/server_room.h | 2 ++ servatrice/src/server_logger.cpp | 7 +++--- servatrice/src/server_logger.h | 2 ++ 10 files changed, 127 insertions(+), 7 deletions(-) diff --git a/common/server_cardzone.cpp b/common/server_cardzone.cpp index 7a0ea239d..f686d423e 100644 --- a/common/server_cardzone.cpp +++ b/common/server_cardzone.cpp @@ -23,6 +23,7 @@ #include "rng_abstract.h" #include #include +#include "server_game.h" Server_CardZone::Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ZoneType _type) : player(_player), name(_name), has_coords(_has_coords), type(_type), cardsBeingLookedAt(0) @@ -37,6 +38,8 @@ Server_CardZone::~Server_CardZone() void Server_CardZone::shuffle() { + QMutexLocker locker(&player->getGame()->gameMutex); + QList temp; for (int i = cards.size(); i; i--) temp.append(cards.takeAt(rng->getNumber(0, i - 1))); @@ -45,6 +48,8 @@ void Server_CardZone::shuffle() int Server_CardZone::removeCard(Server_Card *card) { + QMutexLocker locker(&player->getGame()->gameMutex); + int index = cards.indexOf(card); cards.removeAt(index); return index; @@ -52,6 +57,8 @@ int Server_CardZone::removeCard(Server_Card *card) Server_Card *Server_CardZone::getCard(int id, bool remove, int *position) { + QMutexLocker locker(&player->getGame()->gameMutex); + if (type != HiddenZone) { QListIterator CardIterator(cards); int i = 0; @@ -85,6 +92,8 @@ Server_Card *Server_CardZone::getCard(int id, bool remove, int *position) int Server_CardZone::getFreeGridColumn(int x, int y, const QString &cardName) const { + QMutexLocker locker(&player->getGame()->gameMutex); + QMap coordMap; for (int i = 0; i < cards.size(); ++i) if (cards[i]->getY() == y) @@ -131,6 +140,8 @@ bool Server_CardZone::isColumnStacked(int x, int y) const if (!has_coords) return false; + QMutexLocker locker(&player->getGame()->gameMutex); + QMap coordMap; for (int i = 0; i < cards.size(); ++i) if (cards[i]->getY() == y) @@ -144,6 +155,8 @@ bool Server_CardZone::isColumnEmpty(int x, int y) const if (!has_coords) return true; + QMutexLocker locker(&player->getGame()->gameMutex); + QMap coordMap; for (int i = 0; i < cards.size(); ++i) if (cards[i]->getY() == y) @@ -154,6 +167,8 @@ bool Server_CardZone::isColumnEmpty(int x, int y) const void Server_CardZone::moveCard(CommandContainer *cont, QMap &coordMap, Server_Card *card, int x, int y) { + QMutexLocker locker(&player->getGame()->gameMutex); + coordMap.remove(card->getY() * 10000 + card->getX()); CardToMove *cardToMove = new CardToMove(card->getId()); @@ -165,6 +180,8 @@ void Server_CardZone::moveCard(CommandContainer *cont, QMap void Server_CardZone::fixFreeSpaces(CommandContainer *cont) { + QMutexLocker locker(&player->getGame()->gameMutex); + QMap coordMap; QSet placesToLook; for (int i = 0; i < cards.size(); ++i) { @@ -194,6 +211,8 @@ void Server_CardZone::fixFreeSpaces(CommandContainer *cont) void Server_CardZone::insertCard(Server_Card *card, int x, int y) { + QMutexLocker locker(&player->getGame()->gameMutex); + if (hasCoords()) { card->setCoords(x, y); cards.append(card); @@ -206,6 +225,8 @@ void Server_CardZone::insertCard(Server_Card *card, int x, int y) void Server_CardZone::clear() { + QMutexLocker locker(&player->getGame()->gameMutex); + for (int i = 0; i < cards.size(); i++) delete cards.at(i); cards.clear(); diff --git a/common/server_game.cpp b/common/server_game.cpp index 92501dfe0..3f0d67bb3 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -29,7 +29,7 @@ #include Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent) - : QObject(parent), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0) + : QObject(parent), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0), gameMutex(QMutex::Recursive) { addPlayer(_creator, false, false); @@ -42,6 +42,8 @@ Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QS Server_Game::~Server_Game() { + QMutexLocker locker(&gameMutex); + sendGameEvent(new Event_GameClosed); QMapIterator playerIterator(players); @@ -56,6 +58,7 @@ Server_Game::~Server_Game() void Server_Game::pingClockTimeout() { + QMutexLocker locker(&gameMutex); ++secondsElapsed; QList pingList; @@ -83,6 +86,8 @@ void Server_Game::pingClockTimeout() int Server_Game::getPlayerCount() const { + QMutexLocker locker(&gameMutex); + QMapIterator playerIterator(players); int result = 0; while (playerIterator.hasNext()) @@ -93,6 +98,8 @@ int Server_Game::getPlayerCount() const int Server_Game::getSpectatorCount() const { + QMutexLocker locker(&gameMutex); + QMapIterator playerIterator(players); int result = 0; while (playerIterator.hasNext()) @@ -103,6 +110,8 @@ int Server_Game::getSpectatorCount() const void Server_Game::startGameIfReady() { + QMutexLocker locker(&gameMutex); + if (getPlayerCount() < maxPlayers) return; QMapIterator playerIterator(players); @@ -149,6 +158,8 @@ void Server_Game::startGameIfReady() void Server_Game::stopGameIfFinished() { + QMutexLocker locker(&gameMutex); + QMapIterator playerIterator(players); int playing = 0; while (playerIterator.hasNext()) { @@ -194,6 +205,8 @@ ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_passw Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spectator, bool broadcastUpdate) { + QMutexLocker locker(&gameMutex); + const QList &keyList = players.keys(); int playerId = keyList.isEmpty() ? 0 : (keyList.last() + 1); @@ -209,6 +222,8 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec void Server_Game::removePlayer(Server_Player *player) { + QMutexLocker locker(&gameMutex); + players.remove(player->getPlayerId()); removeArrowsToPlayer(player); @@ -229,6 +244,8 @@ void Server_Game::removePlayer(Server_Player *player) void Server_Game::removeArrowsToPlayer(Server_Player *player) { + QMutexLocker locker(&gameMutex); + // Remove all arrows of other players pointing to the player being removed or to one of his cards. QMapIterator playerIterator(players); while (playerIterator.hasNext()) { @@ -253,6 +270,8 @@ void Server_Game::removeArrowsToPlayer(Server_Player *player) bool Server_Game::kickPlayer(int playerId) { + QMutexLocker locker(&gameMutex); + Server_Player *playerToKick = players.value(playerId); if (!playerToKick) return false; @@ -265,6 +284,8 @@ bool Server_Game::kickPlayer(int playerId) void Server_Game::setActivePlayer(int _activePlayer) { + QMutexLocker locker(&gameMutex); + activePlayer = _activePlayer; sendGameEvent(new Event_SetActivePlayer(activePlayer, activePlayer)); setActivePhase(0); @@ -272,6 +293,8 @@ void Server_Game::setActivePlayer(int _activePlayer) void Server_Game::setActivePhase(int _activePhase) { + QMutexLocker locker(&gameMutex); + QMapIterator playerIterator(players); while (playerIterator.hasNext()) { Server_Player *player = playerIterator.next().value(); @@ -289,6 +312,8 @@ void Server_Game::setActivePhase(int _activePhase) void Server_Game::nextTurn() { + QMutexLocker locker(&gameMutex); + const QList keys = players.keys(); int listPos = -1; if (activePlayer != -1) @@ -304,6 +329,8 @@ void Server_Game::nextTurn() QList Server_Game::getGameState(Server_Player *playerWhosAsking) const { + QMutexLocker locker(&gameMutex); + QList result; QMapIterator playerIterator(players); while (playerIterator.hasNext()) { @@ -392,6 +419,8 @@ void Server_Game::sendGameEvent(GameEvent *event, GameEventContext *context, Ser void Server_Game::sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude, bool excludeOmniscient) { + QMutexLocker locker(&gameMutex); + cont->setGameId(gameId); QMapIterator playerIterator(players); while (playerIterator.hasNext()) { @@ -405,6 +434,8 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont, Server_Player void Server_Game::sendGameEventContainerOmniscient(GameEventContainer *cont, Server_Player *exclude) { + QMutexLocker locker(&gameMutex); + cont->setGameId(gameId); QMapIterator playerIterator(players); while (playerIterator.hasNext()) { @@ -423,6 +454,8 @@ void Server_Game::sendGameEventToPlayer(Server_Player *player, GameEvent *event) ServerInfo_Game *Server_Game::getInfo() const { + QMutexLocker locker(&gameMutex); + if (players.isEmpty()) // Game is closing return new ServerInfo_Game(getGameId(), QString(), false, 0, getMaxPlayers(), QList(), 0, false, 0); diff --git a/common/server_game.h b/common/server_game.h index 02e8ffdb0..2ce9b89eb 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "server_player.h" #include "protocol.h" @@ -55,6 +56,7 @@ signals: private slots: void pingClockTimeout(); public: + mutable QMutex gameMutex; Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent); ~Server_Game(); ServerInfo_Game *getInfo() const; diff --git a/common/server_player.cpp b/common/server_player.cpp index ab29820f1..77c37622f 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -17,6 +17,8 @@ Server_Player::Server_Player(Server_Game *_game, int _playerId, ServerInfo_User Server_Player::~Server_Player() { + QMutexLocker locker(&game->gameMutex); + delete deck; if (handler) @@ -28,11 +30,15 @@ Server_Player::~Server_Player() int Server_Player::newCardId() { + QMutexLocker locker(&game->gameMutex); + return nextCardId++; } int Server_Player::newCounterId() const { + QMutexLocker locker(&game->gameMutex); + int id = 0; QMapIterator i(counters); while (i.hasNext()) { @@ -45,6 +51,8 @@ int Server_Player::newCounterId() const int Server_Player::newArrowId() const { + QMutexLocker locker(&game->gameMutex); + int id = 0; QMapIterator i(arrows); while (i.hasNext()) { @@ -57,6 +65,8 @@ int Server_Player::newArrowId() const void Server_Player::setupZones() { + QMutexLocker locker(&game->gameMutex); + // This may need to be customized according to the game rules. // ------------------------------------------------------------------ @@ -138,6 +148,8 @@ void Server_Player::setupZones() void Server_Player::clearZones() { + QMutexLocker locker(&game->gameMutex); + QMapIterator zoneIterator(zones); while (zoneIterator.hasNext()) delete zoneIterator.next().value(); @@ -158,11 +170,15 @@ void Server_Player::clearZones() ServerInfo_PlayerProperties *Server_Player::getProperties() { + QMutexLocker locker(&game->gameMutex); + return new ServerInfo_PlayerProperties(playerId, new ServerInfo_User(userInfo), spectator, conceded, readyStart, deckId); } void Server_Player::setDeck(DeckList *_deck, int _deckId) { + QMutexLocker locker(&game->gameMutex); + delete deck; deck = _deck; deckId = _deckId; @@ -170,16 +186,22 @@ void Server_Player::setDeck(DeckList *_deck, int _deckId) void Server_Player::addZone(Server_CardZone *zone) { + QMutexLocker locker(&game->gameMutex); + zones.insert(zone->getName(), zone); } void Server_Player::addArrow(Server_Arrow *arrow) { + QMutexLocker locker(&game->gameMutex); + arrows.insert(arrow->getId(), arrow); } bool Server_Player::deleteArrow(int arrowId) { + QMutexLocker locker(&game->gameMutex); + Server_Arrow *arrow = arrows.value(arrowId, 0); if (!arrow) return false; @@ -190,11 +212,15 @@ bool Server_Player::deleteArrow(int arrowId) void Server_Player::addCounter(Server_Counter *counter) { + QMutexLocker locker(&game->gameMutex); + counters.insert(counter->getId(), counter); } bool Server_Player::deleteCounter(int counterId) { + QMutexLocker locker(&game->gameMutex); + Server_Counter *counter = counters.value(counterId, 0); if (!counter) return false; @@ -205,6 +231,8 @@ bool Server_Player::deleteCounter(int counterId) ResponseCode Server_Player::drawCards(CommandContainer *cont, int number) { + QMutexLocker locker(&game->gameMutex); + Server_CardZone *deckZone = zones.value("deck"); Server_CardZone *handZone = zones.value("hand"); if (deckZone->cards.size() < number) @@ -228,6 +256,8 @@ ResponseCode Server_Player::drawCards(CommandContainer *cont, int number) ResponseCode Server_Player::undoDraw(CommandContainer *cont) { + QMutexLocker locker(&game->gameMutex); + if (lastDrawList.isEmpty()) return RespContextError; @@ -240,6 +270,8 @@ ResponseCode Server_Player::undoDraw(CommandContainer *cont) ResponseCode Server_Player::moveCard(CommandContainer *cont, const QString &_startZone, const QList &_cards, int targetPlayerId, const QString &_targetZone, int x, int y, bool faceDown) { + QMutexLocker locker(&game->gameMutex); + Server_CardZone *startzone = getZones().value(_startZone); Server_Player *targetPlayer = game->getPlayers().value(targetPlayerId); if (!targetPlayer) @@ -274,6 +306,8 @@ public: ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *startzone, const QList &_cards, Server_CardZone *targetzone, int x, int y, bool faceDown, bool fixFreeSpaces, bool undoingDraw) { + QMutexLocker locker(&game->gameMutex); + // Disallow controller change to other zones than the table. if (((targetzone->getType() != PublicZone) || !targetzone->hasCoords()) && (startzone->getPlayer() != targetzone->getPlayer())) return RespContextError; @@ -428,6 +462,8 @@ ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *st void Server_Player::unattachCard(CommandContainer *cont, Server_Card *card) { + QMutexLocker locker(&game->gameMutex); + Server_CardZone *zone = card->getZone(); card->setParentCard(0); @@ -441,6 +477,8 @@ void Server_Player::unattachCard(CommandContainer *cont, Server_Card *card) ResponseCode Server_Player::setCardAttrHelper(CommandContainer *cont, const QString &zoneName, int cardId, const QString &attrName, const QString &attrValue) { + QMutexLocker locker(&game->gameMutex); + Server_CardZone *zone = getZones().value(zoneName); if (!zone) return RespNameNotFound; @@ -471,6 +509,8 @@ ResponseCode Server_Player::setCardAttrHelper(CommandContainer *cont, const QStr void Server_Player::sendProtocolItem(ProtocolItem *item, bool deleteItem) { + QMutexLocker locker(&playerMutex); + if (handler) handler->sendProtocolItem(item, deleteItem); } diff --git a/common/server_player.h b/common/server_player.h index 433c90b4a..ccb43d0f0 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "protocol_datastructures.h" class DeckList; @@ -22,6 +23,7 @@ class CommandContainer; class Server_Player : public Server_ArrowTarget { Q_OBJECT private: + mutable QMutex playerMutex; class MoveCardCompareFunctor; Server_Game *game; Server_ProtocolHandler *handler; @@ -42,7 +44,7 @@ public: Server_Player(Server_Game *_game, int _playerId, ServerInfo_User *_userInfo, bool _spectator, Server_ProtocolHandler *_handler); ~Server_Player(); Server_ProtocolHandler *getProtocolHandler() const { return handler; } - void setProtocolHandler(Server_ProtocolHandler *_handler) { handler = _handler; } + void setProtocolHandler(Server_ProtocolHandler *_handler) { playerMutex.lock(); handler = _handler; playerMutex.unlock(); } void setPlayerId(int _id) { playerId = _id; } int getInitialCards() const { return initialCards; } @@ -57,6 +59,7 @@ public: ServerInfo_User *getUserInfo() const { return userInfo; } void setDeck(DeckList *_deck, int _deckId); DeckList *getDeck() const { return deck; } + Server_Game *getGame() const { return game; } const QMap &getZones() const { return zones; } const QMap &getCounters() const { return counters; } const QMap &getArrows() const { return arrows; } diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index c5948bf5d..69014487f 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -68,6 +68,8 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm if (!room) return RespNameNotFound; + QMutexLocker locker(&room->roomMutex); + switch (command->getItemId()) { case ItemId_Command_LeaveRoom: return cmdLeaveRoom(static_cast(command), cont, room); case ItemId_Command_RoomSay: return cmdRoomSay(static_cast(command), cont, room); @@ -90,6 +92,8 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm Server_Game *game = gamePair.first; Server_Player *player = gamePair.second; + QMutexLocker locker(&game->gameMutex); + switch (command->getItemId()) { case ItemId_Command_DeckSelect: return cmdDeckSelect(static_cast(command), cont, game, player); case ItemId_Command_SetSideboardPlan: return cmdSetSideboardPlan(static_cast(command), cont, game, player); diff --git a/common/server_room.cpp b/common/server_room.cpp index a80856923..f9c9b5a0f 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -4,7 +4,7 @@ #include Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) - : QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes) + : QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), roomMutex(QMutex::Recursive) { connect(this, SIGNAL(sigCreateGame(const QString &, const QString &, int, const QList &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *)), this, SLOT(doCreateGame(const QString &, const QString &, int, const QList &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *))); } @@ -16,6 +16,8 @@ Server *Server_Room::getServer() const ServerInfo_Room *Server_Room::getInfo(bool complete) const { + QMutexLocker locker(&roomMutex); + QList gameList; QList userList; QList gameTypeList; @@ -36,6 +38,8 @@ ServerInfo_Room *Server_Room::getInfo(bool complete) const void Server_Room::addClient(Server_ProtocolHandler *client) { + QMutexLocker locker(&roomMutex); + sendRoomEvent(new Event_JoinRoom(id, new ServerInfo_User(client->getUserInfo(), false))); append(client); emit roomInfoChanged(); @@ -43,6 +47,8 @@ void Server_Room::addClient(Server_ProtocolHandler *client) void Server_Room::removeClient(Server_ProtocolHandler *client) { + QMutexLocker locker(&roomMutex); + removeAt(indexOf(client)); sendRoomEvent(new Event_LeaveRoom(id, client->getUserInfo()->getName())); emit roomInfoChanged(); @@ -55,6 +61,8 @@ void Server_Room::say(Server_ProtocolHandler *client, const QString &s) void Server_Room::sendRoomEvent(RoomEvent *event) { + QMutexLocker locker(&roomMutex); + for (int i = 0; i < size(); ++i) at(i)->sendProtocolItem(event, false); delete event; @@ -62,6 +70,8 @@ void Server_Room::sendRoomEvent(RoomEvent *event) void Server_Room::broadcastGameListUpdate(Server_Game *game) { + QMutexLocker locker(&roomMutex); + Event_ListGames *event = new Event_ListGames(id, QList() << game->getInfo()); for (int i = 0; i < size(); i++) @@ -71,6 +81,8 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game) void Server_Room::doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) { + QMutexLocker locker(&roomMutex); + Server_Game *newGame = new Server_Game(creator, static_cast(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); games.insert(newGame->getGameId(), newGame); connect(newGame, SIGNAL(gameClosing()), this, SLOT(removeGame())); @@ -89,6 +101,8 @@ void Server_Room::createGame(const QString &description, const QString &password void Server_Room::removeGame() { + QMutexLocker locker(&roomMutex); + Server_Game *game = static_cast(sender()); broadcastGameListUpdate(game); games.remove(game->getGameId()); diff --git a/common/server_room.h b/common/server_room.h index 0cd2b8b4e..445234016 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -5,6 +5,7 @@ #include #include #include +#include class Server_ProtocolHandler; class RoomEvent; @@ -33,6 +34,7 @@ private slots: void doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); void removeGame(); public: + mutable QMutex roomMutex; Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent); int getId() const { return id; } QString getName() const { return name; } diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index b06652792..a8f7fed0b 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #ifdef Q_OS_UNIX @@ -34,11 +33,11 @@ void ServerLogger::logMessage(QString message) if (!logFile) return; - static QMutex mutex; - mutex.lock(); + logFileMutex.lock(); QTextStream stream(logFile); stream << QDateTime::currentDateTime().toString() << " " << ((void *) QThread::currentThread()) << " " << message << "\n"; - mutex.unlock(); + stream.flush(); + logFileMutex.unlock(); } void ServerLogger::hupSignalHandler(int /*unused*/) diff --git a/servatrice/src/server_logger.h b/servatrice/src/server_logger.h index c1fb7872e..9ee519a73 100644 --- a/servatrice/src/server_logger.h +++ b/servatrice/src/server_logger.h @@ -2,6 +2,7 @@ #define SERVER_LOGGER_H #include +#include class QSocketNotifier; class QFile; @@ -20,6 +21,7 @@ private: static int sigHupFD[2]; QSocketNotifier *snHup; static QFile *logFile; + QMutex logFileMutex; }; #endif From 45890b836b195713c9c27c430498eaafb3e7c058 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 20:45:18 +0100 Subject: [PATCH 07/87] added send buffer to limit socket operations to one thread --- common/server.h | 2 ++ common/server_protocolhandler.cpp | 8 ++++++++ common/server_protocolhandler.h | 4 ++++ servatrice/src/serversocketinterface.cpp | 26 +++++++++++++++++------- servatrice/src/serversocketinterface.h | 7 +++++++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/common/server.h b/common/server.h index 552fd8ea8..324ae8608 100644 --- a/common/server.h +++ b/common/server.h @@ -4,6 +4,7 @@ #include #include #include +#include class Server_Game; class Server_Room; @@ -22,6 +23,7 @@ private slots: void gameClosing(int gameId); void broadcastRoomUpdate(); public: + mutable QMutex serverMutex; Server(QObject *parent = 0); ~Server(); AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 69014487f..6aa78e037 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -17,6 +17,7 @@ Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) : QObject(parent), server(_server), authState(PasswordWrong), acceptsUserListChanges(false), acceptsRoomListChanges(false), userInfo(0), timeRunning(0), lastDataReceived(0) { connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); + connect(this, SIGNAL(sigGameCreated(Server_Game *)), this, SLOT(processSigGameCreated(Server_Game *)), Qt::QueuedConnection); } Server_ProtocolHandler::~Server_ProtocolHandler() @@ -430,6 +431,13 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm void Server_ProtocolHandler::gameCreated(Server_Game *game) { + emit sigGameCreated(game); +} + +void Server_ProtocolHandler::processSigGameCreated(Server_Game *game) +{ + QMutexLocker locker(&game->gameMutex); + Server_Player *creator = game->getPlayers().values().first(); games.insert(game->getGameId(), QPair(game, creator)); diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 075ba0cfb..3234bdb3b 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -91,7 +91,11 @@ private: ResponseCode processCommandHelper(Command *command, CommandContainer *cont); private slots: void pingClockTimeout(); + void processSigGameCreated(Server_Game *game); +signals: + void sigGameCreated(Server_Game *game); public: + mutable QMutex protocolHandlerMutex; Server_ProtocolHandler(Server *_server, QObject *parent = 0); ~Server_ProtocolHandler(); void playerRemovedFromGame(Server_Game *game); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 2a65e8b69..ff91c99cd 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -35,18 +35,18 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent) : Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0) { - xmlWriter = new QXmlStreamWriter; - xmlWriter->setDevice(socket); - + xmlWriter = new QXmlStreamWriter(&xmlBuffer); xmlReader = new QXmlStreamReader; connect(socket, SIGNAL(readyRead()), this, SLOT(readClient())); connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); + connect(this, SIGNAL(xmlBufferChanged()), this, SLOT(flushXmlBuffer()), Qt::QueuedConnection); xmlWriter->writeStartDocument(); xmlWriter->writeStartElement("cockatrice_server_stream"); xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion)); + flushXmlBuffer(); int maxUsers = _server->getMaxUsersPerAddress(); if ((maxUsers > 0) && (_server->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) { @@ -58,6 +58,8 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s ServerSocketInterface::~ServerSocketInterface() { + QMutexLocker locker(&protocolHandlerMutex); + logger->logMessage("ServerSocketInterface destructor"); socket->flush(); @@ -75,8 +77,18 @@ void ServerSocketInterface::processProtocolItem(ProtocolItem *item) processCommandContainer(cont); } +void ServerSocketInterface::flushXmlBuffer() +{ + QMutexLocker locker(&xmlBufferMutex); + socket->write(xmlBuffer.toUtf8()); + socket->flush(); + xmlBuffer.clear(); +} + void ServerSocketInterface::readClient() { + QMutexLocker locker(&protocolHandlerMutex); + QByteArray data = socket->readAll(); logger->logMessage(QString(data)); xmlReader->addData(data); @@ -101,13 +113,13 @@ void ServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socket void ServerSocketInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) { - static QMutex mutex; - mutex.lock(); + QMutexLocker locker(&xmlBufferMutex); + item->write(xmlWriter); - socket->flush(); - mutex.unlock(); if (deleteItem) delete item; + + emit xmlBufferChanged(); } int ServerSocketInterface::getUserIdInDB(const QString &name) const diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index f55dfd128..8f7b937ec 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -22,6 +22,7 @@ #include #include +#include #include "server_protocolhandler.h" class QTcpSocket; @@ -30,6 +31,7 @@ class QXmlStreamReader; class QXmlStreamWriter; class DeckList; class TopLevelProtocolItem; +class QByteArray; class ServerSocketInterface : public Server_ProtocolHandler { @@ -38,11 +40,16 @@ private slots: void readClient(); void catchSocketError(QAbstractSocket::SocketError socketError); void processProtocolItem(ProtocolItem *item); + void flushXmlBuffer(); +signals: + void xmlBufferChanged(); private: + QMutex xmlBufferMutex; Servatrice *servatrice; QTcpSocket *socket; QXmlStreamWriter *xmlWriter; QXmlStreamReader *xmlReader; + QString xmlBuffer; TopLevelProtocolItem *topLevelItem; int getUserIdInDB(const QString &name) const; From 51269f4b91151306202a1414c3117daad8736f65 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 20:57:59 +0100 Subject: [PATCH 08/87] don't flush empty buffers --- servatrice/src/serversocketinterface.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index ff91c99cd..9b2e21607 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -58,11 +58,9 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s ServerSocketInterface::~ServerSocketInterface() { - QMutexLocker locker(&protocolHandlerMutex); - logger->logMessage("ServerSocketInterface destructor"); - socket->flush(); + flushXmlBuffer(); delete xmlWriter; delete xmlReader; delete socket; @@ -80,6 +78,8 @@ void ServerSocketInterface::processProtocolItem(ProtocolItem *item) void ServerSocketInterface::flushXmlBuffer() { QMutexLocker locker(&xmlBufferMutex); + if (xmlBuffer.isEmpty()) + return; socket->write(xmlBuffer.toUtf8()); socket->flush(); xmlBuffer.clear(); From eca941201d8c08904fbe9aac2a2b0e6f21327e85 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 22 Mar 2011 22:46:15 +0100 Subject: [PATCH 09/87] more mutexes --- cockatrice/src/localserverinterface.cpp | 1 + common/server.cpp | 7 +++++++ common/server_protocolhandler.cpp | 4 ---- servatrice/src/servatrice.cpp | 3 +++ servatrice/src/serversocketinterface.cpp | 5 +++++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/cockatrice/src/localserverinterface.cpp b/cockatrice/src/localserverinterface.cpp index b4e0918d6..c4d413792 100644 --- a/cockatrice/src/localserverinterface.cpp +++ b/cockatrice/src/localserverinterface.cpp @@ -9,6 +9,7 @@ LocalServerInterface::LocalServerInterface(LocalServer *_server) LocalServerInterface::~LocalServerInterface() { + server->removeClient(this); } void LocalServerInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) diff --git a/common/server.cpp b/common/server.cpp index ab5ca8b52..b48e8f932 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -38,6 +38,7 @@ Server::~Server() AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString &name, const QString &password) { + QMutexLocker locker(&serverMutex); if (name.size() > 35) name = name.left(35); AuthenticationResult authState = checkUserPassword(name, password); @@ -78,11 +79,13 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString void Server::addClient(Server_ProtocolHandler *client) { + QMutexLocker locker(&serverMutex); clients << client; } void Server::removeClient(Server_ProtocolHandler *client) { + QMutexLocker locker(&serverMutex); clients.removeAt(clients.indexOf(client)); ServerInfo_User *data = client->getUserInfo(); if (data) { @@ -104,6 +107,7 @@ Server_Game *Server::getGame(int gameId) const void Server::broadcastRoomUpdate() { + QMutexLocker locker(&serverMutex); Server_Room *room = static_cast(sender()); QList eventRoomList; eventRoomList.append(new ServerInfo_Room(room->getId(), room->getName(), room->getDescription(), room->getGames().size(), room->size(), room->getAutoJoin())); @@ -117,17 +121,20 @@ void Server::broadcastRoomUpdate() void Server::gameCreated(Server_Game *game) { + QMutexLocker locker(&serverMutex); games.insert(game->getGameId(), game); } void Server::gameClosing(int gameId) { + QMutexLocker locker(&serverMutex); qDebug("Server::gameClosing"); games.remove(gameId); } void Server::addRoom(Server_Room *newRoom) { + QMutexLocker locker(&serverMutex); rooms.insert(newRoom->getId(), newRoom); connect(newRoom, SIGNAL(roomInfoChanged()), this, SLOT(broadcastRoomUpdate())); connect(newRoom, SIGNAL(gameCreated(Server_Game *)), this, SLOT(gameCreated(Server_Game *))); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 6aa78e037..e0351a3ac 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -22,10 +22,6 @@ Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) Server_ProtocolHandler::~Server_ProtocolHandler() { - // The socket has to be removed from the server's list before it is removed from the game's list - // so it will not receive the game update event. - server->removeClient(this); - QMapIterator roomIterator(rooms); while (roomIterator.hasNext()) roomIterator.next().value()->removeClient(this); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 511525c2a..c7bbd7176 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -249,6 +249,7 @@ ServerInfo_User *Servatrice::getUserData(const QString &name) int Servatrice::getUsersWithAddress(const QHostAddress &address) const { + QMutexLocker locker(&serverMutex); int result = 0; for (int i = 0; i < clients.size(); ++i) if (static_cast(clients[i])->getPeerAddress() == address) @@ -304,6 +305,7 @@ QMap Servatrice::getIgnoreList(const QString &name) bool Servatrice::getUserBanned(Server_ProtocolHandler *client, const QString &userName) const { + QMutexLocker locker(&serverMutex); QHostAddress address = static_cast(client)->getPeerAddress(); for (int i = 0; i < addressBanList.size(); ++i) if (address == addressBanList[i].first) @@ -316,6 +318,7 @@ bool Servatrice::getUserBanned(Server_ProtocolHandler *client, const QString &us void Servatrice::updateBanTimer() { + QMutexLocker locker(&serverMutex); for (int i = 0; i < addressBanList.size(); ) if (--(addressBanList[i].second) <= 0) addressBanList.removeAt(i); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 9b2e21607..d00362655 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -58,12 +58,17 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s ServerSocketInterface::~ServerSocketInterface() { + QMutexLocker locker(&servatrice->serverMutex); logger->logMessage("ServerSocketInterface destructor"); flushXmlBuffer(); delete xmlWriter; delete xmlReader; delete socket; + socket = 0; + + // This call has to stay here so that the mutex is not freed prematurely. + server->removeClient(this); } void ServerSocketInterface::processProtocolItem(ProtocolItem *item) From 6d5b29395c050ce46be347baf1656007d4d51ba0 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 29 Mar 2011 23:54:08 +0200 Subject: [PATCH 10/87] mutex and ghost games fixes --- common/server.cpp | 15 +++------------ common/server.h | 1 - common/server_game.cpp | 5 ++++- common/server_protocolhandler.cpp | 2 ++ 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/common/server.cpp b/common/server.cpp index b48e8f932..d19d2edb0 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -26,7 +26,7 @@ #include Server::Server(QObject *parent) - : QObject(parent), nextGameId(0) + : QObject(parent), serverMutex(QMutex::Recursive), nextGameId(0) { } @@ -46,12 +46,8 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString return authState; if (authState == PasswordRight) { - Server_ProtocolHandler *oldSession = users.value(name); - if (oldSession) { - if (!(oldSession->getUserInfo()->getUserLevel() & ServerInfo_User::IsRegistered)) - return WouldOverwriteOldSession; - delete oldSession; // ~Server_ProtocolHandler() will call Server::removeClient - } + if (users.contains(name)) + return WouldOverwriteOldSession; } else if (authState == UnknownUser) { // Change user name so that no two users have the same names, // don't interfere with registered user names though. @@ -100,11 +96,6 @@ void Server::removeClient(Server_ProtocolHandler *client) qDebug() << "Server::removeClient: " << clients.size() << "clients; " << users.size() << "users left"; } -Server_Game *Server::getGame(int gameId) const -{ - return games.value(gameId); -} - void Server::broadcastRoomUpdate() { QMutexLocker locker(&serverMutex); diff --git a/common/server.h b/common/server.h index 324ae8608..70ef8b024 100644 --- a/common/server.h +++ b/common/server.h @@ -28,7 +28,6 @@ public: ~Server(); AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password); QList getGames() const { return games.values(); } - Server_Game *getGame(int gameId) const; const QMap &getRooms() { return rooms; } int getNextGameId() { return nextGameId++; } diff --git a/common/server_game.cpp b/common/server_game.cpp index 3f0d67bb3..2c1e52b2c 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -64,8 +64,11 @@ void Server_Game::pingClockTimeout() QList pingList; QMapIterator playerIterator(players); bool allPlayersInactive = true; + int playerCount = 0; while (playerIterator.hasNext()) { Server_Player *player = playerIterator.next().value(); + if (!player->getSpectator()) + ++playerCount; int pingTime; if (player->getProtocolHandler()) { pingTime = player->getProtocolHandler()->getLastCommandTime(); @@ -78,7 +81,7 @@ void Server_Game::pingClockTimeout() const int maxTime = static_cast(parent())->getServer()->getMaxGameInactivityTime(); if (allPlayersInactive) { - if ((++inactivityCounter >= maxTime) && (maxTime > 0)) + if (((++inactivityCounter >= maxTime) && (maxTime > 0)) || (playerCount < maxPlayers)) deleteLater(); } else inactivityCounter = 0; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index e0351a3ac..e7a430bcb 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -263,8 +263,10 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain ignoreList = server->getIgnoreList(userInfo->getName()); // This might not scale very well. Use an extra QMap if it becomes a problem. + QMutexLocker serverLocker(&server->serverMutex); const QList &serverGames = server->getGames(); for (int i = 0; i < serverGames.size(); ++i) { + QMutexLocker gameLocker(&serverGames[i]->gameMutex); const QList &gamePlayers = serverGames[i]->getPlayers().values(); for (int j = 0; j < gamePlayers.size(); ++j) if (gamePlayers[j]->getUserInfo()->getName() == userInfo->getName()) { From 1fca2e5d5d0213b4944aedaf31323f383ff62b31 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 30 Mar 2011 00:32:39 +0200 Subject: [PATCH 11/87] minor sql changes --- servatrice/servatrice.sql | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index 44298d85e..637d9a6bf 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -28,11 +28,12 @@ SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; CREATE TABLE IF NOT EXISTS `cockatrice_decklist_files` ( `id` int(7) unsigned zerofill NOT NULL auto_increment, `id_folder` int(7) unsigned zerofill NOT NULL, - `user` varchar(30) NOT NULL, + `user` varchar(35) NOT NULL, `name` varchar(50) NOT NULL, `upload_time` datetime NOT NULL, `content` text NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `FolderPlusUser` (`id_folder`,`user`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=550 ; -- -------------------------------------------------------- @@ -44,10 +45,10 @@ CREATE TABLE IF NOT EXISTS `cockatrice_decklist_files` ( CREATE TABLE IF NOT EXISTS `cockatrice_decklist_folders` ( `id` int(7) unsigned zerofill NOT NULL auto_increment, `id_parent` int(7) unsigned zerofill NOT NULL, - `user` varchar(30) NOT NULL, + `user` varchar(35) NOT NULL, `name` varchar(30) NOT NULL, PRIMARY KEY (`id`), - KEY `id_parent` (`id_parent`,`name`) + KEY `ParentPlusUser` (`id_parent`,`user`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=80 ; -- -------------------------------------------------------- @@ -73,7 +74,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_games` ( CREATE TABLE IF NOT EXISTS `cockatrice_games_players` ( `id_game` int(7) unsigned zerofill NOT NULL, - `player` varchar(30) default NULL, + `player` varchar(35) default NULL, KEY `id_game` (`id_game`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; @@ -101,7 +102,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_news` ( CREATE TABLE IF NOT EXISTS `cockatrice_users` ( `id` int(7) unsigned zerofill NOT NULL auto_increment, `admin` tinyint(1) NOT NULL, - `name` varchar(255) NOT NULL, + `name` varchar(35) NOT NULL, `realname` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, @@ -132,12 +133,16 @@ CREATE TABLE `cockatrice_servermessages` ( CREATE TABLE `cockatrice_ignorelist` ( `id_user1` int(7) unsigned NOT NULL, `id_user2` int(7) unsigned NOT NULL, - UNIQUE KEY `key` (`id_user1`, `id_user2`) + UNIQUE KEY `key` (`id_user1`, `id_user2`), + KEY `id_user1` (`id_user1`), + KEY `id_user2` (`id_user2`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE `cockatrice_buddylist` ( `id_user1` int(7) unsigned NOT NULL, `id_user2` int(7) unsigned NOT NULL, - UNIQUE KEY `key` (`id_user1`, `id_user2`) + UNIQUE KEY `key` (`id_user1`, `id_user2`), + KEY `id_user1` (`id_user1`), + KEY `id_user2` (`id_user2`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; From 6504a889e106d58eaccd1a9be9eebd90d29d9655 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 6 Apr 2011 14:46:54 +0200 Subject: [PATCH 12/87] threaded logging; sigsegv handler to flush logfile before crashing --- servatrice/src/main.cpp | 22 +++++++++- servatrice/src/server_logger.cpp | 70 ++++++++++++++++++++++++++++---- servatrice/src/server_logger.h | 25 +++++++++++- 3 files changed, 106 insertions(+), 11 deletions(-) diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index 9c4c25e5f..e3eee8929 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -32,6 +32,7 @@ RNG_Abstract *rng; ServerLogger *logger; +ServerLoggerThread *loggerThread; void testRNG() { @@ -72,6 +73,14 @@ void myMessageOutput(QtMsgType /*type*/, const char *msg) logger->logMessage(msg); } +void sigSegvHandler(int sig) +{ + logger->logMessage("SIGSEGV"); + usleep(1000); + delete loggerThread; + raise(sig); +} + int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); @@ -86,7 +95,12 @@ int main(int argc, char *argv[]) QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat); - logger = new ServerLogger(settings->value("server/logfile").toString()); + + loggerThread = new ServerLoggerThread(settings->value("server/logfile").toString()); + loggerThread->start(); + loggerThread->waitForInit(); + logger = loggerThread->getLogger(); + qInstallMsgHandler(myMessageOutput); #ifdef Q_OS_UNIX struct sigaction hup; @@ -95,6 +109,12 @@ int main(int argc, char *argv[]) hup.sa_flags = 0; hup.sa_flags |= SA_RESTART; sigaction(SIGHUP, &hup, 0); + + struct sigaction segv; + segv.sa_handler = sigSegvHandler; + segv.sa_flags = SA_RESETHAND; + sigemptyset(&segv.sa_mask); + sigaction(SIGSEGV, &segv, 0); #endif rng = new RNG_SFMT; diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index a8f7fed0b..07ba42787 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -3,17 +3,14 @@ #include #include #include -#include -#ifdef Q_OS_UNIX #include #include -#endif ServerLogger::ServerLogger(const QString &logFileName, QObject *parent) - : QObject(parent) + : QObject(parent), flushRunning(false) { if (!logFileName.isEmpty()) { - logFile = new QFile(logFileName, this); + logFile = new QFile("server.log", this); logFile->open(QIODevice::Append); #ifdef Q_OS_UNIX ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); @@ -22,6 +19,8 @@ ServerLogger::ServerLogger(const QString &logFileName, QObject *parent) connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup())); } else logFile = 0; + + connect(this, SIGNAL(sigFlushBuffer()), this, SLOT(flushBuffer()), Qt::QueuedConnection); } ServerLogger::~ServerLogger() @@ -33,11 +32,33 @@ void ServerLogger::logMessage(QString message) if (!logFile) return; - logFileMutex.lock(); + bufferMutex.lock(); + buffer.append(QDateTime::currentDateTime().toString() + " " + QString::number((qulonglong) QThread::currentThread(), 16) + " " + message); + bufferMutex.unlock(); + + emit sigFlushBuffer(); +} + +void ServerLogger::flushBuffer() +{ + if (flushRunning) + return; + + flushRunning = true; QTextStream stream(logFile); - stream << QDateTime::currentDateTime().toString() << " " << ((void *) QThread::currentThread()) << " " << message << "\n"; - stream.flush(); - logFileMutex.unlock(); + forever { + bufferMutex.lock(); + if (buffer.isEmpty()) { + bufferMutex.unlock(); + flushRunning = false; + return; + } + QString message = buffer.takeFirst(); + bufferMutex.unlock(); + + stream << message << "\n"; + stream.flush(); + } } void ServerLogger::hupSignalHandler(int /*unused*/) @@ -66,3 +87,34 @@ void ServerLogger::handleSigHup() QFile *ServerLogger::logFile; int ServerLogger::sigHupFD[2]; + +ServerLoggerThread::ServerLoggerThread(const QString &_fileName, QObject *parent) + : QThread(parent), fileName(_fileName) +{ +} + +ServerLoggerThread::~ServerLoggerThread() +{ + quit(); + wait(); +} + +void ServerLoggerThread::run() +{ + logger = new ServerLogger(fileName); + + usleep(100); + initWaitCondition.wakeAll(); + + exec(); + + delete logger; +} + +void ServerLoggerThread::waitForInit() +{ + QMutex mutex; + mutex.lock(); + initWaitCondition.wait(&mutex); + mutex.unlock(); +} diff --git a/servatrice/src/server_logger.h b/servatrice/src/server_logger.h index 9ee519a73..3d3d46834 100644 --- a/servatrice/src/server_logger.h +++ b/servatrice/src/server_logger.h @@ -2,7 +2,10 @@ #define SERVER_LOGGER_H #include +#include #include +#include +#include class QSocketNotifier; class QFile; @@ -17,11 +20,31 @@ public slots: void logMessage(QString message); private slots: void handleSigHup(); + void flushBuffer(); +signals: + void sigFlushBuffer(); private: static int sigHupFD[2]; QSocketNotifier *snHup; static QFile *logFile; - QMutex logFileMutex; + bool flushRunning; + QStringList buffer; + QMutex bufferMutex; +}; + +class ServerLoggerThread : public QThread { + Q_OBJECT +private: + QString fileName; + ServerLogger *logger; + QWaitCondition initWaitCondition; +protected: + void run(); +public: + ServerLoggerThread(const QString &_fileName, QObject *parent = 0); + ~ServerLoggerThread(); + ServerLogger *getLogger() const { return logger; } + void waitForInit(); }; #endif From 0b22f73095aa44676698be3a608208f009d13828 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 6 Apr 2011 15:03:21 +0200 Subject: [PATCH 13/87] added ukraine to countries --- cockatrice/cockatrice.qrc | 1 + cockatrice/resources/countries/ua.svg | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 cockatrice/resources/countries/ua.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index a71ed41e6..a36e8e317 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -73,6 +73,7 @@ resources/countries/ru.svg resources/countries/se.svg resources/countries/tr.svg + resources/countries/ua.svg resources/countries/uk.svg resources/countries/us.svg diff --git a/cockatrice/resources/countries/ua.svg b/cockatrice/resources/countries/ua.svg new file mode 100644 index 000000000..8f4b0a436 --- /dev/null +++ b/cockatrice/resources/countries/ua.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 5f46b5cd41ac87d5d5148c98bea70af1ea95b116 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 6 Apr 2011 15:49:03 +0200 Subject: [PATCH 14/87] game tab: added splitter for manual size control of text boxes --- cockatrice/src/cardinfowidget.cpp | 43 +++---------------------------- cockatrice/src/cardinfowidget.h | 3 --- cockatrice/src/settingscache.cpp | 8 +++--- cockatrice/src/settingscache.h | 6 ++--- cockatrice/src/tab_game.cpp | 35 ++++++++++++++++--------- cockatrice/src/tab_game.h | 2 ++ 6 files changed, 36 insertions(+), 61 deletions(-) diff --git a/cockatrice/src/cardinfowidget.cpp b/cockatrice/src/cardinfowidget.cpp index 3e7268bf3..cd51f2350 100644 --- a/cockatrice/src/cardinfowidget.cpp +++ b/cockatrice/src/cardinfowidget.cpp @@ -11,13 +11,8 @@ #include "settingscache.h" CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlags flags) - : QFrame(parent, flags), pixmapWidth(160), aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH), minimized(false), mode(_mode), minimizeButton(0), info(0) + : QFrame(parent, flags), pixmapWidth(160), aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH), minimized(false), mode(_mode), info(0) { - if (mode == ModeGameTab) { - minimizeButton = new QPushButton(QIcon(style()->standardIcon(QStyle::SP_ArrowUp)), QString()); - connect(minimizeButton, SIGNAL(clicked()), this, SLOT(minimizeClicked())); - } - cardPicture = new QLabel; cardPicture->setAlignment(Qt::AlignCenter); @@ -38,8 +33,6 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlag QGridLayout *grid = new QGridLayout(this); int row = 0; - if (mode == ModeGameTab) - grid->addWidget(minimizeButton, row++, 1, 1, 1, Qt::AlignRight); grid->addWidget(cardPicture, row++, 0, 1, 2); grid->addWidget(nameLabel1, row, 0); grid->addWidget(nameLabel2, row++, 1); @@ -58,43 +51,15 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlag retranslateUi(); setFrameStyle(QFrame::Panel | QFrame::Raised); + setMinimumHeight(350); if (mode == ModeGameTab) { textLabel->setFixedHeight(100); setFixedWidth(sizeHint().width()); - setMinimized(settingsCache->getCardInfoMinimized()); + setMaximumHeight(580); } else if (mode == ModePopUp) setFixedWidth(350); else setFixedWidth(250); - if (mode != ModeDeckEditor) - setFixedHeight(sizeHint().height()); -} - -void CardInfoWidget::minimizeClicked() -{ - setMinimized(!minimized); - settingsCache->setCardInfoMinimized(minimized); -} - -void CardInfoWidget::setMinimized(bool _minimized) -{ - minimized = _minimized; - - cardPicture->setVisible(!minimized); - nameLabel2->setVisible(!minimized); - nameLabel1->setVisible(!minimized); - manacostLabel1->setVisible(!minimized); - manacostLabel2->setVisible(!minimized); - cardtypeLabel1->setVisible(!minimized); - cardtypeLabel2->setVisible(!minimized); - powtoughLabel1->setVisible(!minimized); - powtoughLabel2->setVisible(!minimized); - textLabel->setVisible(!minimized); - - if (minimizeButton) - minimizeButton->setIcon(style()->standardIcon(minimized ? QStyle::SP_ArrowDown : QStyle::SP_ArrowUp)); - - setFixedHeight(sizeHint().height()); } void CardInfoWidget::setCard(CardInfo *card) @@ -147,7 +112,7 @@ void CardInfoWidget::retranslateUi() void CardInfoWidget::resizeEvent(QResizeEvent * /*event*/) { - if (mode == ModeDeckEditor) { + if ((mode == ModeDeckEditor) || (mode == ModeGameTab)) { pixmapWidth = qMin(width() * 0.95, (height() - 200) / aspectRatio); updatePixmap(); } diff --git a/cockatrice/src/cardinfowidget.h b/cockatrice/src/cardinfowidget.h index d140009e4..f71a6c1f5 100644 --- a/cockatrice/src/cardinfowidget.h +++ b/cockatrice/src/cardinfowidget.h @@ -21,7 +21,6 @@ private: bool minimized; ResizeMode mode; - QPushButton *minimizeButton; QLabel *cardPicture; QLabel *nameLabel1, *nameLabel2; QLabel *manacostLabel1, *manacostLabel2; @@ -30,7 +29,6 @@ private: QTextEdit *textLabel; CardInfo *info; - void setMinimized(bool _minimized); public: CardInfoWidget(ResizeMode _mode, QWidget *parent = 0, Qt::WindowFlags f = 0); void retranslateUi(); @@ -41,7 +39,6 @@ public slots: private slots: void clear(); void updatePixmap(); - void minimizeClicked(); signals: void mouseReleased(); protected: diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index de7cb7bf7..4d621a8a9 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -19,7 +19,7 @@ SettingsCache::SettingsCache() picDownload = settings->value("personal/picturedownload", true).toBool(); doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool(); - cardInfoMinimized = settings->value("interface/cardinfominimized", false).toBool(); + tabGameSplitterSizes = settings->value("interface/tabgame_splittersizes").toByteArray(); displayCardNames = settings->value("cards/displaycardnames", true).toBool(); horizontalHand = settings->value("hand/horizontal", true).toBool(); invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool(); @@ -104,10 +104,10 @@ void SettingsCache::setDoubleClickToPlay(int _doubleClickToPlay) settings->setValue("interface/doubleclicktoplay", doubleClickToPlay); } -void SettingsCache::setCardInfoMinimized(bool _cardInfoMinimized) +void SettingsCache::setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes) { - cardInfoMinimized = _cardInfoMinimized; - settings->setValue("interface/cardinfominimized", cardInfoMinimized); + tabGameSplitterSizes = _tabGameSplitterSizes; + settings->setValue("interface/tabgame_splittersizes", tabGameSplitterSizes); } void SettingsCache::setDisplayCardNames(int _displayCardNames) diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 607d572d9..8960dc569 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -28,7 +28,7 @@ private: QString handBgPath, stackBgPath, tableBgPath, playerBgPath, cardBackPicturePath; bool picDownload; bool doubleClickToPlay; - bool cardInfoMinimized; + QByteArray tabGameSplitterSizes; bool displayCardNames; bool horizontalHand; bool invertVerticalCoordinate; @@ -47,7 +47,7 @@ public: QString getCardBackPicturePath() const { return cardBackPicturePath; } bool getPicDownload() const { return picDownload; } bool getDoubleClickToPlay() const { return doubleClickToPlay; } - bool getCardInfoMinimized() const { return cardInfoMinimized; } + QByteArray getTabGameSplitterSizes() const { return tabGameSplitterSizes; } bool getDisplayCardNames() const { return displayCardNames; } bool getHorizontalHand() const { return horizontalHand; } bool getInvertVerticalCoordinate() const { return invertVerticalCoordinate; } @@ -66,7 +66,7 @@ public slots: void setCardBackPicturePath(const QString &_cardBackPicturePath); void setPicDownload(int _picDownload); void setDoubleClickToPlay(int _doubleClickToPlay); - void setCardInfoMinimized(bool _cardInfoMinimized); + void setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes); void setDisplayCardNames(int _displayCardNames); void setHorizontalHand(int _horizontalHand); void setInvertVerticalCoordinate(int _invertVerticalCoordinate); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index fa608c29d..a90281ad5 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -191,17 +192,23 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client deckViewContainerLayout = new QVBoxLayout; - QVBoxLayout *verticalLayout = new QVBoxLayout; - verticalLayout->addWidget(cardInfo); - verticalLayout->addWidget(playerListWidget, 1); - verticalLayout->addWidget(timeElapsedLabel); - verticalLayout->addWidget(messageLog, 5); - verticalLayout->addLayout(hLayout); + QVBoxLayout *messageLogLayout = new QVBoxLayout; + messageLogLayout->addWidget(timeElapsedLabel); + messageLogLayout->addWidget(messageLog); + messageLogLayout->addLayout(hLayout); + + QWidget *messageLogLayoutWidget = new QWidget; + messageLogLayoutWidget->setLayout(messageLogLayout); + + splitter = new QSplitter(Qt::Vertical); + splitter->addWidget(cardInfo); + splitter->addWidget(playerListWidget); + splitter->addWidget(messageLogLayoutWidget); mainLayout = new QHBoxLayout; mainLayout->addWidget(gameView, 10); mainLayout->addLayout(deckViewContainerLayout, 10); - mainLayout->addLayout(verticalLayout); + mainLayout->addWidget(splitter); if (spectator && !spectatorsCanTalk) { sayLabel->hide(); @@ -253,12 +260,16 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client retranslateUi(); setLayout(mainLayout); + + splitter->restoreState(settingsCache->getTabGameSplitterSizes()); messageLog->logGameJoined(gameId); } TabGame::~TabGame() { + settingsCache->setTabGameSplitterSizes(splitter->saveState()); + QMapIterator i(players); while (i.hasNext()) delete i.next().value(); @@ -767,12 +778,12 @@ void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName) infoPopup = new CardInfoWidget(CardInfoWidget::ModePopUp, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint); connect(infoPopup, SIGNAL(mouseReleased()), this, SLOT(deleteCardInfoPopup())); infoPopup->setCard(cardName); - QRect screenRect = qApp->desktop()->screenGeometry(this); - infoPopup->move( - qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())), - qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height())) - ); + QRect screenRect = qApp->desktop()->screenGeometry(this); infoPopup->show(); + infoPopup->move( + qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())), + qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height())) + ); infoPopup->grabMouse(); } diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index b11f857c0..4bf30af73 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -12,6 +12,7 @@ class DeckView; class GameScene; class CardInfoWidget; class MessageLogWidget; +class QSplitter; class QLabel; class QLineEdit; class QPushButton; @@ -98,6 +99,7 @@ private: int currentPhase; int activePlayer; + QSplitter *splitter; CardInfoWidget *infoPopup; CardInfoWidget *cardInfo; PlayerListWidget *playerListWidget; From 091a2ed6b2907c7231b7d036aa815678d06bd1a6 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 6 Apr 2011 17:37:33 +0200 Subject: [PATCH 15/87] server version bump; hashed password transmission; updated servatrice.sql --- cockatrice/src/remoteclient.cpp | 3 ++- servatrice/servatrice.sql | 1 + servatrice/src/servatrice.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cockatrice/src/remoteclient.cpp b/cockatrice/src/remoteclient.cpp index 2bb43b999..fac63019a 100644 --- a/cockatrice/src/remoteclient.cpp +++ b/cockatrice/src/remoteclient.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "remoteclient.h" #include "protocol.h" #include "protocol_items.h" @@ -87,7 +88,7 @@ void RemoteClient::readData() connect(topLevelItem, SIGNAL(protocolItemReceived(ProtocolItem *)), this, SLOT(processProtocolItem(ProtocolItem *))); setStatus(StatusLoggingIn); - Command_Login *cmdLogin = new Command_Login(userName, password); + Command_Login *cmdLogin = new Command_Login(userName, QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1).toBase64()); connect(cmdLogin, SIGNAL(finished(ProtocolResponse *)), this, SLOT(loginResponse(ProtocolResponse *))); sendCommand(cmdLogin); } diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index 637d9a6bf..f35b1d9f8 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -117,6 +117,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_users` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=915 ; CREATE TABLE `cockatrice_uptime` ( + `id_server` tinyint(3) NOT NULL, `timest` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `uptime` int(11) DEFAULT NULL, `users_count` int(11) DEFAULT NULL, diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index c7bbd7176..62992bf66 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -366,4 +366,4 @@ void Servatrice::statusUpdate() execSqlQuery(query); } -const QString Servatrice::versionString = "Servatrice 0.20110303"; +const QString Servatrice::versionString = "Servatrice 0.20110406"; From 7ae0e31964f646f24d1c9f4e5a920cccd7443bfb Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 13 Apr 2011 03:08:44 +0200 Subject: [PATCH 16/87] race condition fixed --- servatrice/src/main.cpp | 1 - servatrice/src/servatrice.cpp | 7 ------- servatrice/src/servatrice.h | 3 --- servatrice/src/server_logger.cpp | 1 + servatrice/src/serversocketinterface.cpp | 2 ++ servatrice/src/serversocketthread.cpp | 2 -- servatrice/src/serversocketthread.h | 2 -- 7 files changed, 3 insertions(+), 15 deletions(-) diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index e3eee8929..5feffe0ad 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -76,7 +76,6 @@ void myMessageOutput(QtMsgType /*type*/, const char *msg) void sigSegvHandler(int sig) { logger->logMessage("SIGSEGV"); - usleep(1000); delete loggerThread; raise(sig); } diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 62992bf66..94ab833a6 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -30,7 +30,6 @@ void Servatrice_TcpServer::incomingConnection(int socketDescriptor) { ServerSocketThread *sst = new ServerSocketThread(socketDescriptor, server, this); - connect(sst, SIGNAL(clientAdded(ServerSocketInterface *)), this, SIGNAL(clientAdded(ServerSocketInterface *))); sst->start(); } @@ -57,7 +56,6 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) } tcpServer = new Servatrice_TcpServer(this); - connect(tcpServer, SIGNAL(clientAdded(ServerSocketInterface *)), this, SLOT(newConnection(ServerSocketInterface *))); int port = settings->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << port; tcpServer->listen(QHostAddress::Any, port); @@ -154,11 +152,6 @@ bool Servatrice::execSqlQuery(QSqlQuery &query) return false; } -void Servatrice::newConnection(ServerSocketInterface *client) -{ - addClient(client); -} - AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QString &password) { QMutexLocker locker(&dbMutex); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index c4be3ec71..0296a9033 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -41,15 +41,12 @@ public: : QTcpServer(parent), server(_server) { } protected: void incomingConnection(int socketDescriptor); -signals: - void clientAdded(ServerSocketInterface *client); }; class Servatrice : public Server { Q_OBJECT private slots: - void newConnection(ServerSocketInterface *client); void statusUpdate(); void updateBanTimer(); public: diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index 07ba42787..0b59c46ab 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -25,6 +25,7 @@ ServerLogger::ServerLogger(const QString &logFileName, QObject *parent) ServerLogger::~ServerLogger() { + flushBuffer(); } void ServerLogger::logMessage(QString message) diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index d00362655..5aedb7db3 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -54,6 +54,8 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s deleteLater(); } else sendProtocolItem(new Event_ServerMessage(Servatrice::versionString)); + + server->addClient(this); } ServerSocketInterface::~ServerSocketInterface() diff --git a/servatrice/src/serversocketthread.cpp b/servatrice/src/serversocketthread.cpp index 4bb7129ae..9c08ce1b9 100644 --- a/servatrice/src/serversocketthread.cpp +++ b/servatrice/src/serversocketthread.cpp @@ -23,7 +23,5 @@ void ServerSocketThread::run() ssi = new ServerSocketInterface(server, socket); connect(ssi, SIGNAL(destroyed()), this, SLOT(deleteLater())); - emit clientAdded(ssi); - exec(); } diff --git a/servatrice/src/serversocketthread.h b/servatrice/src/serversocketthread.h index 867756b5b..2aa6dc8bd 100644 --- a/servatrice/src/serversocketthread.h +++ b/servatrice/src/serversocketthread.h @@ -17,8 +17,6 @@ public: ~ServerSocketThread(); protected: void run(); -signals: - void clientAdded(ServerSocketInterface *client); }; #endif From 2d8b12a5761f8d86d605ad7cd9cca3a5536f3a5b Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 17 Apr 2011 15:46:47 +0200 Subject: [PATCH 17/87] reduced game selector minimum height; server race conditions fixed --- cockatrice/src/localserverinterface.cpp | 2 +- cockatrice/src/tab_room.cpp | 2 +- common/server_game.cpp | 16 ++++++------ common/server_game.h | 1 + common/server_protocolhandler.cpp | 32 +++++++++++++----------- common/server_protocolhandler.h | 7 ++---- common/server_room.cpp | 15 ++++++----- common/server_room.h | 5 +--- servatrice/src/serversocketinterface.cpp | 5 +--- 9 files changed, 40 insertions(+), 45 deletions(-) diff --git a/cockatrice/src/localserverinterface.cpp b/cockatrice/src/localserverinterface.cpp index c4d413792..79734c40c 100644 --- a/cockatrice/src/localserverinterface.cpp +++ b/cockatrice/src/localserverinterface.cpp @@ -9,7 +9,7 @@ LocalServerInterface::LocalServerInterface(LocalServer *_server) LocalServerInterface::~LocalServerInterface() { - server->removeClient(this); + prepareDestroy(); } void LocalServerInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index 4e7770aea..efdc0e8af 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -49,7 +49,7 @@ GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, QWidget *par setLayout(mainLayout); setMinimumWidth((qreal) (gameListView->columnWidth(0) * gameListModel->columnCount()) / 1.5); - setMinimumHeight(400); + setMinimumHeight(200); connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int))); connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); diff --git a/common/server_game.cpp b/common/server_game.cpp index 2c1e52b2c..cf65553e2 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -28,12 +28,12 @@ #include #include -Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent) - : QObject(parent), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0), gameMutex(QMutex::Recursive) +Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room) + : QObject(), room(_room), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0), gameMutex(QMutex::Recursive) { addPlayer(_creator, false, false); - if (parent->getServer()->getGameShouldPing()) { + if (room->getServer()->getGameShouldPing()) { pingClock = new QTimer(this); connect(pingClock, SIGNAL(timeout()), this, SLOT(pingClockTimeout())); pingClock->start(1000); @@ -79,7 +79,7 @@ void Server_Game::pingClockTimeout() } sendGameEvent(new Event_Ping(secondsElapsed, pingList)); - const int maxTime = static_cast(parent())->getServer()->getMaxGameInactivityTime(); + const int maxTime = room->getServer()->getMaxGameInactivityTime(); if (allPlayersInactive) { if (((++inactivityCounter >= maxTime) && (maxTime > 0)) || (playerCount < maxPlayers)) deleteLater(); @@ -193,9 +193,9 @@ ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_passw if (!(user->getUserLevel() & ServerInfo_User::IsRegistered) && onlyRegistered) return RespUserLevelTooLow; if (onlyBuddies) - if (!static_cast(parent())->getServer()->getBuddyList(creatorInfo->getName()).contains(user->getName())) + if (!room->getServer()->getBuddyList(creatorInfo->getName()).contains(user->getName())) return RespOnlyBuddies; - if (static_cast(parent())->getServer()->getIgnoreList(creatorInfo->getName()).contains(user->getName())) + if (room->getServer()->getIgnoreList(creatorInfo->getName()).contains(user->getName())) return RespInIgnoreList; if (spectator) { if (!spectatorsAllowed) @@ -218,7 +218,7 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec players.insert(playerId, newPlayer); if (broadcastUpdate) - qobject_cast(parent())->broadcastGameListUpdate(this); + room->broadcastGameListUpdate(this); return newPlayer; } @@ -242,7 +242,7 @@ void Server_Game::removePlayer(Server_Player *player) if (gameStarted && playerActive) nextTurn(); } - qobject_cast(parent())->broadcastGameListUpdate(this); + room->broadcastGameListUpdate(this); } void Server_Game::removeArrowsToPlayer(Server_Player *player) diff --git a/common/server_game.h b/common/server_game.h index 2ce9b89eb..15e85968f 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -34,6 +34,7 @@ class ServerInfo_User; class Server_Game : public QObject { Q_OBJECT private: + Server_Room *room; ServerInfo_User *creatorInfo; QMap players; bool gameStarted; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 167bab6f1..ab81a2c24 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -17,11 +17,20 @@ Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) : QObject(parent), server(_server), authState(PasswordWrong), acceptsUserListChanges(false), acceptsRoomListChanges(false), userInfo(0), timeRunning(0), lastDataReceived(0) { connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); - connect(this, SIGNAL(sigGameCreated(Server_Game *)), this, SLOT(processSigGameCreated(Server_Game *)), Qt::QueuedConnection); } Server_ProtocolHandler::~Server_ProtocolHandler() { +} + +// This is essentially the destructor, but it needs to be called from the +// child's destructor with the server mutex locked. Otherwise, the mutex +// could get unlocked while the object is not finished being destroyed, +// leading to calls to pure virtual functions. +void Server_ProtocolHandler::prepareDestroy() +{ + server->removeClient(this); + QMapIterator roomIterator(rooms); while (roomIterator.hasNext()) roomIterator.next().value()->removeClient(this); @@ -423,24 +432,17 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm for (int i = 0; i < gameTypeList.size(); ++i) gameTypes.append(gameTypeList[i]->getData()); - room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); - return RespOk; -} - -void Server_ProtocolHandler::gameCreated(Server_Game *game) -{ - emit sigGameCreated(game); -} - -void Server_ProtocolHandler::processSigGameCreated(Server_Game *game) -{ - QMutexLocker locker(&game->gameMutex); + Server_Game *game = room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); Server_Player *creator = game->getPlayers().values().first(); games.insert(game->getGameId(), QPair(game, creator)); sendProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); sendProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(creator)), game->getGameId())); + + game->gameMutex.unlock(); + + return RespOk; } ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandContainer * /*cont*/, Server_Room *room) @@ -454,7 +456,9 @@ ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandC Server_Game *g = room->getGames().value(cmd->getGameId()); if (!g) return RespNameNotFound; - + + QMutexLocker locker(&g->gameMutex); + ResponseCode result = g->checkJoin(userInfo, cmd->getPassword(), cmd->getSpectator()); if (result == RespOk) { Server_Player *player = g->addPlayer(this, cmd->getSpectator()); diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 3234bdb3b..8e671ce5d 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -28,6 +28,8 @@ protected: bool acceptsRoomListChanges; ServerInfo_User *userInfo; QMap buddyList, ignoreList; + + void prepareDestroy(); private: QList itemQueue; QList messageSizeOverTime, messageCountOverTime; @@ -91,11 +93,7 @@ private: ResponseCode processCommandHelper(Command *command, CommandContainer *cont); private slots: void pingClockTimeout(); - void processSigGameCreated(Server_Game *game); -signals: - void sigGameCreated(Server_Game *game); public: - mutable QMutex protocolHandlerMutex; Server_ProtocolHandler(Server *_server, QObject *parent = 0); ~Server_ProtocolHandler(); void playerRemovedFromGame(Server_Game *game); @@ -107,7 +105,6 @@ public: const QMap &getBuddyList() const { return buddyList; } const QMap &getIgnoreList() const { return ignoreList; } - void gameCreated(Server_Game *game); int getLastCommandTime() const { return timeRunning - lastDataReceived; } void processCommandContainer(CommandContainer *cont); virtual void sendProtocolItem(ProtocolItem *item, bool deleteItem = true) = 0; diff --git a/common/server_room.cpp b/common/server_room.cpp index f9c9b5a0f..329534274 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -6,7 +6,6 @@ Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) : QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), roomMutex(QMutex::Recursive) { - connect(this, SIGNAL(sigCreateGame(const QString &, const QString &, int, const QList &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *)), this, SLOT(doCreateGame(const QString &, const QString &, int, const QList &, bool, bool, bool, bool, bool, bool, Server_ProtocolHandler *))); } Server *Server_Room::getServer() const @@ -79,24 +78,24 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game) delete event; } -void Server_Room::doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) +Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) { QMutexLocker locker(&roomMutex); Server_Game *newGame = new Server_Game(creator, static_cast(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); + newGame->moveToThread(thread()); + newGame->setParent(this); + // This mutex needs to be unlocked by the caller. + newGame->gameMutex.lock(); games.insert(newGame->getGameId(), newGame); connect(newGame, SIGNAL(gameClosing()), this, SLOT(removeGame())); broadcastGameListUpdate(newGame); - creator->gameCreated(newGame); emit gameCreated(newGame); emit roomInfoChanged(); -} - -void Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) -{ - emit sigCreateGame(description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, creator); + + return newGame; } void Server_Room::removeGame() diff --git a/common/server_room.h b/common/server_room.h index 445234016..10f6c255b 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -20,8 +20,6 @@ signals: void roomInfoChanged(); void gameCreated(Server_Game *game); void gameClosing(int gameId); - - void sigCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); private: int id; QString name; @@ -31,7 +29,6 @@ private: QStringList gameTypes; QMap games; private slots: - void doCreateGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); void removeGame(); public: mutable QMutex roomMutex; @@ -49,7 +46,7 @@ public: void removeClient(Server_ProtocolHandler *client); void say(Server_ProtocolHandler *client, const QString &s); void broadcastGameListUpdate(Server_Game *game); - void createGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); + Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); void sendRoomEvent(RoomEvent *event); }; diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 5aedb7db3..835e9a111 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -69,8 +69,7 @@ ServerSocketInterface::~ServerSocketInterface() delete socket; socket = 0; - // This call has to stay here so that the mutex is not freed prematurely. - server->removeClient(this); + prepareDestroy(); } void ServerSocketInterface::processProtocolItem(ProtocolItem *item) @@ -94,8 +93,6 @@ void ServerSocketInterface::flushXmlBuffer() void ServerSocketInterface::readClient() { - QMutexLocker locker(&protocolHandlerMutex); - QByteArray data = socket->readAll(); logger->logMessage(QString(data)); xmlReader->addData(data); From 9933b219a99f7935e301293854ce58781d0ad64e Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 17 Apr 2011 16:31:03 +0200 Subject: [PATCH 18/87] game list mutex in S_PH --- common/server_player.cpp | 1 + common/server_protocolhandler.cpp | 19 ++++++++++++++++--- common/server_protocolhandler.h | 2 ++ servatrice/src/serversocketinterface.cpp | 4 ++-- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/common/server_player.cpp b/common/server_player.cpp index 77c37622f..f71c4cd58 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -18,6 +18,7 @@ Server_Player::Server_Player(Server_Game *_game, int _playerId, ServerInfo_User Server_Player::~Server_Player() { QMutexLocker locker(&game->gameMutex); + QMutexLocker locker2(&playerMutex); delete deck; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index ab81a2c24..05ef513b7 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -14,7 +14,7 @@ #include Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) - : QObject(parent), server(_server), authState(PasswordWrong), acceptsUserListChanges(false), acceptsRoomListChanges(false), userInfo(0), timeRunning(0), lastDataReceived(0) + : QObject(parent), server(_server), authState(PasswordWrong), acceptsUserListChanges(false), acceptsRoomListChanges(false), userInfo(0), timeRunning(0), lastDataReceived(0), gameListMutex(QMutex::Recursive) { connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); } @@ -35,6 +35,7 @@ void Server_ProtocolHandler::prepareDestroy() while (roomIterator.hasNext()) roomIterator.next().value()->removeClient(this); + gameListMutex.lock(); QMapIterator > gameIterator(games); while (gameIterator.hasNext()) { gameIterator.next(); @@ -46,6 +47,7 @@ void Server_ProtocolHandler::prepareDestroy() else p->setProtocolHandler(0); } + gameListMutex.unlock(); delete userInfo; QMapIterator i(buddyList); @@ -59,6 +61,8 @@ void Server_ProtocolHandler::prepareDestroy() void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game) { qDebug() << "Server_ProtocolHandler::playerRemovedFromGame(): gameId =" << game->getGameId(); + + QMutexLocker locker(&gameListMutex); games.remove(game->getGameId()); } @@ -89,7 +93,8 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm qDebug() << "received GameCommand: game =" << gameCommand->getGameId(); if (authState == PasswordWrong) return RespLoginNeeded; - + + gameListMutex.lock(); if (!games.contains(gameCommand->getGameId())) { qDebug() << "invalid game"; return RespNameNotFound; @@ -99,6 +104,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm Server_Player *player = gamePair.second; QMutexLocker locker(&game->gameMutex); + gameListMutex.unlock(); switch (command->getItemId()) { case ItemId_Command_DeckSelect: return cmdDeckSelect(static_cast(command), cont, game, player); @@ -181,7 +187,8 @@ void Server_ProtocolHandler::processCommandContainer(CommandContainer *cont) ProtocolResponse *pr = cont->getResponse(); if (!pr) pr = new ProtocolResponse(cont->getCmdId(), finalResponseCode); - + + gameListMutex.lock(); GameEventContainer *gQPublic = cont->getGameEventQueuePublic(); if (gQPublic) { Server_Game *game = games.value(gQPublic->getGameId()).first; @@ -204,6 +211,7 @@ void Server_ProtocolHandler::processCommandContainer(CommandContainer *cont) } else game->sendGameEventContainer(gQPublic); } + gameListMutex.unlock(); const QList &iQ = cont->getItemQueue(); for (int i = 0; i < iQ.size(); ++i) @@ -273,6 +281,7 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain // This might not scale very well. Use an extra QMap if it becomes a problem. QMutexLocker serverLocker(&server->serverMutex); + QMutexLocker gameListLocker(&gameListMutex); const QList &serverGames = server->getGames(); for (int i = 0; i < serverGames.size(); ++i) { QMutexLocker gameLocker(&serverGames[i]->gameMutex); @@ -435,6 +444,8 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm Server_Game *game = room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); Server_Player *creator = game->getPlayers().values().first(); + + QMutexLocker gameListLocker(&gameListMutex); games.insert(game->getGameId(), QPair(game, creator)); sendProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), creator->getPlayerId(), false, game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), false)); @@ -450,6 +461,8 @@ ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandC if (authState == PasswordWrong) return RespLoginNeeded; + QMutexLocker gameListLocker(&gameListMutex); + if (games.contains(cmd->getGameId())) return RespContextError; diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 8e671ce5d..c65d8d020 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -94,6 +94,8 @@ private: private slots: void pingClockTimeout(); public: + QMutex gameListMutex; + Server_ProtocolHandler(Server *_server, QObject *parent = 0); ~Server_ProtocolHandler(); void playerRemovedFromGame(Server_Game *game); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 835e9a111..79ef89ea2 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -63,13 +63,13 @@ ServerSocketInterface::~ServerSocketInterface() QMutexLocker locker(&servatrice->serverMutex); logger->logMessage("ServerSocketInterface destructor"); + prepareDestroy(); + flushXmlBuffer(); delete xmlWriter; delete xmlReader; delete socket; socket = 0; - - prepareDestroy(); } void ServerSocketInterface::processProtocolItem(ProtocolItem *item) From 0ea8375a2fa4937d13fcd44d4af4923d87d52f5a Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 17 Apr 2011 17:23:44 +0200 Subject: [PATCH 19/87] close buttons for tabs --- cockatrice/src/tab.h | 1 + cockatrice/src/tab_game.cpp | 10 +++- cockatrice/src/tab_game.h | 1 + cockatrice/src/tab_message.cpp | 5 ++ cockatrice/src/tab_message.h | 1 + cockatrice/src/tab_room.cpp | 5 ++ cockatrice/src/tab_room.h | 1 + cockatrice/src/tab_supervisor.cpp | 85 ++++++++++++++++++++++++++++--- cockatrice/src/tab_supervisor.h | 17 ++++++- 9 files changed, 116 insertions(+), 10 deletions(-) diff --git a/cockatrice/src/tab.h b/cockatrice/src/tab.h index ac83ec593..31fdcbab6 100644 --- a/cockatrice/src/tab.h +++ b/cockatrice/src/tab.h @@ -23,6 +23,7 @@ public: void setContentsChanged(bool _contentsChanged) { contentsChanged = _contentsChanged; } virtual QString getTabText() const = 0; virtual void retranslateUi() = 0; + virtual void closeRequest() { } }; #endif diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index a90281ad5..49f724db9 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -310,6 +310,11 @@ void TabGame::retranslateUi() scene->retranslateUi(); } +void TabGame::closeRequest() +{ + actLeaveGame(); +} + void TabGame::actConcede() { if (QMessageBox::question(this, tr("Concede"), tr("Are you sure you want to concede this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) @@ -320,8 +325,9 @@ void TabGame::actConcede() void TabGame::actLeaveGame() { - if (QMessageBox::question(this, tr("Leave game"), tr("Are you sure you want to leave this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) - return; + if (!spectator) + if (QMessageBox::question(this, tr("Leave game"), tr("Are you sure you want to leave this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) + return; sendGameCommand(new Command_LeaveGame); deleteLater(); diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 4bf30af73..5982b42b3 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -161,6 +161,7 @@ public: TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); ~TabGame(); void retranslateUi(); + void closeRequest(); const QMap &getPlayers() const { return players; } CardItem *getCard(int playerId, const QString &zoneName, int cardId) const; int getGameId() const { return gameId; } diff --git a/cockatrice/src/tab_message.cpp b/cockatrice/src/tab_message.cpp index 4581ad140..03fb401f0 100644 --- a/cockatrice/src/tab_message.cpp +++ b/cockatrice/src/tab_message.cpp @@ -40,6 +40,11 @@ void TabMessage::retranslateUi() aLeave->setText(tr("&Leave")); } +void TabMessage::closeRequest() +{ + actLeave(); +} + void TabMessage::sendMessage() { if (sayEdit->text().isEmpty() || !userOnline) diff --git a/cockatrice/src/tab_message.h b/cockatrice/src/tab_message.h index 17856aa53..b8543704c 100644 --- a/cockatrice/src/tab_message.h +++ b/cockatrice/src/tab_message.h @@ -30,6 +30,7 @@ public: TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, const QString &_userName); ~TabMessage(); void retranslateUi(); + void closeRequest(); QString getUserName() const { return userName; } QString getTabText() const { return tr("Talking to %1").arg(userName); } diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index efdc0e8af..5c4409413 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -193,6 +193,11 @@ void TabRoom::retranslateUi() aLeaveRoom->setText(tr("&Leave room")); } +void TabRoom::closeRequest() +{ + actLeaveRoom(); +} + QString TabRoom::sanitizeHtml(QString dirty) const { return dirty diff --git a/cockatrice/src/tab_room.h b/cockatrice/src/tab_room.h index 1b0133067..9c19542f3 100644 --- a/cockatrice/src/tab_room.h +++ b/cockatrice/src/tab_room.h @@ -84,6 +84,7 @@ public: TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, ServerInfo_Room *info); ~TabRoom(); void retranslateUi(); + void closeRequest(); void processRoomEvent(RoomEvent *event); int getRoomId() const { return roomId; } const QMap &getGameTypes() const { return gameTypes; } diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index 2d09bb124..be7751a08 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -11,8 +11,60 @@ #include "protocol_items.h" #include "pixmapgenerator.h" #include +#include -TabSupervisor:: TabSupervisor(QWidget *parent) +CloseButton::CloseButton(QWidget *parent) + : QAbstractButton(parent) +{ + setFocusPolicy(Qt::NoFocus); + setCursor(Qt::ArrowCursor); + resize(sizeHint()); +} + +QSize CloseButton::sizeHint() const +{ + ensurePolished(); + int width = style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, 0, this); + int height = style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, 0, this); + return QSize(width, height); +} + +void CloseButton::enterEvent(QEvent *event) +{ + update(); + QAbstractButton::enterEvent(event); +} + +void CloseButton::leaveEvent(QEvent *event) +{ + update(); + QAbstractButton::leaveEvent(event); +} + +void CloseButton::paintEvent(QPaintEvent * /*event*/) +{ + QPainter p(this); + QStyleOption opt; + opt.init(this); + opt.state |= QStyle::State_AutoRaise; + if (isEnabled() && underMouse() && !isChecked() && !isDown()) + opt.state |= QStyle::State_Raised; + if (isChecked()) + opt.state |= QStyle::State_On; + if (isDown()) + opt.state |= QStyle::State_Sunken; + + if (const QTabBar *tb = qobject_cast(parent())) { + int index = tb->currentIndex(); + QTabBar::ButtonPosition position = (QTabBar::ButtonPosition) style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, tb); + if (tb->tabButton(index, position) == this) + opt.state |= QStyle::State_Selected; + } + + style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this); +} + +TabSupervisor::TabSupervisor(QWidget *parent) : QTabWidget(parent), client(0), tabServer(0), tabDeckStorage(0), tabAdmin(0) { tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg"); @@ -47,10 +99,10 @@ void TabSupervisor::retranslateUi() } } -void TabSupervisor::myAddTab(Tab *tab) +int TabSupervisor::myAddTab(Tab *tab) { connect(tab, SIGNAL(userEvent()), this, SLOT(tabUserEvent())); - addTab(tab, tab->getTabText()); + return addTab(tab, tab->getTabText()); } void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo) @@ -152,12 +204,28 @@ void TabSupervisor::updatePingTime(int value, int max) setTabIcon(0, QIcon(PingPixmapGenerator::generatePixmap(15, value, max))); } +void TabSupervisor::closeButtonPressed() +{ + Tab *tab = static_cast(static_cast(sender())->property("tab").value()); + tab->closeRequest(); +} + +void TabSupervisor::addCloseButtonToTab(Tab *tab, int tabIndex) +{ + QTabBar::ButtonPosition closeSide = (QTabBar::ButtonPosition) tabBar()->style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, tabBar()); + CloseButton *closeButton = new CloseButton; + connect(closeButton, SIGNAL(clicked()), this, SLOT(closeButtonPressed())); + closeButton->setProperty("tab", qVariantFromValue((QObject *) tab)); + tabBar()->setTabButton(tabIndex, closeSide, closeButton); +} + void TabSupervisor::gameJoined(Event_GameJoined *event) { TabGame *tab = new TabGame(this, QList() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); - myAddTab(tab); + int tabIndex = myAddTab(tab); + addCloseButtonToTab(tab, tabIndex); gameTabs.insert(event->getGameId(), tab); setCurrentWidget(tab); } @@ -166,7 +234,8 @@ void TabSupervisor::localGameJoined(Event_GameJoined *event) { TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); - myAddTab(tab); + int tabIndex = myAddTab(tab); + addCloseButtonToTab(tab, tabIndex); gameTabs.insert(event->getGameId(), tab); setCurrentWidget(tab); @@ -192,7 +261,8 @@ void TabSupervisor::addRoomTab(ServerInfo_Room *info, bool setCurrent) TabRoom *tab = new TabRoom(this, client, userName, info); connect(tab, SIGNAL(roomClosing(TabRoom *)), this, SLOT(roomLeft(TabRoom *))); connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); - myAddTab(tab); + int tabIndex = myAddTab(tab); + addCloseButtonToTab(tab, tabIndex); roomTabs.insert(info->getRoomId(), tab); if (setCurrent) setCurrentWidget(tab); @@ -213,7 +283,8 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus TabMessage *tab = new TabMessage(this, client, userName, receiverName); connect(tab, SIGNAL(talkClosing(TabMessage *)), this, SLOT(talkLeft(TabMessage *))); - myAddTab(tab); + int tabIndex = myAddTab(tab); + addCloseButtonToTab(tab, tabIndex); messageTabs.insert(receiverName, tab); if (focus) setCurrentWidget(tab); diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index 087d93270..439ac1f88 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -3,6 +3,7 @@ #include #include +#include class QMenu; class AbstractClient; @@ -21,6 +22,18 @@ class Event_Message; class ServerInfo_Room; class ServerInfo_User; +class CloseButton : public QAbstractButton { + Q_OBJECT +public: + CloseButton(QWidget *parent = 0); + QSize sizeHint() const; + inline QSize minimumSizeHint() const { return sizeHint(); } +protected: + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void paintEvent(QPaintEvent *event); +}; + class TabSupervisor : public QTabWidget { Q_OBJECT private: @@ -36,7 +49,8 @@ private: QMap roomTabs; QMap gameTabs; QMap messageTabs; - void myAddTab(Tab *tab); + int myAddTab(Tab *tab); + void addCloseButtonToTab(Tab *tab, int tabIndex); public: TabSupervisor(QWidget *parent = 0); ~TabSupervisor(); @@ -52,6 +66,7 @@ signals: void setMenu(QMenu *menu); void localGameEnded(); private slots: + void closeButtonPressed(); void updateCurrent(int index); void updatePingTime(int value, int max); void gameJoined(Event_GameJoined *event); From e6fc20114e70291953514b22ccfeb94ece40e315 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 18 Apr 2011 02:00:48 +0200 Subject: [PATCH 20/87] deck editor and picture file name fixes --- cockatrice/src/carddatabase.cpp | 4 ++-- cockatrice/src/carddatabasemodel.h | 10 +++++----- cockatrice/src/window_deckeditor.cpp | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index ff8e44742..1ba308b6d 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -298,8 +298,8 @@ QString CardInfo::getMainCardType() const QString CardInfo::getCorrectedName() const { QString result = name; - // Fire // Ice, Circle of Protection: Red - return result.remove(" // ").remove(":"); + // Fire // Ice, Circle of Protection: Red, "Ach! Hans, Run!", Who/What/When/Where/Why, Question Elemental? + return result.remove(" // ").remove(':').remove('"').remove('?').replace('/', ' '); } void CardInfo::addToSet(CardSet *set) diff --git a/cockatrice/src/carddatabasemodel.h b/cockatrice/src/carddatabasemodel.h index 453782579..d6404b422 100644 --- a/cockatrice/src/carddatabasemodel.h +++ b/cockatrice/src/carddatabasemodel.h @@ -31,11 +31,11 @@ private: QSet cardTypes, cardColors; public: CardDatabaseDisplayModel(QObject *parent = 0); - void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidateFilter(); } - void setCardName(const QString &_cardName) { cardName = _cardName; invalidateFilter(); } - void setCardText(const QString &_cardText) { cardText = _cardText; invalidateFilter(); } - void setCardTypes(const QSet &_cardTypes) { cardTypes = _cardTypes; invalidateFilter(); } - void setCardColors(const QSet &_cardColors) { cardColors = _cardColors; invalidateFilter(); } + void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); } + void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); } + void setCardText(const QString &_cardText) { cardText = _cardText; invalidate(); } + void setCardTypes(const QSet &_cardTypes) { cardTypes = _cardTypes; invalidate(); } + void setCardColors(const QSet &_cardColors) { cardColors = _cardColors; invalidate(); } void clearSearch(); protected: bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp index ef16693dd..e540aad6c 100644 --- a/cockatrice/src/window_deckeditor.cpp +++ b/cockatrice/src/window_deckeditor.cpp @@ -68,6 +68,7 @@ WndDeckEditor::WndDeckEditor(QWidget *parent) databaseView = new QTreeView(); databaseView->setModel(databaseDisplayModel); databaseView->setUniformRowHeights(true); + databaseView->setRootIsDecorated(false); databaseView->setAlternatingRowColors(true); databaseView->setSortingEnabled(true); databaseView->sortByColumn(0, Qt::AscendingOrder); From 6f3a20f53f9c70531d188e7cee764f3199fdb865 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 18 Apr 2011 17:50:42 +0200 Subject: [PATCH 21/87] SIGABRT handler, crash fix --- common/server_room.cpp | 1 - servatrice/src/main.cpp | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/common/server_room.cpp b/common/server_room.cpp index 329534274..8ca6e9971 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -84,7 +84,6 @@ Server_Game *Server_Room::createGame(const QString &description, const QString & Server_Game *newGame = new Server_Game(creator, static_cast(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); newGame->moveToThread(thread()); - newGame->setParent(this); // This mutex needs to be unlocked by the caller. newGame->gameMutex.lock(); games.insert(newGame->getGameId(), newGame); diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index 5feffe0ad..a5ebe207c 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -75,7 +75,10 @@ void myMessageOutput(QtMsgType /*type*/, const char *msg) void sigSegvHandler(int sig) { - logger->logMessage("SIGSEGV"); + if (sig == SIGSEGV) + logger->logMessage("CRASH: SIGSEGV"); + else if (sig == SIGABRT) + logger->logMessage("CRASH: SIGABRT"); delete loggerThread; raise(sig); } @@ -114,6 +117,7 @@ int main(int argc, char *argv[]) segv.sa_flags = SA_RESETHAND; sigemptyset(&segv.sa_mask); sigaction(SIGSEGV, &segv, 0); + sigaction(SIGABRT, &segv, 0); #endif rng = new RNG_SFMT; From 69fce1fb5dfd655be43997c623ed00663981e269 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 18 Apr 2011 18:55:35 +0200 Subject: [PATCH 22/87] thread fixes --- common/server.cpp | 2 ++ common/server_game.cpp | 10 +++++++++- common/server_game.h | 2 ++ common/server_player.cpp | 6 ++++++ common/server_player.h | 1 + common/server_protocolhandler.cpp | 1 + common/server_room.cpp | 2 ++ 7 files changed, 23 insertions(+), 1 deletion(-) diff --git a/common/server.cpp b/common/server.cpp index d19d2edb0..064f7519c 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -101,7 +101,9 @@ void Server::broadcastRoomUpdate() QMutexLocker locker(&serverMutex); Server_Room *room = static_cast(sender()); QList eventRoomList; + room->roomMutex.lock(); eventRoomList.append(new ServerInfo_Room(room->getId(), room->getName(), room->getDescription(), room->getGames().size(), room->size(), room->getAutoJoin())); + room->roomMutex.unlock(); Event_ListRooms *event = new Event_ListRooms(eventRoomList); for (int i = 0; i < clients.size(); ++i) diff --git a/common/server_game.cpp b/common/server_game.cpp index cf65553e2..3ef78a0fb 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -31,6 +31,8 @@ Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room) : QObject(), room(_room), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0), gameMutex(QMutex::Recursive) { + connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection); + addPlayer(_creator, false, false); if (room->getServer()->getGameShouldPing()) { @@ -111,7 +113,7 @@ int Server_Game::getSpectatorCount() const return result; } -void Server_Game::startGameIfReady() +void Server_Game::doStartGameIfReady() { QMutexLocker locker(&gameMutex); @@ -159,6 +161,11 @@ void Server_Game::startGameIfReady() nextTurn(); } +void Server_Game::startGameIfReady() +{ + emit sigStartGameIfReady(); +} + void Server_Game::stopGameIfFinished() { QMutexLocker locker(&gameMutex); @@ -214,6 +221,7 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec int playerId = keyList.isEmpty() ? 0 : (keyList.last() + 1); Server_Player *newPlayer = new Server_Player(this, playerId, handler->getUserInfo(), spectator, handler); + newPlayer->moveToThread(thread()); sendGameEvent(new Event_Join(newPlayer->getProperties())); players.insert(playerId, newPlayer); diff --git a/common/server_game.h b/common/server_game.h index 15e85968f..d2af449b9 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -54,8 +54,10 @@ private: QTimer *pingClock; signals: void gameClosing(); + void sigStartGameIfReady(); private slots: void pingClockTimeout(); + void doStartGameIfReady(); public: mutable QMutex gameMutex; Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent); diff --git a/common/server_player.cpp b/common/server_player.cpp index f71c4cd58..9dd42eb53 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -29,6 +29,12 @@ Server_Player::~Server_Player() clearZones(); } +void Server_Player::moveToThread(QThread *thread) +{ + QObject::moveToThread(thread); + userInfo->moveToThread(thread); +} + int Server_Player::newCardId() { QMutexLocker locker(&game->gameMutex); diff --git a/common/server_player.h b/common/server_player.h index ccb43d0f0..e0f7de492 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -43,6 +43,7 @@ private: public: Server_Player(Server_Game *_game, int _playerId, ServerInfo_User *_userInfo, bool _spectator, Server_ProtocolHandler *_handler); ~Server_Player(); + void moveToThread(QThread *thread); Server_ProtocolHandler *getProtocolHandler() const { return handler; } void setProtocolHandler(Server_ProtocolHandler *_handler) { playerMutex.lock(); handler = _handler; playerMutex.unlock(); } diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 05ef513b7..dc74ad62b 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -821,6 +821,7 @@ ResponseCode Server_ProtocolHandler::cmdCreateToken(Command_CreateToken *cmd, Co y = 0; Server_Card *card = new Server_Card(cmd->getCardName(), player->newCardId(), x, y); + card->moveToThread(player->thread()); card->setPT(cmd->getPt()); card->setColor(cmd->getColor()); card->setAnnotation(cmd->getAnnotation()); diff --git a/common/server_room.cpp b/common/server_room.cpp index 329534274..f02517099 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -103,6 +103,8 @@ void Server_Room::removeGame() QMutexLocker locker(&roomMutex); Server_Game *game = static_cast(sender()); + QMutexLocker gameLocker(&game->gameMutex); + broadcastGameListUpdate(game); games.remove(game->getGameId()); From 1b8a6dc2e957bfa599be155aba1428ca0d0b5542 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 18 Apr 2011 19:02:00 +0200 Subject: [PATCH 23/87] error message for tcpServer->listen() --- servatrice/src/servatrice.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 94ab833a6..cc8fb5b33 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -58,7 +58,10 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) tcpServer = new Servatrice_TcpServer(this); int port = settings->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << port; - tcpServer->listen(QHostAddress::Any, port); + if (tcpServer->listen(QHostAddress::Any, port)) + qDebug() << "Server listening."; + else + qDebug() << "tcpServer->listen(): Error."; QString dbType = settings->value("database/type").toString(); dbPrefix = settings->value("database/prefix").toString(); From e978624e3fbd974bc31c29938416cc9308cf74f6 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 18 Apr 2011 19:16:18 +0200 Subject: [PATCH 24/87] added esc as leave game shortcut --- cockatrice/src/tab_game.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 49f724db9..596a4e4be 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -296,6 +296,7 @@ void TabGame::retranslateUi() aConcede->setText(tr("&Concede")); aConcede->setShortcut(tr("F2")); aLeaveGame->setText(tr("&Leave game")); + aLeaveGame->setShortcut(tr("Esc")); sayLabel->setText(tr("&Say:")); cardInfo->retranslateUi(); From d0b8c6ebd951d85e1eb927402acbfc5eb6acf220 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 19 Apr 2011 04:13:23 +0200 Subject: [PATCH 25/87] changed mutex lock --- common/server_protocolhandler.cpp | 7 ++++--- servatrice/src/serversocketinterface.cpp | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index dc74ad62b..355ccdaf7 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -24,11 +24,12 @@ Server_ProtocolHandler::~Server_ProtocolHandler() } // This is essentially the destructor, but it needs to be called from the -// child's destructor with the server mutex locked. Otherwise, the mutex -// could get unlocked while the object is not finished being destroyed, -// leading to calls to pure virtual functions. +// child's destructor so that the server mutex does not get unlocked during +// finalization. void Server_ProtocolHandler::prepareDestroy() { + QMutexLocker locker(&server->serverMutex); + server->removeClient(this); QMapIterator roomIterator(rooms); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 79ef89ea2..f02747cae 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -60,7 +60,6 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s ServerSocketInterface::~ServerSocketInterface() { - QMutexLocker locker(&servatrice->serverMutex); logger->logMessage("ServerSocketInterface destructor"); prepareDestroy(); From 38b31681e2864e745efa7279150135e43d10617e Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 21 Apr 2011 01:52:09 +0200 Subject: [PATCH 26/87] changed leave game shortcut, server cleanups, added max_games_per_user --- cockatrice/src/tab_game.cpp | 2 +- common/server.cpp | 34 ++++++++++-------- common/server.h | 7 ++-- common/server_game.cpp | 5 ++- common/server_game.h | 1 - common/server_protocolhandler.cpp | 60 +++++++++++++++++-------------- common/server_room.cpp | 23 +++++++----- common/server_room.h | 6 ++-- servatrice/servatrice.ini.example | 1 + servatrice/src/servatrice.cpp | 7 ++-- servatrice/src/servatrice.h | 3 +- 11 files changed, 85 insertions(+), 64 deletions(-) diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 596a4e4be..fd6c76f03 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -296,7 +296,7 @@ void TabGame::retranslateUi() aConcede->setText(tr("&Concede")); aConcede->setShortcut(tr("F2")); aLeaveGame->setText(tr("&Leave game")); - aLeaveGame->setShortcut(tr("Esc")); + aLeaveGame->setShortcut(tr("Ctrl+Q")); sayLabel->setText(tr("&Say:")); cardInfo->retranslateUi(); diff --git a/common/server.cpp b/common/server.cpp index 064f7519c..67e1172a7 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -112,24 +112,28 @@ void Server::broadcastRoomUpdate() delete event; } -void Server::gameCreated(Server_Game *game) -{ - QMutexLocker locker(&serverMutex); - games.insert(game->getGameId(), game); -} - -void Server::gameClosing(int gameId) -{ - QMutexLocker locker(&serverMutex); - qDebug("Server::gameClosing"); - games.remove(gameId); -} - void Server::addRoom(Server_Room *newRoom) { QMutexLocker locker(&serverMutex); rooms.insert(newRoom->getId(), newRoom); connect(newRoom, SIGNAL(roomInfoChanged()), this, SLOT(broadcastRoomUpdate())); - connect(newRoom, SIGNAL(gameCreated(Server_Game *)), this, SLOT(gameCreated(Server_Game *))); - connect(newRoom, SIGNAL(gameClosing(int)), this, SLOT(gameClosing(int))); +} + +int Server::getUsersCount() const +{ + QMutexLocker locker(&serverMutex); + return users.size(); +} + +int Server::getGamesCount() const +{ + int result = 0; + QMutexLocker locker(&serverMutex); + QMapIterator roomIterator(rooms); + while (roomIterator.hasNext()) { + Server_Room *room = roomIterator.next().value(); + QMutexLocker roomLocker(&room->roomMutex); + result += room->getGames().size(); + } + return result; } diff --git a/common/server.h b/common/server.h index 70ef8b024..e401ca806 100644 --- a/common/server.h +++ b/common/server.h @@ -19,15 +19,12 @@ class Server : public QObject signals: void pingClockTimeout(); private slots: - void gameCreated(Server_Game *game); - void gameClosing(int gameId); void broadcastRoomUpdate(); public: mutable QMutex serverMutex; Server(QObject *parent = 0); ~Server(); AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password); - QList getGames() const { return games.values(); } const QMap &getRooms() { return rooms; } int getNextGameId() { return nextGameId++; } @@ -42,12 +39,12 @@ public: virtual int getMessageCountingInterval() const { return 0; } virtual int getMaxMessageCountPerInterval() const { return 0; } virtual int getMaxMessageSizePerInterval() const { return 0; } + virtual int getMaxGamesPerUser() const { return 0; } virtual QMap getBuddyList(const QString &name) = 0; virtual QMap getIgnoreList(const QString &name) = 0; virtual bool getUserBanned(Server_ProtocolHandler * /*client*/, const QString & /*userName*/) const { return false; } protected: - QMap games; QList clients; QMap users; QMap rooms; @@ -55,6 +52,8 @@ protected: virtual bool userExists(const QString &user) = 0; virtual AuthenticationResult checkUserPassword(const QString &user, const QString &password) = 0; virtual ServerInfo_User *getUserData(const QString &name) = 0; + int getUsersCount() const; + int getGamesCount() const; int nextGameId; void addRoom(Server_Room *newRoom); }; diff --git a/common/server_game.cpp b/common/server_game.cpp index 3ef78a0fb..6a206bb74 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -44,6 +44,7 @@ Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QS Server_Game::~Server_Game() { + QMutexLocker roomLocker(&room->roomMutex); QMutexLocker locker(&gameMutex); sendGameEvent(new Event_GameClosed); @@ -53,7 +54,7 @@ Server_Game::~Server_Game() delete playerIterator.next().value(); players.clear(); - emit gameClosing(); + room->removeGame(this); delete creatorInfo; qDebug("Server_Game destructor"); } @@ -233,6 +234,7 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec void Server_Game::removePlayer(Server_Player *player) { + QMutexLocker roomLocker(&room->roomMutex); QMutexLocker locker(&gameMutex); players.remove(player->getPlayerId()); @@ -281,6 +283,7 @@ void Server_Game::removeArrowsToPlayer(Server_Player *player) bool Server_Game::kickPlayer(int playerId) { + QMutexLocker roomLocker(&room->roomMutex); QMutexLocker locker(&gameMutex); Server_Player *playerToKick = players.value(playerId); diff --git a/common/server_game.h b/common/server_game.h index d2af449b9..2042a4441 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -53,7 +53,6 @@ private: int secondsElapsed; QTimer *pingClock; signals: - void gameClosing(); void sigStartGameIfReady(); private slots: void pingClockTimeout(); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 355ccdaf7..70e8c1eb6 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -276,37 +276,21 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage())); + QList _buddyList, _ignoreList; if (authState == PasswordRight) { buddyList = server->getBuddyList(userInfo->getName()); + + QMapIterator buddyIterator(buddyList); + while (buddyIterator.hasNext()) + _buddyList.append(new ServerInfo_User(buddyIterator.next().value())); + ignoreList = server->getIgnoreList(userInfo->getName()); - // This might not scale very well. Use an extra QMap if it becomes a problem. - QMutexLocker serverLocker(&server->serverMutex); - QMutexLocker gameListLocker(&gameListMutex); - const QList &serverGames = server->getGames(); - for (int i = 0; i < serverGames.size(); ++i) { - QMutexLocker gameLocker(&serverGames[i]->gameMutex); - const QList &gamePlayers = serverGames[i]->getPlayers().values(); - for (int j = 0; j < gamePlayers.size(); ++j) - if (gamePlayers[j]->getUserInfo()->getName() == userInfo->getName()) { - gamePlayers[j]->setProtocolHandler(this); - games.insert(serverGames[i]->getGameId(), QPair(serverGames[i], gamePlayers[j])); - - enqueueProtocolItem(new Event_GameJoined(serverGames[i]->getGameId(), serverGames[i]->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), serverGames[i]->getSpectatorsCanTalk(), serverGames[i]->getSpectatorsSeeEverything(), true)); - enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(serverGames[i]->getGameStarted(), serverGames[i]->getActivePlayer(), serverGames[i]->getActivePhase(), serverGames[i]->getGameState(gamePlayers[j])), serverGames[i]->getGameId())); - } - } + QMapIterator ignoreIterator(ignoreList); + while (ignoreIterator.hasNext()) + _ignoreList.append(new ServerInfo_User(ignoreIterator.next().value())); } - QList _buddyList; - QMapIterator buddyIterator(buddyList); - while (buddyIterator.hasNext()) - _buddyList.append(new ServerInfo_User(buddyIterator.next().value())); - QList _ignoreList; - QMapIterator ignoreIterator(ignoreList); - while (ignoreIterator.hasNext()) - _ignoreList.append(new ServerInfo_User(ignoreIterator.next().value())); - cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList)); return RespNothing; } @@ -373,12 +357,32 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC Server_Room *r = server->getRooms().value(cmd->getRoomId(), 0); if (!r) return RespNameNotFound; - + + QMutexLocker roomLocker(&r->roomMutex); r->addClient(this); rooms.insert(r->getId(), r); enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage())); + // This might not scale very well. Use an extra QMap if it becomes a problem. + QMutexLocker gameListLocker(&gameListMutex); + QMapIterator gameIterator(r->getGames()); + while (gameIterator.hasNext()) { + Server_Game *game = gameIterator.next().value(); + QMutexLocker gameLocker(&game->gameMutex); + const QList &gamePlayers = game->getPlayers().values(); + for (int j = 0; j < gamePlayers.size(); ++j) + if (gamePlayers[j]->getUserInfo()->getName() == userInfo->getName()) { + gamePlayers[j]->setProtocolHandler(this); + games.insert(game->getGameId(), QPair(game, gamePlayers[j])); + + enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), true)); + enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(gamePlayers[j])), game->getGameId())); + + break; + } + } + cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, r->getInfo(true))); return RespNothing; } @@ -436,6 +440,10 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm { if (authState == PasswordWrong) return RespLoginNeeded; + + if (server->getMaxGamesPerUser() > 0) + if (room->getGamesCreatedByUser(userInfo->getName()) >= server->getMaxGamesPerUser()) + return RespContextError; QList gameTypes; QList gameTypeList = cmd->getGameTypes(); diff --git a/common/server_room.cpp b/common/server_room.cpp index 7117b7980..75aa10edd 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -87,26 +87,33 @@ Server_Game *Server_Room::createGame(const QString &description, const QString & // This mutex needs to be unlocked by the caller. newGame->gameMutex.lock(); games.insert(newGame->getGameId(), newGame); - connect(newGame, SIGNAL(gameClosing()), this, SLOT(removeGame())); broadcastGameListUpdate(newGame); - emit gameCreated(newGame); emit roomInfoChanged(); return newGame; } -void Server_Room::removeGame() +void Server_Room::removeGame(Server_Game *game) { - QMutexLocker locker(&roomMutex); - - Server_Game *game = static_cast(sender()); - QMutexLocker gameLocker(&game->gameMutex); + // No need to lock roomMutex or gameMutex. This method is only + // called from ~Server_Game, which locks both mutexes anyway beforehand. broadcastGameListUpdate(game); games.remove(game->getGameId()); - emit gameClosing(game->getGameId()); emit roomInfoChanged(); } + +int Server_Room::getGamesCreatedByUser(const QString &userName) const +{ + QMutexLocker locker(&roomMutex); + + QMapIterator gamesIterator(games); + int result = 0; + while (gamesIterator.hasNext()) + if (gamesIterator.next().value()->getCreatorInfo()->getName() == userName) + ++result; + return result; +} diff --git a/common/server_room.h b/common/server_room.h index 10f6c255b..e5f4867c4 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -18,8 +18,6 @@ class Server_Room : public QObject, public QList { Q_OBJECT signals: void roomInfoChanged(); - void gameCreated(Server_Game *game); - void gameClosing(int gameId); private: int id; QString name; @@ -28,8 +26,6 @@ private: QString joinMessage; QStringList gameTypes; QMap games; -private slots: - void removeGame(); public: mutable QMutex roomMutex; Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent); @@ -41,12 +37,14 @@ public: const QMap &getGames() const { return games; } Server *getServer() const; ServerInfo_Room *getInfo(bool complete) const; + int getGamesCreatedByUser(const QString &name) const; void addClient(Server_ProtocolHandler *client); void removeClient(Server_ProtocolHandler *client); void say(Server_ProtocolHandler *client, const QString &s); void broadcastGameListUpdate(Server_Game *game); Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); + void removeGame(Server_Game *game); void sendRoomEvent(RoomEvent *event); }; diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 37e88a75e..72647bc4d 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -35,3 +35,4 @@ max_users_per_address=4 message_counting_interval=10 max_message_size_per_interval=1000 max_message_count_per_interval=10 +max_games_per_user=5 diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index cc8fb5b33..3e36a808c 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -102,6 +102,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) messageCountingInterval = settings->value("security/message_counting_interval").toInt(); maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt(); maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt(); + maxGamesPerUser = settings->value("security/max_games_per_user").toInt(); } Servatrice::~Servatrice() @@ -357,9 +358,9 @@ void Servatrice::statusUpdate() query.prepare("insert into " + dbPrefix + "_uptime (id_server, timest, uptime, users_count, games_count) values(:id, NOW(), :uptime, :users_count, :games_count)"); query.bindValue(":id", serverId); query.bindValue(":uptime", uptime); - query.bindValue(":users_count", users.size()); - query.bindValue(":games_count", games.size()); + query.bindValue(":users_count", getUsersCount()); + query.bindValue(":games_count", getGamesCount()); execSqlQuery(query); } -const QString Servatrice::versionString = "Servatrice 0.20110406"; +const QString Servatrice::versionString = "Servatrice 0.20110421"; diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 0296a9033..9498d8a17 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -65,6 +65,7 @@ public: int getMessageCountingInterval() const { return messageCountingInterval; } int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; } int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; } + int getMaxGamesPerUser() const { return maxGamesPerUser; } QString getDbPrefix() const { return dbPrefix; } void updateLoginMessage(); ServerInfo_User *getUserData(const QString &name); @@ -88,7 +89,7 @@ private: QList > addressBanList; QList > nameBanList; int maxGameInactivityTime, maxPlayerInactivityTime; - int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval; + int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser; ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete); }; From c4ba33dfebeb0abc6beb69ca048f87100834bb24 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 21 Apr 2011 02:04:15 +0200 Subject: [PATCH 27/87] server mutex fix --- common/server_game.cpp | 4 ++-- common/server_player.cpp | 10 +++++++++- common/server_player.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/common/server_game.cpp b/common/server_game.cpp index 6a206bb74..a23c2bcb5 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -51,7 +51,7 @@ Server_Game::~Server_Game() QMapIterator playerIterator(players); while (playerIterator.hasNext()) - delete playerIterator.next().value(); + playerIterator.next().value()->prepareDestroy(); players.clear(); room->removeGame(this); @@ -243,7 +243,7 @@ void Server_Game::removePlayer(Server_Player *player) sendGameEvent(new Event_Leave(player->getPlayerId())); bool playerActive = activePlayer == player->getPlayerId(); bool spectator = player->getSpectator(); - delete player; + player->prepareDestroy(); if (!getPlayerCount()) deleteLater(); diff --git a/common/server_player.cpp b/common/server_player.cpp index 9dd42eb53..0a6dc8aca 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -16,17 +16,25 @@ Server_Player::Server_Player(Server_Game *_game, int _playerId, ServerInfo_User } Server_Player::~Server_Player() +{ +} + +void Server_Player::prepareDestroy() { QMutexLocker locker(&game->gameMutex); - QMutexLocker locker2(&playerMutex); delete deck; + playerMutex.lock(); if (handler) handler->playerRemovedFromGame(game); + playerMutex.unlock(); + delete userInfo; clearZones(); + + deleteLater(); } void Server_Player::moveToThread(QThread *thread) diff --git a/common/server_player.h b/common/server_player.h index e0f7de492..955dd77cf 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -43,6 +43,7 @@ private: public: Server_Player(Server_Game *_game, int _playerId, ServerInfo_User *_userInfo, bool _spectator, Server_ProtocolHandler *_handler); ~Server_Player(); + void prepareDestroy(); void moveToThread(QThread *thread); Server_ProtocolHandler *getProtocolHandler() const { return handler; } void setProtocolHandler(Server_ProtocolHandler *_handler) { playerMutex.lock(); handler = _handler; playerMutex.unlock(); } From 91e98aafd59a18b9a9ed5bb693a954a927669aef Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 21 Apr 2011 13:50:16 +0200 Subject: [PATCH 28/87] added polish translation stub --- cockatrice/cockatrice.pro | 3 +- cockatrice/cockatrice.qrc | 1 + cockatrice/translations/cockatrice_pl.ts | 3064 ++++++++++++++++++++++ 3 files changed, 3067 insertions(+), 1 deletion(-) create mode 100644 cockatrice/translations/cockatrice_pl.ts diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 4a0203f26..a1070b42b 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -177,7 +177,8 @@ TRANSLATIONS += \ translations/cockatrice_pt-br.ts \ translations/cockatrice_fr.ts \ translations/cockatrice_ja.ts \ - translations/cockatrice_ru.ts + translations/cockatrice_ru.ts \ + translations/cockatrice_pl.ts win32 { RC_FILE = cockatrice.rc } diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index a71ed41e6..6a8dd3d69 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -45,6 +45,7 @@ translations/cockatrice_fr.qm translations/cockatrice_ja.qm translations/cockatrice_ru.qm + translations/cockatrice_pl.qm resources/countries/at.svg resources/countries/au.svg diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts new file mode 100644 index 000000000..8f843f821 --- /dev/null +++ b/cockatrice/translations/cockatrice_pl.ts @@ -0,0 +1,3064 @@ + + + + + AbstractCounter + + + &Set counter... + + + + + Ctrl+L + + + + + F11 + + + + + F12 + + + + + Set counter + + + + + New value for counter '%1': + + + + + AppearanceSettingsPage + + + Zone background pictures + + + + + Path to hand background: + + + + + Path to stack background: + + + + + Path to table background: + + + + + Path to player info background: + + + + + Path to picture of card back: + + + + + Card rendering + + + + + Display card names on cards having a picture + + + + + Hand layout + + + + + Display hand horizontally (wastes space) + + + + + Table grid layout + + + + + Invert vertical coordinate + + + + + Zone view layout + + + + + Sort by name + + + + + Sort by type + + + + + + + + + Choose path + + + + + CardDatabaseModel + + + Name + + + + + Sets + + + + + Mana cost + + + + + Card type + + + + + P/T + + + + + CardInfoWidget + + + Name: + + + + + Mana cost: + + + + + Card type: + + + + + P / T: + + + + + CardItem + + + &Play + + + + + &Hide + + + + + &Tap + + + + + &Untap + + + + + Toggle &normal untapping + + + + + &Flip + + + + + &Clone + + + + + Ctrl+H + + + + + &Attach to card... + + + + + Ctrl+A + + + + + Unattac&h + + + + + &Power / toughness + + + + + &Increase power + + + + + Ctrl++ + + + + + &Decrease power + + + + + Ctrl+- + + + + + I&ncrease toughness + + + + + Alt++ + + + + + D&ecrease toughness + + + + + Alt+- + + + + + In&crease power and toughness + + + + + Ctrl+Alt++ + + + + + Dec&rease power and toughness + + + + + Ctrl+Alt+- + + + + + Set &power and toughness... + + + + + Ctrl+P + + + + + &Set annotation... + + + + + red + + + + + yellow + + + + + green + + + + + &Add counter (%1) + + + + + &Remove counter (%1) + + + + + &Set counters (%1)... + + + + + &top of library + + + + + &bottom of library + + + + + &graveyard + + + + + Ctrl+Del + + + + + &exile + + + + + &Move to + + + + + CardZone + + + his hand + nominative + + + + + %1's hand + nominative + + + + + of his hand + genitive + + + + + of %1's hand + genitive + + + + + his hand + accusative + + + + + %1's hand + accusative + + + + + his library + nominative + + + + + %1's library + nominative + + + + + of his library + genitive + + + + + of %1's library + genitive + + + + + his library + accusative + + + + + %1's library + accusative + + + + + his graveyard + nominative + + + + + %1's graveyard + nominative + + + + + of his graveyard + genitive + + + + + of %1's graveyard + genitive + + + + + his graveyard + accusative + + + + + %1's graveyard + accusative + + + + + his exile + nominative + + + + + %1's exile + nominative + + + + + of his exile + genitive + + + + + of %1's exile + genitive + + + + + his exile + accusative + + + + + %1's exile + accusative + + + + + his sideboard + nominative + + + + + %1's sideboard + nominative + + + + + of his sideboard + genitive + + + + + of %1's sideboard + genitive + + + + + his sideboard + accusative + + + + + %1's sideboard + accusative + + + + + DeckListModel + + + Number + + + + + Card + + + + + DeckViewContainer + + + Load &local deck + + + + + Load d&eck from server + + + + + Ready to s&tart + + + + + Load deck + + + + + DlgCardSearch + + + Card name: + + + + + Card text: + + + + + Card type (OR): + + + + + Color (OR): + + + + + O&K + + + + + &Cancel + + + + + Card search + + + + + DlgConnect + + + &Host: + + + + + &Port: + + + + + Player &name: + + + + + P&assword: + + + + + &OK + + + + + &Cancel + + + + + Connect to server + + + + + DlgCreateGame + + + &Description: + + + + + P&layers: + + + + + Game type + + + + + &Password: + + + + + Only &buddies can join + + + + + Only &registered users can join + + + + + Joining restrictions + + + + + &Spectators allowed + + + + + Spectators &need a password to join + + + + + Spectators can &chat + + + + + Spectators see &everything + + + + + Spectators + + + + + &OK + + + + + &Cancel + + + + + Create game + + + + + Error + + + + + Server error. + + + + + DlgCreateToken + + + &Name: + + + + + Token + + + + + C&olor: + + + + + white + + + + + blue + + + + + black + + + + + red + + + + + green + + + + + multicolor + + + + + colorless + + + + + &P/T: + + + + + &Annotation: + + + + + &Destroy token when it leaves the table + + + + + &OK + + + + + &Cancel + + + + + Create token + + + + + DlgLoadDeckFromClipboard + + + &Refresh + + + + + &OK + + + + + &Cancel + + + + + Load deck from clipboard + + + + + Error + + + + + Invalid deck list. + + + + + DlgLoadRemoteDeck + + + O&K + + + + + &Cancel + + + + + Load deck + + + + + DlgSettings + + + + + Error + + + + + Your card database is invalid. Would you like to go back and set the correct path? + + + + + The path to your deck directory is invalid. Would you like to go back and set the correct path? + + + + + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? + + + + + Settings + + + + + General + + + + + Appearance + + + + + User interface + + + + + Messages + + + + + &Close + + + + + GameSelector + + + + + + + + + Error + + + + + Wrong password. + + + + + Spectators are not allowed in this game. + + + + + The game is already full. + + + + + The game does not exist any more. + + + + + This game is only open to registered users. + + + + + This game is only open to its creator's buddies. + + + + + You are being ignored by the creator of this game. + + + + + Join game + + + + + Password: + + + + + Games + + + + + Show &full games + + + + + C&reate + + + + + &Join + + + + + J&oin as spectator + + + + + GameView + + + Esc + + + + + GamesModel + + + yes + + + + + yes, free for spectators + + + + + no + + + + + buddies only + + + + + reg. users only + + + + + not allowed + + + + + Description + + + + + Creator + + + + + Game type + + + + + Password + + + + + Restrictions + + + + + Players + + + + + Spectators + + + + + GeneralSettingsPage + + + + English + + + + + + + Choose path + + + + + Personal settings + + + + + Language: + + + + + Download card pictures on the fly + + + + + Paths + + + + + Decks directory: + + + + + Pictures directory: + + + + + Path to card database: + + + + + MainWindow + + + There are too many concurrent connections from your address. + + + + + Banned by moderator. + + + + + Unknown reason. + + + + + Connection closed + + + + + The server has terminated your connection. +Reason: %1 + + + + + Number of players + + + + + Please enter the number of players. + + + + + + Player %1 + + + + + About Cockatrice + + + + + Version %1 + + + + + Authors: + + + + + Translators: + + + + + Spanish: + + + + + Portugese (Portugal): + + + + + Portugese (Brazil): + + + + + French: + + + + + Japanese: + + + + + Russian: + + + + + + + + + + Error + + + + + Server timeout + + + + + Invalid login data. + + + + + There is already an active session using this user name. +Please close that session first and re-login. + + + + + Socket error: %1 + + + + + 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. + + + + + Your Cockatrice client is obsolete. Please update your Cockatrice version. +Local version is %1, remote version is %2. + + + + + Connecting to %1... + + + + + Disconnected + + + + + Logged in at %1 + + + + + &Connect... + + + + + &Disconnect + + + + + Start &local game... + + + + + &Deck editor + + + + + &Full screen + + + + + Ctrl+F + + + + + &Settings... + + + + + &Exit + + + + + &Cockatrice + + + + + &About Cockatrice + + + + + &Help + + + + + Are you sure? + + + + + There are still open games. Are you sure you want to quit? + + + + + MessageLogWidget + + + Connecting to %1... + + + + + Connected. + + + + + Disconnected from server. + + + + + Invalid password. + + + + + Protocol version mismatch. Client: %1, Server: %2 + + + + + Protocol error. + + + + + You have joined game #%1. + + + + + %1 has joined the game. + + + + + %1 has left the game. + + + + + The game has been closed. + + + + + %1 is now watching the game. + + + + + %1 is not watching the game any more. + + + + + %1 has loaded a local deck. + + + + + %1 has loaded deck #%2. + + + + + %1 is ready to start the game. + + + + + %1 is not ready to start the game any more. + + + + + %1 has conceded the game. + + + + + The game has started. + + + + + %1 shuffles his library. + + + + + %1 rolls a %2 with a %3-sided die. + + + + + %1 draws %n card(s). + + + + + + + + + %1 undoes his last draw. + + + + + %1 undoes his last draw (%2). + + + + + from table + + + + + from graveyard + + + + + from exile + + + + + from hand + + + + + the bottom card of his library + + + + + from the bottom of his library + + + + + the top card of his library + + + + + from the top of his library + + + + + from library + + + + + from sideboard + + + + + from the stack + + + + + + a card + + + + + %1 gives %2 control over %3. + + + + + %1 puts %2 into play tapped%3. + + + + + %1 puts %2 into play%3. + + + + + %1 puts %2%3 into graveyard. + + + + + %1 exiles %2%3. + + + + + %1 moves %2%3 to hand. + + + + + %1 puts %2%3 into his library. + + + + + %1 puts %2%3 on bottom of his library. + + + + + %1 puts %2%3 on top of his library. + + + + + %1 puts %2%3 into his library at position %4. + + + + + %1 moves %2%3 to sideboard. + + + + + %1 plays %2%3. + + + + + %1 flips %2 face-down. + + + + + %1 flips %2 face-up. + + + + + %1 destroys %2. + + + + + %1 attaches %2 to %3's %4. + + + + + %1 unattaches %2. + + + + + %1 creates token: %2%3. + + + + + %1 points from %2's %3 to %4. + + + + + %1 points from %2's %3 to %4's %5. + + + + + %1 places %n %2 counter(s) on %3 (now %4). + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + + + + + + + + + red + + + + + + + + + yellow + + + + + + + + + green + + + + + + + + + his permanents + + + + + %1 %2 %3. + + + + + taps + + + + + untaps + + + + + %1 sets counter %2 to %3 (%4%5). + + + + + %1 sets %2 to not untap normally. + + + + + %1 sets %2 to untap normally. + + + + + %1 sets PT of %2 to %3. + + + + + %1 sets annotation of %2 to %3. + + + + + %1 is looking at the top %2 cards %3. + + + + + %1 is looking at %2. + + + + + %1 stops looking at %2. + + + + + %1 reveals %2 to %3. + + + + + %1 reveals %2. + + + + + %1 randomly reveals %2%3 to %4. + + + + + %1 randomly reveals %2%3. + + + + + %1 reveals %2%3 to %4. + + + + + %1 reveals %2%3. + + + + + It is now %1's turn. + + + + + untap step + + + + + upkeep step + + + + + draw step + + + + + first main phase + + + + + beginning of combat step + + + + + declare attackers step + + + + + declare blockers step + + + + + combat damage step + + + + + end of combat step + + + + + second main phase + + + + + ending phase + + + + + It is now the %1. + + + + + MessagesSettingsPage + + + Add message + + + + + Message: + + + + + &Add + + + + + &Remove + + + + + PhasesToolbar + + + Untap step + + + + + Upkeep step + + + + + Draw step + + + + + First main phase + + + + + Beginning of combat step + + + + + Declare attackers step + + + + + Declare blockers step + + + + + Combat damage step + + + + + End of combat step + + + + + Second main phase + + + + + End of turn step + + + + + Player + + + &View graveyard + + + + + &View exile + + + + + Player "%1" + + + + + &Graveyard + + + + + &Exile + + + + + + + Move to &top of library + + + + + + + Move to &bottom of library + + + + + + Move to &graveyard + + + + + + Move to &exile + + + + + + Move to &hand + + + + + &View library + + + + + View &top cards of library... + + + + + Reveal &library to + + + + + Reveal t&op card to + + + + + &View sideboard + + + + + &Draw card + + + + + D&raw cards... + + + + + &Undo last draw + + + + + Take &mulligan + + + + + &Shuffle + + + + + Move top cards to &graveyard... + + + + + Move top cards to &exile... + + + + + Put top card on &bottom + + + + + &Hand + + + + + &Reveal to + + + + + Reveal r&andom card to + + + + + &Sideboard + + + + + &Library + + + + + &Counters + + + + + &Untap all permanents + + + + + R&oll die... + + + + + &Create token... + + + + + C&reate another token + + + + + S&ay + + + + + C&ard + + + + + &All players + + + + + Ctrl+F3 + + + + + F3 + + + + + Ctrl+W + + + + + F4 + + + + + Ctrl+D + + + + + Ctrl+E + + + + + Ctrl+Shift+D + + + + + Ctrl+M + + + + + Ctrl+S + + + + + Ctrl+U + + + + + Ctrl+I + + + + + Ctrl+T + + + + + Ctrl+G + + + + + View top cards of library + + + + + Number of cards: + + + + + Draw cards + + + + + + + + Number: + + + + + Move top cards to grave + + + + + Move top cards to exile + + + + + Roll die + + + + + Number of sides: + + + + + Set power/toughness + + + + + Please enter the new PT: + + + + + Set annotation + + + + + Please enter the new annotation: + + + + + Set counters + + + + + PlayerListWidget + + + local deck + + + + + deck #%1 + + + + + User &details + + + + + Direct &chat + + + + + Add to &buddy list + + + + + Remove from &buddy list + + + + + Add to &ignore list + + + + + Remove from &ignore list + + + + + Kick from &game + + + + + QObject + + + Maindeck + + + + + Sideboard + + + + + Cockatrice decks (*.cod) + + + + + Plain text decks (*.dec *.mwDeck) + + + + + All files (*.*) + + + + + RemoteDeckList_TreeModel + + + Name + + + + + ID + + + + + Upload time + + + + + RoomSelector + + + Rooms + + + + + Joi&n + + + + + Room + + + + + Description + + + + + Players + + + + + Games + + + + + SetsModel + + + Short name + + + + + Long name + + + + + TabAdmin + + + Update server &message + + + + + Server administration functions + + + + + &Unlock functions + + + + + &Lock functions + + + + + Unlock administration functions + + + + + Do you really want to unlock the administration functions? + + + + + Administration + + + + + TabDeckStorage + + + Local file system + + + + + Server deck storage + + + + + + Open in deck editor + + + + + Upload deck + + + + + Download deck + + + + + + New folder + + + + + Delete + + + + + Enter deck name + + + + + This decklist does not have a name. +Please enter a name: + + + + + + Unnamed deck + + + + + Name of new folder: + + + + + Deck storage + + + + + TabGame + + + F5 + + + + + F6 + + + + + F7 + + + + + F8 + + + + + F9 + + + + + F10 + + + + + &Phases + + + + + &Game + + + + + Next &phase + + + + + Ctrl+Space + + + + + Next &turn + + + + + Ctrl+Return + + + + + Ctrl+Enter + + + + + &Remove all local arrows + + + + + Ctrl+R + + + + + &Concede + + + + + F2 + + + + + &Leave game + + + + + &Say: + + + + + Concede + + + + + Are you sure you want to concede this game? + + + + + Leave game + + + + + Are you sure you want to leave this game? + + + + + Kicked + + + + + You have been kicked out of the game. + + + + + Game %1: %2 + + + + + TabMessage + + + Personal &talk + + + + + &Leave + + + + + This user is ignoring you. + + + + + %1 has left the server. + + + + + %1 has joined the server. + + + + + Talking to %1 + + + + + TabRoom + + + &Say: + + + + + Chat + + + + + &Room + + + + + &Leave room + + + + + You are flooding the chat. Please wait a couple of seconds. + + + + + TabServer + + + Server + + + + + TabUserLists + + + User lists + + + + + UserInfoBox + + + User information + + + + + Real name: + + + + + Location: + + + + + User level: + + + + + Administrator + + + + + Judge + + + + + Registered user + + + + + Unregistered user + + + + + UserInterfaceSettingsPage + + + General interface settings + + + + + &Double-click cards to play them (instead of single-click) + + + + + Animation settings + + + + + &Tap/untap animation + + + + + UserList + + + Users online: %1 + + + + + Users in this room: %1 + + + + + Buddies online: %1 / %2 + + + + + Ignored users online: %1 / %2 + + + + + User &details + + + + + Direct &chat + + + + + Add to &buddy list + + + + + Remove from &buddy list + + + + + Add to &ignore list + + + + + Remove from &ignore list + + + + + Ban from &server + + + + + Duration + + + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + + + + + WndDeckEditor + + + &Search... + + + + + &Clear search + + + + + &Search for: + + + + + Deck &name: + + + + + &Comments: + + + + + Deck editor [*] + + + + + &New deck + + + + + &Load deck... + + + + + &Save deck + + + + + Save deck &as... + + + + + Load deck from cl&ipboard... + + + + + Save deck to clip&board + + + + + &Print deck... + + + + + &Close + + + + + Ctrl+Q + + + + + &Edit sets... + + + + + &Deck + + + + + &Card database + + + + + Add card to &maindeck + + + + + Return + + + + + Enter + + + + + Add card to &sideboard + + + + + Ctrl+Return + + + + + Ctrl+Enter + + + + + &Remove row + + + + + Del + + + + + &Increment number + + + + + + + + + + + &Decrement number + + + + + - + + + + + Are you sure? + + + + + The decklist has been modified. +Do you want to save the changes? + + + + + Load deck + + + + + + Error + + + + + + The deck could not be saved. +Please check that the directory is writable and try again. + + + + + Save deck + + + + + WndSets + + + Edit sets + + + + + ZoneViewWidget + + + sort by name + + + + + sort by type + + + + + shuffle when closing + + + + From 773f4dd61322846c0dd017ff6d6607691d4b0278 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 21 Apr 2011 17:18:03 +0200 Subject: [PATCH 29/87] added id_server to servermessages table --- servatrice/servatrice.sql | 1 + servatrice/src/servatrice.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index f35b1d9f8..203941a9a 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -126,6 +126,7 @@ CREATE TABLE `cockatrice_uptime` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE `cockatrice_servermessages` ( + `id_server` tinyint(3) not null default 0, `timest` datetime NOT NULL default '0000-00-00 00:00:00', `message` text, PRIMARY KEY (`timest`) diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 3e36a808c..c31b0a441 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -333,7 +333,8 @@ void Servatrice::updateLoginMessage() QMutexLocker locker(&dbMutex); checkSql(); QSqlQuery query; - query.prepare("select message from " + dbPrefix + "_servermessages order by timest desc limit 1"); + query.prepare("select message from " + dbPrefix + "_servermessages where id_server = :id_server order by timest desc limit 1"); + query.bindValue(":id_server", serverId); if (execSqlQuery(query)) if (query.next()) { loginMessage = query.value(0).toString(); From ed719090af3ebd92b3efb66ddefef309fd53d97c Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 30 Apr 2011 03:08:45 +0200 Subject: [PATCH 30/87] added NPH to sets, added Belarus to countries --- cockatrice/cockatrice.qrc | 1 + cockatrice/resources/countries/by.svg | 7 +++++++ oracle/sets.xml | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 cockatrice/resources/countries/by.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index a36e8e317..3c14afd1c 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -50,6 +50,7 @@ resources/countries/au.svg resources/countries/be.svg resources/countries/br.svg + resources/countries/by.svg resources/countries/ca.svg resources/countries/ch.svg resources/countries/cn.svg diff --git a/cockatrice/resources/countries/by.svg b/cockatrice/resources/countries/by.svg new file mode 100644 index 000000000..bb1dfa789 --- /dev/null +++ b/cockatrice/resources/countries/by.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/oracle/sets.xml b/oracle/sets.xml index ab9302f2b..8ebabb9ba 100644 --- a/oracle/sets.xml +++ b/oracle/sets.xml @@ -196,6 +196,10 @@ NE Nemesis + + NPH + New Phyrexia + 9E Ninth Edition From 5fa2f019d09d08fc73a9c604f82390942c3ceb43 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 1 May 2011 14:58:36 +0200 Subject: [PATCH 31/87] added SK and CZ flags --- cockatrice/cockatrice.qrc | 2 ++ cockatrice/resources/countries/cz.svg | 11 +++++++++++ cockatrice/resources/countries/sk.svg | 12 ++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 cockatrice/resources/countries/cz.svg create mode 100644 cockatrice/resources/countries/sk.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 3c14afd1c..dcb497f71 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -52,6 +52,7 @@ resources/countries/br.svg resources/countries/by.svg resources/countries/ca.svg + resources/countries/cz.svg resources/countries/ch.svg resources/countries/cn.svg resources/countries/de.svg @@ -73,6 +74,7 @@ resources/countries/pt.svg resources/countries/ru.svg resources/countries/se.svg + resources/countries/sk.svg resources/countries/tr.svg resources/countries/ua.svg resources/countries/uk.svg diff --git a/cockatrice/resources/countries/cz.svg b/cockatrice/resources/countries/cz.svg new file mode 100644 index 000000000..51bf4fb7e --- /dev/null +++ b/cockatrice/resources/countries/cz.svg @@ -0,0 +1,11 @@ + + + + +Flag of the Czech Republic + + + + diff --git a/cockatrice/resources/countries/sk.svg b/cockatrice/resources/countries/sk.svg new file mode 100644 index 000000000..3b4e666a3 --- /dev/null +++ b/cockatrice/resources/countries/sk.svg @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file From 461a62e0c85233a714b896c692d6716319ccc9fe Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 8 May 2011 17:56:52 +0200 Subject: [PATCH 32/87] LocalServer crash fix --- cockatrice/src/localserver.cpp | 1 + common/server.cpp | 10 ++++++++++ common/server.h | 1 + common/server_protocolhandler.cpp | 1 + common/server_room.cpp | 13 +++++++++++++ common/server_room.h | 1 + servatrice/src/servatrice.cpp | 1 + 7 files changed, 28 insertions(+) diff --git a/cockatrice/src/localserver.cpp b/cockatrice/src/localserver.cpp index 4cadbdf31..2793a28e2 100644 --- a/cockatrice/src/localserver.cpp +++ b/cockatrice/src/localserver.cpp @@ -10,6 +10,7 @@ LocalServer::LocalServer(QObject *parent) LocalServer::~LocalServer() { + prepareDestroy(); } LocalServerInterface *LocalServer::newConnection() diff --git a/common/server.cpp b/common/server.cpp index 67e1172a7..a7e4c683a 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -32,8 +32,18 @@ Server::Server(QObject *parent) Server::~Server() { +} + +void Server::prepareDestroy() +{ + QMutexLocker locker(&serverMutex); + while (!clients.isEmpty()) delete clients.takeFirst(); + + QMapIterator roomIterator(rooms); + while (roomIterator.hasNext()) + delete roomIterator.next().value(); } AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString &name, const QString &password) diff --git a/common/server.h b/common/server.h index e401ca806..1c35f5a1b 100644 --- a/common/server.h +++ b/common/server.h @@ -45,6 +45,7 @@ public: virtual QMap getIgnoreList(const QString &name) = 0; virtual bool getUserBanned(Server_ProtocolHandler * /*client*/, const QString & /*userName*/) const { return false; } protected: + void prepareDestroy(); QList clients; QMap users; QMap rooms; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 70e8c1eb6..dd5d0dd8f 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -29,6 +29,7 @@ Server_ProtocolHandler::~Server_ProtocolHandler() void Server_ProtocolHandler::prepareDestroy() { QMutexLocker locker(&server->serverMutex); + qDebug("Server_ProtocolHandler::prepareDestroy"); server->removeClient(this); diff --git a/common/server_room.cpp b/common/server_room.cpp index 75aa10edd..b954fa81c 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -8,6 +8,19 @@ Server_Room::Server_Room(int _id, const QString &_name, const QString &_descript { } +Server_Room::~Server_Room() +{ + QMutexLocker locker(&roomMutex); + qDebug("Server_Room destructor"); + + const QList gameList = games.values(); + for (int i = 0; i < gameList.size(); ++i) + delete gameList[i]; + games.clear(); + + clear(); +} + Server *Server_Room::getServer() const { return static_cast(parent()); diff --git a/common/server_room.h b/common/server_room.h index e5f4867c4..b99b626f2 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -29,6 +29,7 @@ private: public: mutable QMutex roomMutex; Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent); + ~Server_Room(); int getId() const { return id; } QString getName() const { return name; } QString getDescription() const { return description; } diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index c31b0a441..6346e0e9c 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -107,6 +107,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) Servatrice::~Servatrice() { + prepareDestroy(); } bool Servatrice::openDatabase() From bd5a687816da4541ecf739d59bffa50fbbbafe26 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 10 May 2011 04:06:54 +0200 Subject: [PATCH 33/87] added SG and ZA to countries --- cockatrice/cockatrice.qrc | 2 ++ cockatrice/resources/countries/sg.svg | 12 ++++++++++++ cockatrice/resources/countries/za.svg | 13 +++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 cockatrice/resources/countries/sg.svg create mode 100644 cockatrice/resources/countries/za.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index dcb497f71..6363dc665 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -74,11 +74,13 @@ resources/countries/pt.svg resources/countries/ru.svg resources/countries/se.svg + resources/countries/sg.svg resources/countries/sk.svg resources/countries/tr.svg resources/countries/ua.svg resources/countries/uk.svg resources/countries/us.svg + resources/countries/za.svg resources/counters/w.svg resources/counters/w_highlight.svg diff --git a/cockatrice/resources/countries/sg.svg b/cockatrice/resources/countries/sg.svg new file mode 100644 index 000000000..572cb3b1b --- /dev/null +++ b/cockatrice/resources/countries/sg.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/cockatrice/resources/countries/za.svg b/cockatrice/resources/countries/za.svg new file mode 100644 index 000000000..ccfe132f5 --- /dev/null +++ b/cockatrice/resources/countries/za.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 731d6bc4d165d1779557274b6ab114cc0f5c078a Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 16 May 2011 14:28:45 +0200 Subject: [PATCH 34/87] added flags for Malaysia and Romania --- cockatrice/cockatrice.qrc | 2 ++ cockatrice/resources/countries/my.svg | 15 +++++++++++++++ cockatrice/resources/countries/ro.svg | 5 +++++ 3 files changed, 22 insertions(+) create mode 100644 cockatrice/resources/countries/my.svg create mode 100644 cockatrice/resources/countries/ro.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 6363dc665..d57e461e4 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -67,11 +67,13 @@ resources/countries/it.svg resources/countries/jp.svg resources/countries/mx.svg + resources/countries/my.svg resources/countries/nl.svg resources/countries/no.svg resources/countries/ph.svg resources/countries/pl.svg resources/countries/pt.svg + resources/countries/ro.svg resources/countries/ru.svg resources/countries/se.svg resources/countries/sg.svg diff --git a/cockatrice/resources/countries/my.svg b/cockatrice/resources/countries/my.svg new file mode 100644 index 000000000..988b507b7 --- /dev/null +++ b/cockatrice/resources/countries/my.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/countries/ro.svg b/cockatrice/resources/countries/ro.svg new file mode 100644 index 000000000..c9b6da860 --- /dev/null +++ b/cockatrice/resources/countries/ro.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From 19ae32f3305a98dcd938d49c91c26161819aad57 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 21 May 2011 19:39:08 +0200 Subject: [PATCH 35/87] lupdate --- cockatrice/translations/cockatrice_de.ts | 335 ++++++++++---------- cockatrice/translations/cockatrice_en.ts | 335 ++++++++++---------- cockatrice/translations/cockatrice_es.ts | 335 ++++++++++---------- cockatrice/translations/cockatrice_fr.ts | 335 ++++++++++---------- cockatrice/translations/cockatrice_ja.ts | 335 ++++++++++---------- cockatrice/translations/cockatrice_pt-br.ts | 335 ++++++++++---------- cockatrice/translations/cockatrice_pt.ts | 335 ++++++++++---------- cockatrice/translations/cockatrice_ru.ts | 335 ++++++++++---------- 8 files changed, 1360 insertions(+), 1320 deletions(-) diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index ebf01d7f8..993c17877 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -187,22 +187,22 @@ CardInfoWidget - + Name: Name: - + Mana cost: Manakosten: - + Card type: Kartentyp: - + P / T: S/W: @@ -841,22 +841,22 @@ DeckViewContainer - + Load &local deck &Lokales Deck laden - + Load d&eck from server Deck vom Server l&aden - + Ready to s&tart Bereit zum S&tarten - + Load deck Deck laden @@ -1533,23 +1533,23 @@ GameSelector - + C&reate Spiel e&rstellen - + &Join &Teilnehmen - + Error Fehler @@ -1558,57 +1558,57 @@ XXX - + Wrong password. Falsches Passwort. - + Spectators are not allowed in this game. In diesem Spiel sind keine Zuschauer zugelassen. - + The game is already full. Das Spiel ist bereits voll. - + The game does not exist any more. Dieses Spiel gibt es nicht mehr. - + This game is only open to registered users. Dieses Spiel kann nur von registrierten Benutzern betreten werden. - + This game is only open to its creator's buddies. Dieses Spiel kann nur von Freunden des Erstellers betreten werden. - + You are being ignored by the creator of this game. Der Ersteller dieses Spiels ignoriert Sie. - + Join game Spiel beitreten - + Password: Passwort: - + Games Spiele - + Show &full games &Volle Spiele anzeigen @@ -1617,7 +1617,7 @@ &Volle Spiele anzeigen - + J&oin as spectator &Zuschauen @@ -2898,21 +2898,21 @@ Lokale Version ist %1, Serverversion ist %2. Player - - - + + + Move to &top of library Oben auf die Biblio&thek legen - - - + + + Move to &bottom of library Unter die &Bibliothek legen - + &View library &Zeige Bibliothek @@ -2921,37 +2921,37 @@ Lokale Version ist %1, Serverversion ist %2. Oberste Karten in den F&riedhof legen... - + Move top cards to &exile... Oberste Karten ins &Exil schicken... - + F3 F3 - + View &top cards of library... Zeige die oberen Kar&ten der Bibliothek... - + &View graveyard &Zeige Friedhof - + &All players &allen Spielern - + Ctrl+F3 Ctrl+F3 - + F4 F4 @@ -2960,73 +2960,73 @@ Lokale Version ist %1, Serverversion ist %2. Zeige ent&fernte Karten - + &View sideboard Zeige &Sideboard - + Player "%1" Spieler "%1" - - + + Move to &graveyard Auf den &Friedhof legen - + Reveal &library to &Bibliothek jemandem zeigen - + Reveal t&op card to &Oberste Karte jemandem zeigen - + &Undo last draw Zuletzt gezogene Karte zur&ücklegen - + Take &mulligan &Mulligan nehmen - + Move top cards to &graveyard... Oberste Karten auf den F&riedhof legen... - + Put top card on &bottom Oberste Karte nach &unten legen - + &Hand &Hand - + &Reveal to Jemandem &zeigen - + Reveal r&andom card to Z&ufällige Karte jemandem zeigen - + &Library Bib&liothek - + &Graveyard &Friedhof @@ -3035,7 +3035,7 @@ Lokale Version ist %1, Serverversion ist %2. Entfe&rnte Karten - + &Sideboard &Sideboard @@ -3048,33 +3048,33 @@ Lokale Version ist %1, Serverversion ist %2. &Hinweis setzen... - + View top cards of library Zeige die obersten Karten der Bibliothek - + Number of cards: Anzahl der Karten: - + &Draw card Karte &ziehen - + &View exile &Zeige Exil - + &Exile &Exil - - + + Move to &hand auf die &Hand nehmen @@ -3083,28 +3083,28 @@ Lokale Version ist %1, Serverversion ist %2. auf den &Friedhof legen - - + + Move to &exile ins &Exil schicken - + Ctrl+W Ctrl+W - + Ctrl+D Ctrl+D - + D&raw cards... Ka&rten ziehen... - + Ctrl+E Ctrl+E @@ -3113,37 +3113,37 @@ Lokale Version ist %1, Serverversion ist %2. &Mulligan nehmen... - + Ctrl+M Ctrl+M - + &Shuffle Mi&schen - + Ctrl+S Ctrl+S - + &Counters &Zähler - + &Untap all permanents &Enttappe alle bleibenden Karten - + Ctrl+Shift+D Ctrl+Shift+D - + Ctrl+U Ctrl+U @@ -3172,42 +3172,42 @@ Lokale Version ist %1, Serverversion ist %2. Ctrl+L - + R&oll die... &Würfeln... - + Ctrl+I Ctrl+I - + &Create token... Spiels&tein erstellen... - + Ctrl+T Ctrl+T - + C&reate another token &Noch einen Spielstein erstellen - + Ctrl+G Ctrl+G - + S&ay S&agen - + C&ard &Karte @@ -3300,50 +3300,50 @@ Lokale Version ist %1, Serverversion ist %2. F10 - + Draw cards Karten ziehen - - - - + + + + Number: Anzahl: - + Move top cards to grave Oberste Karten in den Friedhof legen - + Move top cards to exile Oberste Karten ins Exil schicken - + Set power/toughness Kampfwerte setzen - + Please enter the new PT: Bitte die neuen Kampfwerte eingeben: - + Set annotation Hinweis setzen - + Please enter the new annotation: Bitte den Hinweis eingeben: - + Set counters Setze Zählmarken @@ -3356,12 +3356,12 @@ Lokale Version ist %1, Serverversion ist %2. Neue Lebenspunkte insgesamt: - + Roll die Würfeln - + Number of sides: Anzahl der Seiten: @@ -3689,102 +3689,107 @@ Bitte geben Sie einen Namen ein: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases &Phasen - + &Game Spi&el - + Next &phase Nächste &Phase - + Ctrl+Space Ctrl+Space - + Next &turn Nächster &Zug - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Lokale Pfeile entfernen - + Ctrl+R Ctrl+R - + &Concede - + F2 F2 - + &Leave game Spiel ver&lassen - + + Ctrl+Q + Ctrl+Q + + + Kicked Herausgeworfen - + You have been kicked out of the game. Sie wurden aus dem Spiel geworfen. @@ -3805,7 +3810,7 @@ Bitte geben Sie einen Namen ein: Spiel s&tarten - + &Say: &Sagen: @@ -3818,22 +3823,22 @@ Bitte geben Sie einen Namen ein: Esc - + Concede Aufgeben - + Are you sure you want to concede this game? Sind Sie sicher, dass Sie das Spiel aufgeben möchten? - + Leave game Spiel verlassen - + Are you sure you want to leave this game? Sind Sie sicher, dass Sie das Spiel verlassen möchten? @@ -3842,7 +3847,7 @@ Bitte geben Sie einen Namen ein: Deck laden - + Game %1: %2 Spiel %1: %2 @@ -3860,22 +3865,22 @@ Bitte geben Sie einen Namen ein: Ver&lassen - + This user is ignoring you. Dieser Benutzer ignoriert Sie. - + %1 has left the server. %1 hat den Server verlassen. - + %1 has joined the server. %1 hat den Server betreten. - + Talking to %1 Gespräch mit %1 @@ -3883,27 +3888,27 @@ Bitte geben Sie einen Namen ein: TabRoom - + &Say: &Sagen: - + Chat Unterhaltung - + &Room &Raum - + &Leave room Raum ver&lassen - + You are flooding the chat. Please wait a couple of seconds. Sie überfluten den Chatraum. Bitte warten Sie ein paar Sekunden. @@ -4091,32 +4096,32 @@ Geben Sie 0 ein für einen unbefristeten Bann. &Suchen nach: - + Deck &name: Deck &Name: - + &Comments: &Kommentare: - + Deck editor [*] Deck-Editor [*] - + &New deck &Neues Deck - + &Load deck... Deck &laden... - + &Save deck Deck &speichern @@ -4125,37 +4130,37 @@ Geben Sie 0 ein für einen unbefristeten Bann. Deck &speichern unter... - + Save deck &as... Deck s&peichern unter... - + Save deck to clip&board Deck in Z&wischenablage speichern - + &Print deck... Deck &drucken... - + &Close S&chließen - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editionen bearbeiten... - + &Deck &Deck @@ -4164,27 +4169,27 @@ Geben Sie 0 ein für einen unbefristeten Bann. &Editionen - + Add card to &maindeck Karte zu&m Hauptdeck hinzufügen - + Return Return - + Enter Enter - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter @@ -4193,7 +4198,7 @@ Geben Sie 0 ein für einen unbefristeten Bann. Ctrl+M - + Add card to &sideboard Karte zum &Sideboard hinzufügen @@ -4212,78 +4217,78 @@ Geben Sie 0 ein für einen unbefristeten Bann. Suche a&ufheben - + Load deck from cl&ipboard... Deck aus &Zwischenablage laden... - + &Card database &Kartendatenbank - + &Remove row Zeile entfe&rnen - + Del Entf - + &Increment number Anzahl er&höhen - + + + - + &Decrement number Anzahl v&erringern - + - - - + Are you sure? Bist du sicher? - + The decklist has been modified. Do you want to save the changes? Die Deckliste wurde verändert. Willst du die Änderungen speichern? - + Load deck Deck laden - - + + Error Fehler - - + + The deck could not be saved. Please check that the directory is writable and try again. Das Deck konnte nicht gespeichert werden. Bitte überprüfen Sie, dass Sie Schreibrechte in dem Verzeichnis haben, und versuchen Sie es erneut. - + Save deck Deck speichern diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index f4912678f..e80e16593 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -152,22 +152,22 @@ CardInfoWidget - + Name: - + Mana cost: - + Card type: - + P / T: @@ -569,22 +569,22 @@ DeckViewContainer - + Load &local deck - + Load d&eck from server - + Ready to s&tart - + Load deck @@ -945,83 +945,83 @@ GameSelector - + C&reate - + &Join - + Error - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + J&oin as spectator @@ -1946,322 +1946,322 @@ Local version is %1, remote version is %2. Player - - - + + + Move to &top of library - - - + + + Move to &bottom of library - - + + Move to &graveyard - + &View library - + Reveal &library to - + Reveal t&op card to - + Move top cards to &graveyard... - + F3 - + View &top cards of library... - + &View graveyard - + F4 - + &View sideboard - + Player "%1" - + &Hand - + &Library - + &Graveyard - + &Sideboard - + View top cards of library - + Number of cards: - + &Draw card - + &View exile - + &Exile - - + + Move to &hand - - + + Move to &exile - + Ctrl+W - + Ctrl+D - + D&raw cards... - + Ctrl+E - + Take &mulligan - + Ctrl+M - + &Shuffle - + Ctrl+S - + &Counters - + &Untap all permanents - + Ctrl+U - + R&oll die... - + Ctrl+I - + &Create token... - + Ctrl+T - + C&reate another token - + Ctrl+G - + S&ay - + &Undo last draw - + Move top cards to &exile... - + Put top card on &bottom - + &Reveal to - + Reveal r&andom card to - + C&ard - + &All players - + Ctrl+F3 - + Ctrl+Shift+D - + Draw cards - - - - + + + + Number: - + Move top cards to grave - + Move top cards to exile - + Roll die - + Number of sides: - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -2514,132 +2514,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases - + &Game - + Next &phase - + Ctrl+Space - + Next &turn - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows - + Ctrl+R - + &Concede - + F2 - + &Leave game - + + Ctrl+Q + + + + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + Kicked - + You have been kicked out of the game. - + Game %1: %2 @@ -2657,22 +2662,22 @@ Please enter a name: - + This user is ignoring you. - + %1 has left the server. - + %1 has joined the server. - + Talking to %1 @@ -2680,27 +2685,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -2864,125 +2869,125 @@ Enter 0 for an indefinite ban. - + Deck &name: - + &Comments: - + Deck editor [*] - + &New deck - + &Load deck... - + Load deck from cl&ipboard... - + &Save deck - + Save deck &as... - + Save deck to clip&board - + &Print deck... - + &Close - + Ctrl+Q - + &Edit sets... - + &Deck - + Load deck - - + + Error - - + + The deck could not be saved. Please check that the directory is writable and try again. - + Save deck - + Add card to &maindeck - + Return - + Enter - + Ctrl+Return - + Ctrl+Enter - + Add card to &sideboard @@ -2997,47 +3002,47 @@ Please check that the directory is writable and try again. - + &Card database - + &Remove row - + Del - + &Increment number - + + - + &Decrement number - + - - + Are you sure? - + The decklist has been modified. Do you want to save the changes? diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 38b6ee326..7bd5eaf02 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -160,22 +160,22 @@ CardInfoWidget - + Name: Nombre: - + Mana cost: Coste de mana: - + Card type: Tipo de carta: - + P / T: F / R: @@ -761,22 +761,22 @@ DeckViewContainer - + Load &local deck Cargar mazo &local - + Load d&eck from server Cargar mazo del &servidor - + Ready to s&tart Listo para &empezar - + Load deck Cargar mazo @@ -1156,78 +1156,78 @@ GameSelector - + C&reate C&rear - + &Join E&ntrar - + Error Error - + Wrong password. Contraseña incorrecta. - + Spectators are not allowed in this game. No se permiten espectadores en esta partida. - + The game is already full. La partida no tiene plazas libres. - + The game does not exist any more. La partida ya no existe. - + This game is only open to registered users. Esta partida está abierta sólo a usuarios registrados. - + This game is only open to its creator's buddies. Esta partida está abierta sólo a los amigos del creador. - + You are being ignored by the creator of this game. Estas siendo ignorado por el creador de la partida. - + Join game Entrar en la partida - + Password: Contraseña: - + Games Partidas - + Show &full games Ver partidas &sin plazas libres @@ -1236,7 +1236,7 @@ &Ver partidas sin plazas libres - + J&oin as spectator Entrar como e&spectador @@ -2177,128 +2177,128 @@ La versión local es %1, la versión remota es %2. Player - - - + + + Move to &top of library Mover a la &parte superior de la biblioteca - - - + + + Move to &bottom of library Mover al &fondo de la biblioteca - - + + Move to &graveyard Mover al &cementerio - + &View library &Ver biblioteca - + Reveal &library to Revelar &biblioteca a - + Reveal t&op card to Revelar la carta &superior de la biblioteca a - + &Undo last draw &Deshacer último robo - + Move top cards to &graveyard... Mover cartas de la parte s&uperior de la biblioteca al cementerio... - + F3 F3 - + View &top cards of library... Ver cartas de la parte &superior de la biblioteca... - + &View graveyard Ver &Cementerio - + F4 F4 - + &View sideboard Ver &sideboard - + Player "%1" Jugador "%1" - + &Hand &Mano - + &Library &Biblioteca - + &Graveyard &Cementerio - + &Sideboard &Reserva - + View top cards of library Ver cartas de la parte superior de la biblioteca - + Number of cards: Número de cartas: - + &Draw card &Robar carta - + &View exile Ver &exilio - + &Exile &Exilio - - + + Move to &hand Mover a la m&ano @@ -2307,98 +2307,98 @@ La versión local es %1, la versión remota es %2. Mover al &cementerio - - + + Move to &exile Mover al &exilio - + Ctrl+W Ctrl+W - + Ctrl+D Ctrl+D - + D&raw cards... &Robar cartas... - + Ctrl+E Ctrl+E - + Take &mulligan Hacer &mulligan - + Ctrl+M Ctrl+M - + &Shuffle &Barajar - + Ctrl+S Ctrl+S - + &Counters &Contadores - + &Untap all permanents &Enderezar todos los permanentes - + Ctrl+U Ctrl+U - + R&oll die... &Lanzar dado... - + Ctrl+I Ctrl+I - + &Create token... Crear &Ficha... - + Ctrl+T Ctrl+T - + C&reate another token C&rea otra ficha - + Ctrl+G Ctrl+G - + S&ay D&ecir @@ -2407,100 +2407,100 @@ La versión local es %1, la versión remota es %2. Mover cartas superiores al ce&menterio... - + Move top cards to &exile... Mover cartas superiores al &exilio... - + Put top card on &bottom Poner carta superior en la parte &inferior - + &Reveal to &Revelar a - + Reveal r&andom card to Revelar carta &aleatoriamente a - + C&ard C&arta - + &All players &Todos los jugadores - + Ctrl+F3 Ctrl+F3 - + Ctrl+Shift+D Ctrl+Shift+D - + Draw cards Robar cartas - - - - + + + + Number: Número: - + Move top cards to grave Mover cartas superiores al cementerio - + Move top cards to exile Mover cartas superiores al exilio - + Roll die Lanzar dado - + Number of sides: Número de caras: - + Set power/toughness Establecer fuerza/resistencia - + Please enter the new PT: Por favor, introduzca la nueva F/R: - + Set annotation Escribir anotación - + Please enter the new annotation: Por favor, introduza la nueva anotación: - + Set counters Establecer contadores @@ -2808,132 +2808,137 @@ Por favor, introduzca un nombre: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases &Fases - + &Game &Partida - + Next &phase Próxima &fase - + Ctrl+Space Ctrl+Space - + Next &turn Próximo &turno - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Retirar todas las flechas locales - + Ctrl+R Ctrl+R - + &Concede &Conceder - + F2 F2 - + &Leave game &Abandonar la partida - + + Ctrl+Q + Ctrl+Q + + + &Say: &Decir: - + Concede Conceder - + Are you sure you want to concede this game? ¿Estás seguro de que quieres conceder esta partida? - + Leave game Abandonar la partida - + Are you sure you want to leave this game? ¿Estás seguro de que quieres abandonar la partida? - + Kicked Expulsado - + You have been kicked out of the game. Has sido expulsado de la partida. - + Game %1: %2 Partida %1: %2 @@ -2951,22 +2956,22 @@ Por favor, introduzca un nombre: &Cerrar - + This user is ignoring you. Este usuario está ignorandote. - + %1 has left the server. %1 ha abandonado el servidor. - + %1 has joined the server. %1 se ha unido al servidor. - + Talking to %1 Hablando con %1 @@ -2974,27 +2979,27 @@ Por favor, introduzca un nombre: TabRoom - + &Say: &Decir: - + Chat Chat - + &Room &Sala - + &Leave room &Dejar sala - + You are flooding the chat. Please wait a couple of seconds. Estás floodeando el chat. Por favor, espera unos segundos. @@ -3167,126 +3172,126 @@ Indica 0 para un ban indefinido. &Buscar por: - + Deck &name: &Nombre del mazo: - + &Comments: &Comentarios: - + Deck editor [*] Editor de mazos [*] - + &New deck &Nuevo mazo - + &Load deck... &Cargar mazo... - + Load deck from cl&ipboard... Cargar mazo del &portapapeles... - + &Save deck &Guardar mazo - + Save deck &as... Guardar mazo &como... - + Save deck to clip&board Guardar mazo al p&ortapales - + &Print deck... Im&primir mazo... - + &Close &Cerrar - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editar ediciones... - + &Deck &Mazo - + Load deck Cargar mazo - - + + Error Error - - + + The deck could not be saved. Please check that the directory is writable and try again. El mazo no puede guardarse Por favor, compruebe que tiene permisos de escritura en el directorio e intentelo de nuevo. - + Save deck Guardar mazo - + Add card to &maindeck Añadir carta al &mazo principal - + Return Return - + Enter Enter - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + Add card to &sideboard Añadir carta a la &reserva @@ -3301,47 +3306,47 @@ Por favor, compruebe que tiene permisos de escritura en el directorio e intentel &Limpiar busqueda - + &Card database &Base de datos de cartas - + &Remove row &Eliminar columna - + Del Del - + &Increment number &Incrementar número - + + + - + &Decrement number &Decrementar número - + - - - + Are you sure? ¿Estás seguro? - + The decklist has been modified. Do you want to save the changes? La lista del mazo ha sido modificada diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index e8ab3fdd0..f78ae31e8 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -152,22 +152,22 @@ CardInfoWidget - + Name: Nom: - + Mana cost: Cout de mana: - + Card type: Type de carte: - + P / T: F / E: @@ -623,22 +623,22 @@ DeckViewContainer - + Load &local deck Charger un deck &local - + Load d&eck from server Charger un d&eck depuis le serveur - + Ready to s&tart P&rêt à démarrer - + Load deck Charger deck @@ -1006,68 +1006,68 @@ GameSelector - + Error Erreur - + Wrong password. Mot de passe erroné. - + Spectators are not allowed in this game. Les spectateurs ne sont pas autorisés dans cette partie. - + The game is already full. Cette partie est déjà pleine. - + The game does not exist any more. La partie n'existe plus. - + This game is only open to registered users. Cette partie n'est accessible qu'aux joueurs enregistrés. - + This game is only open to its creator's buddies. Cette partie n'est accessible qu'aux amis. - + You are being ignored by the creator of this game. Vous avez été ignoré par le créateur de la partie. - + Join game Rejoindre partie - + Password: Mot de passe: - + Games Parties - + Show &full games Montrer &toutes les parties @@ -1077,17 +1077,17 @@ &Montrer toutes les parties - + C&reate C&réer - + &Join Re&joindre - + J&oin as spectator Rej&oindre en tant que spectateur @@ -2050,323 +2050,323 @@ La version la plus récente est %1, l'ancienne version est %2. Player - + &View graveyard &Voir le cimetière - + &View exile &Voir la zone exil - + Player "%1" Joueur "%1" - + &Graveyard &Cimetière - + &Exile &Exil - - - + + + Move to &top of library Mettre au-dess&us de sa bibliothèque - - - + + + Move to &bottom of library Mettre en-dess&ous de sa bibliothèque - - + + Move to &graveyard Mettre dans son cime&tière - - + + Move to &exile Déplacer dans la zone &exil - - + + Move to &hand Mettre dans sa &main - + &View library &Voir la bibliothèque - + View &top cards of library... Voir les cartes du &dessus de la bibliothèque... - + Reveal &library to Révéler la &bibliothèque à - + Reveal t&op card to Révéler la carte du &dessus à - + &View sideboard &Voir la réserve - + &Draw card &Piocher une carte - + D&raw cards... P&iocher plusieurs cartes... - + &Undo last draw Annu&ler dernière pioche - + Take &mulligan &Mulliganer - + &Shuffle Mél&anger - + Move top cards to &graveyard... Déplacer les cartes du dessus vers le &cimetière... - + Move top cards to &exile... Déplacer les cartes du dessus vers la zone &exil... - + Put top card on &bottom Mettre la carte du dessus en &dessous - + &Hand &Main - + &Reveal to &Révéler à - + Reveal r&andom card to Révéler une carte au &hasard à - + &Sideboard Ré&serve - + &Library &Bibliothèque - + &Counters Mar&queurs - + &Untap all permanents Dé&gager tous les permanents - + R&oll die... Lancer un &dé... - + &Create token... &Créer un jeton... - + C&reate another token C&réer un autre jeton - + S&ay D&ire - + C&ard C&arte - + &All players &Tous les joueurs - + Ctrl+F3 Ctrl+F3 - + F3 F3 - + Ctrl+W Ctrl+W - + F4 F4 - + Ctrl+D Ctrl+D - + Ctrl+E Ctrl+E - + Ctrl+Shift+D Ctrl+Shift+D - + Ctrl+M Ctrl+M - + Ctrl+S Ctrl+S - + Ctrl+U Ctrl+U - + Ctrl+I Ctrl+I - + Ctrl+T Ctrl+T - + Ctrl+G Ctrl+G - + View top cards of library Voir les cartes du dessus de la bibliothèque - + Number of cards: Nombre de cartes: - + Draw cards Piocher plusieurs cartes - - - - + + + + Number: Nombre: - + Move top cards to grave Mettre les cartes du dessus dans le cimetière - + Move top cards to exile Mettre les cartes du dessus dans la zone exil - + Roll die Lancer un dé - + Number of sides: Nombre de faces: - + Set power/toughness Fixer force/endurance - + Please enter the new PT: maybe better with / Entrer la nouvelle F/E: - + Set annotation Mettre une note - + Please enter the new annotation: Entrez la nouvelle note: - + Set counters Mettre des marqueurs @@ -2667,132 +2667,137 @@ Entrez un nom s'il vous plaît: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases - + &Game &Partie - + Next &phase &Prochaine phase - + Ctrl+Space Ctrl+Space - + Next &turn Prochain &Tour - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Retirer toutes les flèches locales - + Ctrl+R Ctrl+R - + &Concede &Concéder - + F2 F2 - + &Leave game &Quitter la partie - + + Ctrl+Q + Ctrl+Q + + + &Say: &Dire: - + Concede Concéder - + Are you sure you want to concede this game? Êtes-vous sûr de vouloir concéder la partie? - + Leave game Quitter la partie - + Are you sure you want to leave this game? Êtes-vous sûr de vouloir quitter la partie? - + Kicked Exclu - + You have been kicked out of the game. Vous avez été exclu de la partie. - + Game %1: %2 Partie %1:%2 @@ -2811,22 +2816,22 @@ Entrez un nom s'il vous plaît: &Quitter - + This user is ignoring you. Cet utilisateur vous a ignoré. - + %1 has left the server. %1 a quitté le serveur. - + %1 has joined the server. %1 a rejoint le serveur. - + Talking to %1 Vous parlez à %1 @@ -2834,27 +2839,27 @@ Entrez un nom s'il vous plaît: TabRoom - + &Say: &Dire: - + Chat Chat - + &Room &Salon - + &Leave room &Quitter le salon - + You are flooding the chat. Please wait a couple of seconds. Vous floodez le chat. Veuillez patienter quelques secondes. @@ -3038,175 +3043,175 @@ Entrez 0 pour une durée illimitée du ban. &Rechercher: - + Deck &name: &Nom du deck: - + &Comments: &Commentaires: - + Deck editor [*] Editeur de deck [*] - + &New deck &Nouveau deck - + &Load deck... Char&ger deck... - + &Save deck &Sauvegarder le deck - + Save deck &as... S&auvegarder le deck sous... - + Load deck from cl&ipboard... Charger deck depuis le presse-pap&ier... - + Save deck to clip&board Sauve&garder le deck dans le presse-papier - + &Print deck... Im&primer le deck... - + &Close &Fermer - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editer les editions... - + &Deck &Deck - + &Card database Base de &cartes - + Add card to &maindeck Ajouter carte au &deck - + Return Retour - + Enter Entrer - + Add card to &sideboard Ajouter carte à la ré&serve - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove row &Retirer la ligne - + Del Supprimer - + &Increment number to check &Augmenter quantité - + + + - + &Decrement number to check &Diminuer quantité - + - - - + Are you sure? Êtes-vous sûr? - + The decklist has been modified. Do you want to save the changes? Le deck a été modifié. Voulez vous enregistrer les modifications? - + Load deck Charger deck - - + + Error Erreur - - + + The deck could not be saved. Please check that the directory is writable and try again. Le deck n'a pas pu être enregistré. Vérifiez que le répertoire ne soit pas en lecture seule et réessayez. - + Save deck Sauvegarder le deck diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index 6ad1942ae..cea482a4d 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -157,22 +157,22 @@ CardInfoWidget - + Name: カード名: - + Mana cost: マナコスト: - + Card type: カードタイプ: - + P / T: @@ -617,22 +617,22 @@ DeckViewContainer - + Load &local deck ローカルからデッキをロード - + Load d&eck from server サーバーからデッキをロード - + Ready to s&tart 開始準備完了 - + Load deck デッキをロード @@ -993,78 +993,78 @@ GameSelector - + C&reate 部屋を作る - + &Join 参加する - + Error エラー - + Wrong password. パスワードが間違っています. - + Spectators are not allowed in this game. この試合は観戦者は許可されていません. - + The game is already full. このゲームはすでに満員です. - + The game does not exist any more. このゲームはもう存在しません. - + This game is only open to registered users. このゲームは登録済みプレイヤーにのみ公開されています. - + This game is only open to its creator's buddies. このゲームは作成者のフレンドのみに公開されています. - + You are being ignored by the creator of this game. あなたはこのゲームの作成者によって拒否されています. - + Join game 参加 - + Password: パスワード: - + Games ゲーム - + Show &full games 全てのゲームを見る @@ -1073,7 +1073,7 @@ 全てのゲームを見る - + J&oin as spectator 観戦者として参加 @@ -1995,322 +1995,322 @@ Local version is %1, remote version is %2. Player - - - + + + Move to &top of library ライブラリーの一番上へ移動 - - - + + + Move to &bottom of library ライブラリーの一番下へ移動 - - + + Move to &graveyard 墓地へ移動 - + &View library ライブラリーを見る - + Reveal &library to ライブラリーを公開する - + Reveal t&op card to 一番上のカードを公開する - + Move top cards to &graveyard... カードを上から墓地へ置く... - + F3 - + View &top cards of library... ライブラリーのカードを上からX枚見る - + &View graveyard 墓地を見る - + F4 - + &View sideboard サイドボードを見る - + Player "%1" プレイヤー "%1" - + &Hand 手札 - + &Library ライブラリー - + &Graveyard 墓地 - + &Sideboard サイドボード - + View top cards of library ライブラリーのカードを上からX枚見る - + Number of cards: カードの枚数: - + &Draw card カードを引く - + &View exile 追放領域を見る - + &Exile 追放領域 - - + + Move to &hand 手札に移動する - - + + Move to &exile 追放領域へ移動する - + Ctrl+W - + Ctrl+D - + D&raw cards... カードをX枚引く - + Ctrl+E - + Take &mulligan マリガンする - + Ctrl+M - + &Shuffle シャッフル - + Ctrl+S - + &Counters カウンター - + &Untap all permanents 全てのパーマネントをアンタップする - + Ctrl+U - + R&oll die... X面ダイスを振る - + Ctrl+I - + &Create token... トークンを作成する - + Ctrl+T - + C&reate another token 同じトークンを作成する - + Ctrl+G - + S&ay 発言する - + &Undo last draw 最後のドローを取り消す - + Move top cards to &exile... ライブラリーの一番上からX枚追放する - + Put top card on &bottom 一番上のカードを一番下に置く - + &Reveal to 公開する - + Reveal r&andom card to ランダムに公開する - + C&ard カード - + &All players 全てのプレイヤー - + Ctrl+F3 - + Ctrl+Shift+D - + Draw cards カードを引く - - - - + + + + Number: 枚数 - + Move top cards to grave ライブラリーのトップからX枚墓地へ置く - + Move top cards to exile ライブラリーのトップからX枚追放領域へ置く - + Roll die ダイスを振る - + Number of sides: 面の数: - + Set power/toughness パワーとタフネスを設定する - + Please enter the new PT: 新しいP/Tを入力してください - + Set annotation 補足を付ける - + Please enter the new annotation: 新しい補足を付けてください - + Set counters カウンターを設定する @@ -2601,132 +2601,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases フェイズ - + &Game ゲーム - + Next &phase 次のフェイズ - + Ctrl+Space - + Next &turn 次のターン - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows 全ての矢印を消す - + Ctrl+R - + &Concede 投了する - + F2 - + &Leave game ゲームを退出する - + + Ctrl+Q + + + + &Say: 発言する - + Concede 投了する - + Are you sure you want to concede this game? 本当にこのゲームに投了しますか? - + Leave game ゲームから退出する - + Are you sure you want to leave this game? 本当にこのゲームから退出しますか? - + Kicked キック - + You have been kicked out of the game. あなたはこのゲームからキックされました. - + Game %1: %2 ゲーム %1: %2 @@ -2744,22 +2749,22 @@ Please enter a name: 退出する - + This user is ignoring you. このユーザーはあなたを無視しています. - + %1 has left the server. %1はサーバーから退出しました. - + %1 has joined the server. %1がサーバーに参加しました. - + Talking to %1 %1と会話 @@ -2767,27 +2772,27 @@ Please enter a name: TabRoom - + &Say: 発言する - + Chat チャット - + &Room 部屋 - + &Leave room 部屋から出る - + You are flooding the chat. Please wait a couple of seconds. あなたはチャットルームから弾かれました.少々お待ちください. @@ -2959,126 +2964,126 @@ Enter 0 for an indefinite ban. 検索: - + Deck &name: デッキ名: - + &Comments: コメント: - + Deck editor [*] デッキエディター [*] - + &New deck 新しいデッキ - + &Load deck... デッキをロード... - + Load deck from cl&ipboard... クリップボードからデッキをロード... - + &Save deck デッキを保存 - + Save deck &as... 名前を付けてデッキを保存... - + Save deck to clip&board クリップボードにデッキを保存 - + &Print deck... デッキを印刷... - + &Close 閉じる - + Ctrl+Q - + &Edit sets... セットの設定... - + &Deck デッキ - + Load deck デッキをロード - - + + Error エラー - - + + The deck could not be saved. Please check that the directory is writable and try again. 要検証 このデッキは保存されていません. ディレクトリをチェックして再度上書きしてください. - + Save deck デッキを保存 - + Add card to &maindeck メインデッキにカードを加える - + Return - + Enter - + Ctrl+Return - + Ctrl+Enter - + Add card to &sideboard サイドボードにカードを加える @@ -3093,47 +3098,47 @@ Please check that the directory is writable and try again. 検索を解除 - + &Card database カードデータベース - + &Remove row 全て取り除く - + Del - + &Increment number 枚数を増やす - + + - + &Decrement number 枚数を減らす - + - - + Are you sure? 本当によろしいですか? - + The decklist has been modified. Do you want to save the changes? このデッキリストは変更されています.変更を保存しますか? diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index c7d3bb81c..4e9b7d752 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -156,22 +156,22 @@ CardInfoWidget - + Name: Nome: - + Mana cost: Custo de mana: - + Card type: Tipo de card: - + P / T: P / R: @@ -627,22 +627,22 @@ DeckViewContainer - + Load &local deck Carregar dec&k local - + Load d&eck from server Carregar deck do &servidor - + Ready to s&tart &Pronto para começar - + Load deck Carregar deck @@ -1010,78 +1010,78 @@ GameSelector - + C&reate &Criar - + &Join &Entrar - + Error Erro - + Wrong password. Senha incorreta. - + Spectators are not allowed in this game. Não são permitidos visitantes neste jogo. - + The game is already full. O jogo está cheio. - + The game does not exist any more. O jogo não existe mais. - + This game is only open to registered users. Este jogo é aberto apenas para usuários registrados. - + This game is only open to its creator's buddies. Este jogo é aberto apenas para os amigos de quem criou o jogo. - + You are being ignored by the creator of this game. Você está sendo ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Senha: - + Games Jogos - + Show &full games &Mostrar os jogos cheios @@ -1090,7 +1090,7 @@ &Mostrar os jogos cheios - + J&oin as spectator E&ntrar como visitante @@ -2035,322 +2035,322 @@ A versão local é %1 e a versão remota é %2. Player - - - + + + Move to &top of library Mover para o &topo do grimório - - - + + + Move to &bottom of library Mover para o &fundo do grimório - - + + Move to &graveyard Mover para o &cemitério - + &View library &Ver grimório - + Reveal &library to Revelar o &grimório para - + Reveal t&op card to Revelar o card do t&opo para - + Move top cards to &graveyard... Mover os cards do topo para o ce&mitério... - + F3 F3 - + View &top cards of library... Ver os cards do to&po do grimório... - + &View graveyard V&er cemitério - + F4 F4 - + &View sideboard &Ver sideboard - + Player "%1" Jogador "%1" - + &Hand &Mão - + &Library &Grimório - + &Graveyard &Cemitério - + &Sideboard &Sideboard - + View top cards of library Ver os cards do topo do grimório - + Number of cards: Número de cards: - + &Draw card Co&mprar card - + &View exile &Ver exílio - + &Exile &Exílio - - + + Move to &hand Mo&ver para a mão - - + + Move to &exile Mover para o &exílio - + Ctrl+W Ctrl+W - + Ctrl+D Ctrl+D - + D&raw cards... Comprar car&ds... - + Ctrl+E Ctrl+E - + Take &mulligan Pedir mu&lligan - + Ctrl+M Ctrl+M - + &Shuffle &Embaralhar - + Ctrl+S Ctrl+S - + &Counters &Marcadores - + &Untap all permanents Des&virar todos as permanentes - + Ctrl+U Ctrl+U - + R&oll die... &Jogar dado... - + Ctrl+I Ctrl+I - + &Create token... Criar fich&a... - + Ctrl+T Ctrl+T - + C&reate another token Criar &outra ficha - + Ctrl+G Ctrl+G - + S&ay &Falar - + &Undo last draw Desfa&zer última compra - + Move top cards to &exile... Mover os cards do topo para o e&xílio... - + Put top card on &bottom Colocar o card do topo no &fundo - + &Reveal to Re&velar para - + Reveal r&andom card to Revelar card alea&tório para - + C&ard C&ard - + &All players To&dos os jogadores - + Ctrl+F3 Ctrl+F3 - + Ctrl+Shift+D Ctrl+Shift+D - + Draw cards Comprar cards - - - - + + + + Number: Número: - + Move top cards to grave Mover os cards do topo para o cemitério - + Move top cards to exile Mover os cards do topo para o exílio - + Roll die Jogar dado - + Number of sides: Número de lados: - + Set power/toughness Alterar poder/resistência - + Please enter the new PT: Por favor, entre com o novo P/R: - + Set annotation Alterar nota - + Please enter the new annotation: Por favor, entre com a nova nota: - + Set counters Alterar marcadores @@ -2650,132 +2650,137 @@ Por favor, entre um nome: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases &Etapas - + &Game &Jogo - + Next &phase Próxima &etapa - + Ctrl+Space Ctrl+Espaço - + Next &turn Próximo &turno - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Apagar todas as setas locais - + Ctrl+R Ctrl+R - + &Concede &Conceder - + F2 F2 - + &Leave game &Sair do jogo - + + Ctrl+Q + Ctrl+Q + + + &Say: &Falar: - + Concede Conceder - + Are you sure you want to concede this game? Você tem certeza que deseja conceder este jogo? - + Leave game Sair do jogo - + Are you sure you want to leave this game? Você tem certeza que deseja sair deste jogo? - + Kicked Chutado - + You have been kicked out of the game. Você foi chutado do jogo. - + Game %1: %2 Jogo %1: %2 @@ -2793,22 +2798,22 @@ Por favor, entre um nome: &Sair - + This user is ignoring you. Este usuário está ignorando você. - + %1 has left the server. %1 saiu do servidor. - + %1 has joined the server. %1 entrou no servidor. - + Talking to %1 Falando com %1 @@ -2816,27 +2821,27 @@ Por favor, entre um nome: TabRoom - + &Say: &Falar: - + Chat Chat - + &Room &Sala - + &Leave room S&air da sala - + You are flooding the chat. Please wait a couple of seconds. Você está flodando o chat. Por favor, espere alguns segundos. @@ -3009,126 +3014,126 @@ Digite 0 para banir indefinidamente. &Buscar por: - + Deck &name: Nome do &deck: - + &Comments: &Comentários: - + Deck editor [*] Editor de decks [*] - + &New deck &Novo deck - + &Load deck... &Abrir deck... - + Load deck from cl&ipboard... Carregar deck da área de &transferência... - + &Save deck &Salvar deck - + Save deck &as... Salvar deck c&omo... - + Save deck to clip&board Salvar deck para a área de t&ransferência - + &Print deck... &Imprimir deck... - + &Close &Fechar - + Ctrl+Q Ctrl+Q - + &Edit sets... E&ditar expansões... - + &Deck &Deck - + Load deck Abrir deck - - + + Error Erro - - + + The deck could not be saved. Please check that the directory is writable and try again. O deck não pôde ser salvo. Por favor, verifique se o diretório não é somente leitura e tente novamente. - + Save deck Salvar deck - + Add card to &maindeck Incluir no deck &principal - + Return Return - + Enter Enter - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + Add card to &sideboard Incluir no side&board @@ -3143,47 +3148,47 @@ Por favor, verifique se o diretório não é somente leitura e tente novamente.< &Limpar busca - + &Card database Banco de dados de &cards - + &Remove row &Apagar linha - + Del Del - + &Increment number &Aumentar quantidade - + + + - + &Decrement number &Diminuir quantidade - + - - - + Are you sure? Você tem certeza? - + The decklist has been modified. Do you want to save the changes? O deck foi modificado. diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index e9d026b0c..4c85f4c83 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -156,22 +156,22 @@ CardInfoWidget - + Name: Nome: - + Mana cost: Custo de Mana: - + Card type: Tipo de carta: - + P / T: P / R: @@ -627,22 +627,22 @@ DeckViewContainer - + Load &local deck Carregar deck l&ocal - + Load d&eck from server Carregar deck do &servidor - + Ready to s&tart &Pronto para começar - + Load deck Carregar deck @@ -1010,68 +1010,68 @@ GameSelector - + Error Erro - + Wrong password. Password incorrecta. - + Spectators are not allowed in this game. Não são permitidos espectadores neste jogo. - + The game is already full. O jogo já se encontra cheio. - + The game does not exist any more. O jogo já não existe. - + This game is only open to registered users. Este jogo só está aberto a utilizadores registados. - + This game is only open to its creator's buddies. Este jogo só está aberto aos amigos do seu criador. - + You are being ignored by the creator of this game. Você está a ser ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Password: - + Games Jogos - + Show &full games &Mostrar jogos cheios @@ -1080,17 +1080,17 @@ &Mostrar jogos cheios - + C&reate &Criar - + &Join &Entrar - + J&oin as spectator Entrar como &espectador @@ -2039,322 +2039,322 @@ Versão local é %1, versão remota é %2. Player - + &View graveyard &Ver cemitério - + &View exile &Ver exílio - + Player "%1" Jogador "%1" - + &Graveyard &Cemitério - + &Exile &Exílio - - - + + + Move to &top of library Mover para o &topo do grimório - - - + + + Move to &bottom of library Mover para o &fundo do grimório - - + + Move to &graveyard Mover para o &cemitério - - + + Move to &exile Mover para o &exílio - - + + Move to &hand Mover para a &mão - + &View library &Ver grimório - + View &top cards of library... Ver as cartas do &topo do grimório... - + Reveal &library to Revelar &grimório a - + Reveal t&op card to Revelar carta do t&opo a - + &View sideboard &Ver sideboard - + &Draw card &Comprar carta - + D&raw cards... C&omprar cartas... - + &Undo last draw Desfa&zer a última compra - + Take &mulligan Fazer &mulligan - + &Shuffle &Baralhar - + Move top cards to &graveyard... Mover as cartas do topo para o &cemitério... - + Move top cards to &exile... Mover as cartas do topo para o &exílio... - + Put top card on &bottom Colocar carta do topo no &fundo - + &Hand &Mão - + &Reveal to &Revelar a - + Reveal r&andom card to Revelar carta &aleatória a - + &Sideboard &Sideboard - + &Library &Grimório - + &Counters &Marcadores - + &Untap all permanents &Desvirar topas as permanentes - + R&oll die... &Lançar dado... - + &Create token... Criar fic&ha... - + C&reate another token Cr&iar outra ficha - + S&ay &Dizer - + C&ard C&arta - + &All players Todos os &jogadores - + Ctrl+F3 Ctrl+F3 - + F3 F3 - + Ctrl+W Ctrl+W - + F4 F4 - + Ctrl+D Ctrl+D - + Ctrl+E Ctrl+E - + Ctrl+Shift+D Ctrl+Shift+D - + Ctrl+M Ctrl+M - + Ctrl+S Ctrl+S - + Ctrl+U Ctrl+U - + Ctrl+I Ctrl+I - + Ctrl+T Ctrl+T - + Ctrl+G Ctrl+G - + View top cards of library Ver as cartas do topo do grimório - + Number of cards: Número de cartas: - + Draw cards Comprar cartas - - - - + + + + Number: Número: - + Move top cards to grave Mover as cartas to topo para o cemitério - + Move top cards to exile Mover as cartas to topo para o exílio - + Roll die Lançar dado - + Number of sides: Número de faces: - + Set power/toughness Definir poder/resistência - + Please enter the new PT: Por favor introduza o novo P/R: - + Set annotation Colocar nota - + Please enter the new annotation: Por favor introduza a nova nota: - + Set counters Definir marcadores @@ -2654,132 +2654,137 @@ Por favor introduza um nome: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases Fa&ses - + &Game &Jogo - + Next &phase Próxima &fase - + Ctrl+Space Ctrl+Space - + Next &turn Próximo &turno - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Remover todas as setas locais - + Ctrl+R Ctrl+R - + &Concede &Conceder - + F2 F2 - + &Leave game Sair do &jogo - + + Ctrl+Q + Ctrl+Q + + + &Say: &Dizer: - + Concede Conceder - + Are you sure you want to concede this game? Tem a certeza que deseja conceder este jogo? - + Leave game Sair do jogo - + Are you sure you want to leave this game? Tem a certeza que deseja sair deste jogo? - + Kicked Expulso - + You have been kicked out of the game. Você foi expulso do jogo. - + Game %1: %2 Jogo %1: %2 @@ -2797,22 +2802,22 @@ Por favor introduza um nome: &Abandonar - + This user is ignoring you. Este utilizador esta a ignorar-te. - + %1 has left the server. %1 abandonou o servidor. - + %1 has joined the server. %1 entrou no servidor. - + Talking to %1 Falar para %1 @@ -2820,27 +2825,27 @@ Por favor introduza um nome: TabRoom - + &Say: &Dizer: - + Chat - + &Room &Sala - + &Leave room &Abandonar a sala - + You are flooding the chat. Please wait a couple of seconds. Estás a inundar o chat .Por favor aguarde alguns segundos. @@ -3023,173 +3028,173 @@ Introduza 0 para um banimento indefinido. &Procurar por: - + Deck &name: &Nome do deck: - + &Comments: &Comentários: - + Deck editor [*] Editor de decks [*] - + &New deck &Novo deck - + &Load deck... &Carregar deck... - + &Save deck &Guardar deck - + Save deck &as... G&uardar deck como... - + Load deck from cl&ipboard... Carregar dec&k da memória... - + Save deck to clip&board Guardar deck na &memória - + &Print deck... &Imprimir deck... - + &Close &Fechar - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editar expansões... - + &Deck &Deck - + &Card database &Base de dados das cartas - + Add card to &maindeck Adicionar carta ao &maindeck - + Return Return - + Enter Enter - + Add card to &sideboard Adicionar carta ao &sideboard - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove row &Remover linha - + Del Del - + &Increment number &Aumentar o número - + + + - + &Decrement number &Diminuir o número - + - - - + Are you sure? Tem a certeza? - + The decklist has been modified. Do you want to save the changes? A lista foi modificada. Gostaria de guardar as alterações? - + Load deck Carregar deck - - + + Error Erro - - + + The deck could not be saved. Please check that the directory is writable and try again. O deck não pode ser guardado. Por favor confirme se é possível escrever do directório e tente de novo. - + Save deck Guardar deck diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 288d096d7..b0f24d6aa 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -152,22 +152,22 @@ CardInfoWidget - + Name: Название: - + Mana cost: Манакост: - + Card type: Тип: - + P / T: Сила/Защита: @@ -573,22 +573,22 @@ DeckViewContainer - + Load &local deck Загрузить &колоду с диска - + Load d&eck from server Загрузить к&олоду с сервера - + Ready to s&tart &Готов - + Load deck Загрузить колоду @@ -949,83 +949,83 @@ GameSelector - + Error Ошибка - + Wrong password. Неверный пароль. - + Spectators are not allowed in this game. В эту игру не пускают зрителей. - + The game is already full. Все места заняты! =Ь - + The game does not exist any more. Эта игра была удалена. - + This game is only open to registered users. Доступно только для зарегистрированных. - + This game is only open to its creator's buddies. Доступно только для друзей. - + You are being ignored by the creator of this game. Вы добавлены в игнор-лист данного игрока. - + Join game Присоединиться - + Password: Пароль: - + Games Игры - + Show &full games Показывать &текущие - + C&reate С&оздать - + &Join &Присоединиться - + J&oin as spectator П&рисоединиться как зритель @@ -1970,322 +1970,322 @@ Local version is %1, remote version is %2. Player - + &View graveyard &Посмотреть кладбище - + &View exile П&осмотреть изгнанные карты - + Player "%1" Игрок "%1" - + &Graveyard &Кладбище - + &Exile &Изгнание - - - + + + Move to &top of library Поместить &наверх библиотеки - - - + + + Move to &bottom of library Поместить на &дно библиотеки - - + + Move to &graveyard поместить на клад&бище - - + + Move to &exile Поместить в изгнани&е - - + + Move to &hand Поместить в &руку - + &View library Просмортеть &библиотеку - + View &top cards of library... Посмтореть верхние карт&ы... - + Reveal &library to Показать б&иблиотеку... - + Reveal t&op card to Показать верхние карты... - + &View sideboard Просмотреть &сайд - + &Draw card В&зять карту - + D&raw cards... Вз&ять карты... - + &Undo last draw &Отменить последнее взятие - + Take &mulligan Взять стра&ховку - + &Shuffle Переме&шать - + Move top cards to &graveyard... Поместить верхние карты на кладби&ще... - + Move top cards to &exile... Поместить верхние карты в и&згнание... - + Put top card on &bottom Поместить верхн&юю карту на дно - + &Hand Р&ука - + &Reveal to &Показать... - + Reveal r&andom card to Показать &случайную карту... - + &Sideboard &Сайд - + &Library &Библиотека - + &Counters &Жетоны - + &Untap all permanents &Развернуть все перманенты - + R&oll die... Бросить &кубик... - + &Create token... Создать &фишку... - + C&reate another token Создать &еще одну фишку - + S&ay Ска&зать - + C&ard Ка&рта - + &All players &Все игроки - + Ctrl+F3 - + F3 - + Ctrl+W - + F4 - + Ctrl+D - + Ctrl+E - + Ctrl+Shift+D - + Ctrl+M - + Ctrl+S - + Ctrl+U - + Ctrl+I - + Ctrl+T - + Ctrl+G - + View top cards of library Просмотр верхних карт - + Number of cards: Количество: - + Draw cards Взять карты - - - - + + + + Number: Количество: - + Move top cards to grave Поместить верхние карты на кладбище - + Move top cards to exile Поместить верхние карты в изгнание - + Roll die Бросить кубик - + Number of sides: Количество граней: - + Set power/toughness Установить Силу/Защиту - + Please enter the new PT: Введите новые Силу/Защиту: - + Set annotation Пометка - + Please enter the new annotation: Введите текст: - + Set counters Установить жетоны @@ -2551,132 +2551,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases &Фазы - + &Game &Игра - + Next &phase Следующая &фаза - + Ctrl+Space - + Next &turn Следующий &ход - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows &Удалить все указатели - + Ctrl+R - + &Concede Сда&юсь! - + F2 - + &Leave game Покинуть и&гру - + + Ctrl+Q + + + + &Say: Ска&зать: - + Concede Сдаться - + Are you sure you want to concede this game? Испугался? - + Leave game Покинуть игру - + Are you sure you want to leave this game? Вы уверены, что хотите уйти? - + Kicked Выкинут - + You have been kicked out of the game. Вас выкинули из игры. - + Game %1: %2 Игра %1: %2 @@ -2694,22 +2699,22 @@ Please enter a name: &Покинуть - + This user is ignoring you. Этот пользователь добавил вас в игнор-лист. - + %1 has left the server. %1 отключился. - + %1 has joined the server. %1 зашел на сервер. - + Talking to %1 Беседует с %1 @@ -2717,27 +2722,27 @@ Please enter a name: TabRoom - + &Say: &Сказать: - + Chat Чат - + &Room &Комната - + &Leave room &Покинуть комнату - + You are flooding the chat. Please wait a couple of seconds. Кажется, Вы нафлудили. Пожалуйста, подождите пару секунд. @@ -2912,173 +2917,173 @@ Enter 0 for an indefinite ban. &Искать: - + Deck &name: &Название колоды: - + &Comments: Ко&мментарии: - + Deck editor [*] Редактор колод [*] - + &New deck Новая коло&да - + &Load deck... &Загрузить колоду... - + &Save deck Со&хранить колоду - + Save deck &as... Сохранить колоду к&ак... - + Load deck from cl&ipboard... Взять колоду из &буфера... - + Save deck to clip&board Копировать колоду в бу&фер - + &Print deck... Пе&чать колоды... - + &Close &Закрыть - + Ctrl+Q - + &Edit sets... Редактировать издани&я... - + &Deck Ко&лода - + &Card database База кар&т - + Add card to &maindeck Добавить ме&йном - + Return - + Enter - + Add card to &sideboard Добавить в са&йд - + Ctrl+Return - + Ctrl+Enter - + &Remove row &Удалить строку - + Del - + &Increment number У&величить количество - + + - + &Decrement number У&меньшить количество - + - - + Are you sure? Вы уверены? - + The decklist has been modified. Do you want to save the changes? Деклист был отредактирован. Сохранить изменения? - + Load deck Загрузить колоду - - + + Error Ошибка - - + + The deck could not be saved. Please check that the directory is writable and try again. Колода не может быть сохранена. Убедитесь, что директория указана верно,а затем повторите попытку. - + Save deck Сохранить колоду From c67bc657625737ba84a93cb7ff3008824e43e62a Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 21 May 2011 22:55:08 +0200 Subject: [PATCH 36/87] preliminary sound support --- cockatrice/cockatrice.pro | 4 ++- cockatrice/cockatrice.qrc | 7 +++++ cockatrice/src/carditem.cpp | 2 +- cockatrice/src/dlg_settings.cpp | 43 ++++++++++++++++++++++++++++ cockatrice/src/dlg_settings.h | 10 ++++++- cockatrice/src/main.cpp | 4 +++ cockatrice/src/main.h | 1 + cockatrice/src/messagelogwidget.cpp | 16 ++++++++++- cockatrice/src/settingscache.cpp | 16 +++++++++++ cockatrice/src/settingscache.h | 7 +++++ sounds/draw.raw | Bin 0 -> 10308 bytes sounds/notification.raw | Bin 0 -> 67788 bytes sounds/playcard.raw | Bin 0 -> 5974 bytes sounds/shuffle.raw | Bin 0 -> 30298 bytes sounds/tap.raw | Bin 0 -> 26460 bytes sounds/untap.raw | Bin 0 -> 26460 bytes 16 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 sounds/draw.raw create mode 100644 sounds/notification.raw create mode 100644 sounds/playcard.raw create mode 100644 sounds/shuffle.raw create mode 100644 sounds/tap.raw create mode 100644 sounds/untap.raw diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 4a0203f26..7d84a2280 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -5,7 +5,7 @@ INCLUDEPATH += . src ../common MOC_DIR = build OBJECTS_DIR = build RESOURCES = cockatrice.qrc -QT += network svg +QT += network svg multimedia HEADERS += src/abstractcounter.h \ src/counter_general.h \ @@ -71,6 +71,7 @@ HEADERS += src/abstractcounter.h \ src/localserverinterface.h \ src/localclient.h \ src/translation.h \ + src/soundengine.h \ ../common/color.h \ ../common/serializable_item.h \ ../common/decklist.h \ @@ -153,6 +154,7 @@ SOURCES += src/abstractcounter.cpp \ src/localserver.cpp \ src/localserverinterface.cpp \ src/localclient.cpp \ + src/soundengine.cpp \ ../common/serializable_item.cpp \ ../common/decklist.cpp \ ../common/protocol.cpp \ diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index d57e461e4..9e20650df 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -97,6 +97,13 @@ resources/counters/general.svg resources/counters/general_highlight.svg + resources/sounds/draw.raw + resources/sounds/notification.raw + resources/sounds/playcard.raw + resources/sounds/shuffle.raw + resources/sounds/tap.raw + resources/sounds/untap.raw + resources/userlevels/normal.svg resources/userlevels/registered.svg resources/userlevels/judge.svg diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index 21ae3bb68..57cef89fe 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -360,7 +360,7 @@ void CardItem::resetState() annotation.clear(); attachedTo = 0; attachedCards.clear(); - setTapped(false); + setTapped(false, false); setDoesntUntap(false); update(); } diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index 88bdfd989..a07fff6cb 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -377,6 +377,8 @@ void AppearanceSettingsPage::cardBackPicturePathButtonClicked() UserInterfaceSettingsPage::UserInterfaceSettingsPage() { + QIcon deleteIcon(":/resources/icon_delete.svg"); + doubleClickToPlayCheckBox = new QCheckBox; doubleClickToPlayCheckBox->setChecked(settingsCache->getDoubleClickToPlay()); connect(doubleClickToPlayCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setDoubleClickToPlay(int))); @@ -391,6 +393,28 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() tapAnimationCheckBox->setChecked(settingsCache->getTapAnimation()); connect(tapAnimationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setTapAnimation(int))); + soundEnabledCheckBox = new QCheckBox; + soundEnabledCheckBox->setChecked(settingsCache->getSoundEnabled()); + connect(soundEnabledCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setSoundEnabled(int))); + + soundPathLabel = new QLabel; + soundPathEdit = new QLineEdit(settingsCache->getSoundPath()); + soundPathEdit->setReadOnly(true); + QPushButton *soundPathClearButton = new QPushButton(deleteIcon, QString()); + connect(soundPathClearButton, SIGNAL(clicked()), this, SLOT(soundPathClearButtonClicked())); + QPushButton *soundPathButton = new QPushButton("..."); + connect(soundPathButton, SIGNAL(clicked()), this, SLOT(soundPathButtonClicked())); + + QGridLayout *soundGrid = new QGridLayout; + soundGrid->addWidget(soundEnabledCheckBox, 0, 0, 1, 4); + soundGrid->addWidget(soundPathLabel, 1, 0); + soundGrid->addWidget(soundPathEdit, 1, 1); + soundGrid->addWidget(soundPathClearButton, 1, 2); + soundGrid->addWidget(soundPathButton, 1, 3); + + soundGroupBox = new QGroupBox; + soundGroupBox->setLayout(soundGrid); + QGridLayout *animationGrid = new QGridLayout; animationGrid->addWidget(tapAnimationCheckBox, 0, 0); @@ -400,6 +424,7 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(generalGroupBox); mainLayout->addWidget(animationGroupBox); + mainLayout->addWidget(soundGroupBox); setLayout(mainLayout); } @@ -410,6 +435,24 @@ void UserInterfaceSettingsPage::retranslateUi() doubleClickToPlayCheckBox->setText(tr("&Double-click cards to play them (instead of single-click)")); animationGroupBox->setTitle(tr("Animation settings")); tapAnimationCheckBox->setText(tr("&Tap/untap animation")); + soundEnabledCheckBox->setText(tr("Enable &sounds")); + soundPathLabel->setText(tr("Path to sounds directory:")); +} + +void UserInterfaceSettingsPage::soundPathClearButtonClicked() +{ + soundPathEdit->setText(QString()); + settingsCache->setSoundPath(QString()); +} + +void UserInterfaceSettingsPage::soundPathButtonClicked() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Choose path")); + if (path.isEmpty()) + return; + + soundPathEdit->setText(path); + settingsCache->setSoundPath(path); } MessagesSettingsPage::MessagesSettingsPage() diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index 70e231f20..54648482b 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -76,10 +76,18 @@ public: class UserInterfaceSettingsPage : public AbstractSettingsPage { Q_OBJECT +private slots: + void soundPathClearButtonClicked(); + void soundPathButtonClicked(); +signals: + void soundPathChanged(); private: QCheckBox *doubleClickToPlayCheckBox; QCheckBox *tapAnimationCheckBox; - QGroupBox *generalGroupBox, *animationGroupBox; + QCheckBox *soundEnabledCheckBox; + QLabel *soundPathLabel; + QLineEdit *soundPathEdit; + QGroupBox *generalGroupBox, *animationGroupBox, *soundGroupBox; public: UserInterfaceSettingsPage(); void retranslateUi(); diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index 5b872b69e..8ce2581b7 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -36,6 +36,7 @@ #include "settingscache.h" #include "pixmapgenerator.h" #include "rng_sfmt.h" +#include "soundengine.h" //Q_IMPORT_PLUGIN(qjpeg) @@ -43,6 +44,7 @@ CardDatabase *db; QTranslator *translator, *qtTranslator; SettingsCache *settingsCache; RNG_Abstract *rng; +SoundEngine *soundEngine; void myMessageOutput(QtMsgType /*type*/, const char *msg) { @@ -114,6 +116,8 @@ int main(int argc, char *argv[]) } if (startMainProgram) { + soundEngine = new SoundEngine; + MainWindow ui; qDebug("main(): MainWindow constructor finished"); diff --git a/cockatrice/src/main.h b/cockatrice/src/main.h index b1f30bdb8..f8e5a1475 100644 --- a/cockatrice/src/main.h +++ b/cockatrice/src/main.h @@ -3,6 +3,7 @@ class CardDatabase; class QTranslator; +class SoundEngine; extern CardDatabase *db; diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index b2907e8c5..15928aa86 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -3,6 +3,7 @@ #include "cardzone.h" #include "cardinfowidget.h" #include "protocol_items.h" +#include "soundengine.h" #include #include #include @@ -60,6 +61,7 @@ void MessageLogWidget::logGameJoined(int gameId) void MessageLogWidget::logJoin(Player *player) { + soundEngine->notification(); append(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); } @@ -123,6 +125,7 @@ void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) void MessageLogWidget::logShuffle(Player *player) { + soundEngine->shuffle(); append(tr("%1 shuffles his library.").arg(sanitizeHtml(player->getName()))); } @@ -133,6 +136,7 @@ void MessageLogWidget::logRollDie(Player *player, int sides, int roll) void MessageLogWidget::logDrawCards(Player *player, int number) { + soundEngine->draw(); append(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); } @@ -212,6 +216,7 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes) QString finalStr; if (targetName == "table") { + soundEngine->playCard(); if (moveCardTapped.value(attributes.card)) finalStr = tr("%1 puts %2 into play tapped%3."); else @@ -233,8 +238,10 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes) finalStr = tr("%1 puts %2%3 into his library at position %4."); } else if (targetName == "sb") finalStr = tr("%1 moves %2%3 to sideboard."); - else if (targetName == "stack") + else if (targetName == "stack") { + soundEngine->playCard(); finalStr = tr("%1 plays %2%3."); + } append(finalStr.arg(sanitizeHtml(attributes.player->getName())).arg(cardStr).arg(fromStr).arg(attributes.newX)); } @@ -317,6 +324,11 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) { + if (tapped) + soundEngine->tap(); + else + soundEngine->untap(); + if (currentContext == MessageContext_MoveCard) moveCardTapped.insert(card, tapped); else { @@ -409,6 +421,7 @@ void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId void MessageLogWidget::logSetActivePlayer(Player *player) { + soundEngine->notification(); append(QString()); append("" + tr("It is now %1's turn.").arg(player->getName()) + ""); append(QString()); @@ -416,6 +429,7 @@ void MessageLogWidget::logSetActivePlayer(Player *player) void MessageLogWidget::logSetActivePhase(int phase) { + soundEngine->notification(); QString phaseName; switch (phase) { case 0: phaseName = tr("untap step"); break; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 4d621a8a9..bb0ecdae7 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -27,6 +27,9 @@ SettingsCache::SettingsCache() zoneViewSortByName = settings->value("zoneview/sortbyname", true).toBool(); zoneViewSortByType = settings->value("zoneview/sortbytype", true).toBool(); + + soundEnabled = settings->value("sound/enabled", false).toBool(); + soundPath = settings->value("sound/path").toString(); } void SettingsCache::setLang(const QString &_lang) @@ -148,3 +151,16 @@ void SettingsCache::setZoneViewSortByType(int _zoneViewSortByType) zoneViewSortByType = _zoneViewSortByType; settings->setValue("zoneview/sortbytype", zoneViewSortByType); } + +void SettingsCache::setSoundEnabled(int _soundEnabled) +{ + soundEnabled = _soundEnabled; + settings->setValue("sound/enabled", soundEnabled); +} + +void SettingsCache::setSoundPath(const QString &_soundPath) +{ + soundPath = _soundPath; + settings->setValue("sound/path", soundPath); + emit soundPathChanged(); +} diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 8960dc569..6a8f1a99c 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -20,6 +20,7 @@ signals: void displayCardNamesChanged(); void horizontalHandChanged(); void invertVerticalCoordinateChanged(); + void soundPathChanged(); private: QSettings *settings; @@ -34,6 +35,8 @@ private: bool invertVerticalCoordinate; bool tapAnimation; bool zoneViewSortByName, zoneViewSortByType; + bool soundEnabled; + QString soundPath; public: SettingsCache(); QString getLang() const { return lang; } @@ -54,6 +57,8 @@ public: bool getTapAnimation() const { return tapAnimation; } bool getZoneViewSortByName() const { return zoneViewSortByName; } bool getZoneViewSortByType() const { return zoneViewSortByType; } + bool getSoundEnabled() const { return soundEnabled; } + QString getSoundPath() const { return soundPath; } public slots: void setLang(const QString &_lang); void setDeckPath(const QString &_deckPath); @@ -73,6 +78,8 @@ public slots: void setTapAnimation(int _tapAnimation); void setZoneViewSortByName(int _zoneViewSortByName); void setZoneViewSortByType(int _zoneViewSortByType); + void setSoundEnabled(int _soundEnabled); + void setSoundPath(const QString &_soundPath); }; extern SettingsCache *settingsCache; diff --git a/sounds/draw.raw b/sounds/draw.raw new file mode 100644 index 0000000000000000000000000000000000000000..3732125f202d3cd70e2e611266a860ead2764276 GIT binary patch literal 10308 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 p#_QuBUgZhY&^&~*jHi-TIBJ}_O literal 0 HcmV?d00001 diff --git a/sounds/notification.raw b/sounds/notification.raw new file mode 100644 index 0000000000000000000000000000000000000000..19906b48d425685181ed0c8540549d2bd2b6ed49 GIT binary patch literal 67788 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 QQS}KvE4JmTl6CX+|Jq-uV*mgE literal 0 HcmV?d00001 diff --git a/sounds/shuffle.raw b/sounds/shuffle.raw new file mode 100644 index 0000000000000000000000000000000000000000..f092e5678a261cc90f308fae3b9317facf0cc747 GIT binary patch literal 30298 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 literal 0 HcmV?d00001 diff --git a/sounds/tap.raw b/sounds/tap.raw new file mode 100644 index 0000000000000000000000000000000000000000..db5290a87fa51a66e3ae11049df6d6bf96cf963c GIT binary patch literal 26460 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 z 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 Date: Sat, 21 May 2011 23:03:00 +0200 Subject: [PATCH 37/87] made server threading optional --- cockatrice/cockatrice.qrc | 7 ------- servatrice/servatrice.ini.example | 1 + servatrice/src/servatrice.cpp | 17 ++++++++++++++--- servatrice/src/servatrice.h | 5 +++-- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 9e20650df..d57e461e4 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -97,13 +97,6 @@ resources/counters/general.svg resources/counters/general_highlight.svg - resources/sounds/draw.raw - resources/sounds/notification.raw - resources/sounds/playcard.raw - resources/sounds/shuffle.raw - resources/sounds/tap.raw - resources/sounds/untap.raw - resources/userlevels/normal.svg resources/userlevels/registered.svg resources/userlevels/judge.svg diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 72647bc4d..8a01bc85f 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -3,6 +3,7 @@ port=4747 statusupdate=15000 logfile=server.log id=1 +threaded=0 [authentication] method=none diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 6346e0e9c..ca5ef443e 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -26,11 +26,21 @@ #include "serversocketinterface.h" #include "serversocketthread.h" #include "protocol.h" +#include "server_logger.h" +#include "main.h" void Servatrice_TcpServer::incomingConnection(int socketDescriptor) { - ServerSocketThread *sst = new ServerSocketThread(socketDescriptor, server, this); - sst->start(); + if (threaded) { + ServerSocketThread *sst = new ServerSocketThread(socketDescriptor, server, this); + sst->start(); + } else { + QTcpSocket *socket = new QTcpSocket; + socket->setSocketDescriptor(socketDescriptor); + logger->logMessage(QString("incoming connection: %1").arg(socket->peerAddress().toString())); + + new ServerSocketInterface(server, socket); + } } Servatrice::Servatrice(QSettings *_settings, QObject *parent) @@ -55,7 +65,8 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) statusUpdateClock->start(statusUpdateTime); } - tcpServer = new Servatrice_TcpServer(this); + bool threaded = settings->value("server/threaded", false).toInt(); + tcpServer = new Servatrice_TcpServer(this, threaded); int port = settings->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << port; if (tcpServer->listen(QHostAddress::Any, port)) diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 9498d8a17..f1174c91d 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -36,9 +36,10 @@ class Servatrice_TcpServer : public QTcpServer { Q_OBJECT private: Servatrice *server; + bool threaded; public: - Servatrice_TcpServer(Servatrice *_server, QObject *parent = 0) - : QTcpServer(parent), server(_server) { } + Servatrice_TcpServer(Servatrice *_server, bool _threaded, QObject *parent = 0) + : QTcpServer(parent), server(_server), threaded(_threaded) { } protected: void incomingConnection(int socketDescriptor); }; From 0c1c0fcb56ef937a99235ba826f47908ef09a99d Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 21 May 2011 23:03:51 +0200 Subject: [PATCH 38/87] added sound engine files --- cockatrice/src/soundengine.cpp | 77 ++++++++++++++++++++++++++++++++++ cockatrice/src/soundengine.h | 32 ++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 cockatrice/src/soundengine.cpp create mode 100644 cockatrice/src/soundengine.h diff --git a/cockatrice/src/soundengine.cpp b/cockatrice/src/soundengine.cpp new file mode 100644 index 000000000..5daeae9a0 --- /dev/null +++ b/cockatrice/src/soundengine.cpp @@ -0,0 +1,77 @@ +#include "soundengine.h" +#include "settingscache.h" +#include +#include +#include +#include + +SoundEngine::SoundEngine(QObject *parent) + : QObject(parent) +{ + inputBuffer = new QBuffer; + QAudioFormat format; + format.setFrequency(44100); + format.setChannels(1); + format.setSampleSize(16); + format.setCodec("audio/pcm"); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setSampleType(QAudioFormat::SignedInt); + audio = new QAudioOutput(format, this); + + connect(settingsCache, SIGNAL(soundPathChanged()), this, SLOT(cacheData())); + cacheData(); +} + +void SoundEngine::cacheData() +{ + static const QStringList fileNames = QStringList() + << "notification" << "draw" << "playcard" << "shuffle" << "tap" << "untap"; + for (int i = 0; i < fileNames.size(); ++i) { + QFile file(settingsCache->getSoundPath() + "/" + fileNames[i] + ".raw"); + file.open(QIODevice::ReadOnly); + audioData.insert(fileNames[i], file.readAll()); + file.close(); + } +} + +void SoundEngine::playSound(const QString &fileName) +{ + if (!settingsCache->getSoundEnabled()) + return; + + audio->stop(); + inputBuffer->close(); + inputBuffer->setData(audioData[fileName]); + inputBuffer->open(QIODevice::ReadOnly); + audio->start(inputBuffer); +} + +void SoundEngine::notification() +{ + playSound("notification"); +} + +void SoundEngine::draw() +{ + playSound("draw"); +} + +void SoundEngine::playCard() +{ + playSound("playcard"); +} + +void SoundEngine::shuffle() +{ + playSound("shuffle"); +} + +void SoundEngine::tap() +{ + playSound("tap"); +} + +void SoundEngine::untap() +{ + playSound("untap"); +} diff --git a/cockatrice/src/soundengine.h b/cockatrice/src/soundengine.h new file mode 100644 index 000000000..312a476bc --- /dev/null +++ b/cockatrice/src/soundengine.h @@ -0,0 +1,32 @@ +#ifndef SOUNDENGINE_H +#define SOUNDENGINE_H + +#include +#include + +class QAudioOutput; +class QBuffer; + +class SoundEngine : public QObject { + Q_OBJECT +private: + void playSound(const QString &fileName); + QMap audioData; + QBuffer *inputBuffer; + QAudioOutput *audio; +private slots: + void cacheData(); +public: + SoundEngine(QObject *parent = 0); +public slots: + void notification(); + void draw(); + void playCard(); + void shuffle(); + void tap(); + void untap(); +}; + +extern SoundEngine *soundEngine; + +#endif \ No newline at end of file From 808d2a3c01e0f81288eef7e380ce0e43dd2699e1 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 21 May 2011 23:48:46 +0200 Subject: [PATCH 39/87] Event context for mulligans, German translation --- cockatrice/src/messagelogwidget.cpp | 28 ++- cockatrice/src/messagelogwidget.h | 7 +- cockatrice/src/player.cpp | 3 +- cockatrice/translations/cockatrice_de.ts | 266 +++++++++++--------- cockatrice/translations/cockatrice_en.ts | 264 ++++++++++--------- cockatrice/translations/cockatrice_es.ts | 264 ++++++++++--------- cockatrice/translations/cockatrice_fr.ts | 264 ++++++++++--------- cockatrice/translations/cockatrice_ja.ts | 263 ++++++++++--------- cockatrice/translations/cockatrice_pt-br.ts | 264 ++++++++++--------- cockatrice/translations/cockatrice_pt.ts | 264 ++++++++++--------- cockatrice/translations/cockatrice_ru.ts | 265 ++++++++++--------- common/protocol_item_ids.h | 7 +- common/protocol_items.cpp | 6 + common/protocol_items.dat | 1 + common/protocol_items.h | 8 + common/server_player.cpp | 1 + common/server_protocolhandler.cpp | 7 + 17 files changed, 1228 insertions(+), 954 deletions(-) diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 15928aa86..a7ab151b6 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -126,7 +126,8 @@ void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) void MessageLogWidget::logShuffle(Player *player) { soundEngine->shuffle(); - append(tr("%1 shuffles his library.").arg(sanitizeHtml(player->getName()))); + if (currentContext != MessageContext_Mulligan) + append(tr("%1 shuffles his library.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logRollDie(Player *player, int sides, int roll) @@ -136,8 +137,12 @@ void MessageLogWidget::logRollDie(Player *player, int sides, int roll) void MessageLogWidget::logDrawCards(Player *player, int number) { - soundEngine->draw(); - append(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); + if (currentContext == MessageContext_Mulligan) + mulliganPlayer = player; + else { + soundEngine->draw(); + append(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); + } } void MessageLogWidget::logUndoDraw(Player *player, QString cardName) @@ -251,10 +256,20 @@ void MessageLogWidget::logMoveCard(Player *player, CardItem *card, CardZone *sta LogMoveCard attributes = {player, card, card->getName(), startZone, oldX, targetZone, newX}; if (currentContext == MessageContext_MoveCard) moveCardQueue.append(attributes); + else if (currentContext == MessageContext_Mulligan) + mulliganPlayer = player; else doMoveCard(attributes); } +void MessageLogWidget::logMulligan(Player *player, int number) +{ + if (number > -1) + append(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); + else + append(tr("%1 draws his initial hand.").arg(sanitizeHtml(player->getName()))); +} + void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown) { if (faceDown) @@ -451,6 +466,10 @@ void MessageLogWidget::containerProcessingStarted(GameEventContext *_context) { if (qobject_cast(_context)) currentContext = MessageContext_MoveCard; + else if (qobject_cast(_context)) { + currentContext = MessageContext_Mulligan; + mulliganNumber = static_cast(_context)->getNumber(); + } } void MessageLogWidget::containerProcessingDone() @@ -461,6 +480,9 @@ void MessageLogWidget::containerProcessingDone() moveCardQueue.clear(); moveCardPT.clear(); moveCardTapped.clear(); + } else if (currentContext == MessageContext_Mulligan) { + logMulligan(mulliganPlayer, mulliganNumber); + mulliganNumber = 0; } currentContext = MessageContext_None; diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index b5295c35a..1a42a3261 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -27,16 +27,20 @@ struct LogMoveCard { class MessageLogWidget : public QTextEdit { Q_OBJECT private: - enum MessageContext { MessageContext_None, MessageContext_MoveCard }; + enum MessageContext { MessageContext_None, MessageContext_MoveCard, MessageContext_Mulligan }; CardInfoWidget *infoWidget; QString sanitizeHtml(QString dirty) const; QPair getFromStr(CardZone *zone, QString cardName, int position) const; QString getCardNameUnderMouse(const QPoint &pos) const; MessageContext currentContext; + QList moveCardQueue; QMap moveCardPT; QMap moveCardTapped; + + Player *mulliganPlayer; + int mulliganNumber; signals: void cardNameHovered(QString cardName); void showCardInfoPopup(QPoint pos, QString cardName); @@ -68,6 +72,7 @@ public slots: void logUndoDraw(Player *player, QString cardName); void doMoveCard(LogMoveCard &attributes); void logMoveCard(Player *player, CardItem *card, CardZone *startZone, int oldX, CardZone *targetZone, int newX); + void logMulligan(Player *player, int number); void logFlipCard(Player *player, QString cardName, bool faceDown); void logDestroyCard(Player *player, QString cardName); void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 96bad5031..1b8ec25bb 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -891,8 +891,7 @@ void Player::eventMoveCard(Event_MoveCard *event, GameEventContext *context) if (context) switch (context->getItemId()) { case ItemId_Context_UndoDraw: emit logUndoDraw(this, card->getName()); break; - case ItemId_Context_MoveCard: emit logMoveCard(this, card, startZone, logPosition, targetZone, logX); - default: ; + default: emit logMoveCard(this, card, startZone, logPosition, targetZone, logX); } else emit logMoveCard(this, card, startZone, logPosition, targetZone, logX); diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 993c17877..21f6d2639 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -1208,9 +1208,9 @@ DlgSettings - - - + + + Error Fehler @@ -1227,47 +1227,47 @@ Der Pfad zum Kartenbilderverzeichnis ist ungültig. - + Your card database is invalid. Would you like to go back and set the correct path? Ihre Kartendatenbank ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Der Pfad zu Ihrem Deckordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Der Pfad zu Ihrem Kartenbilderordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + Settings Einstellungen - + General Allgemeines - + Appearance Erscheinungsbild - + User interface Bedienung - + Messages Nachrichten - + &Close S&chließen @@ -2022,22 +2022,22 @@ Lokale Version ist %1, Serverversion ist %2. MessageLogWidget - + Connecting to %1... Verbinde zu %1... - + Connected. Verbunden. - + Disconnected from server. Verbindung zum Server getrennt. - + Invalid password. Ungültiges Passwort. @@ -2078,8 +2078,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten - - + + a card eine Karte @@ -2136,12 +2136,12 @@ Lokale Version ist %1, Serverversion ist %2. %1s Sideboard - + The game has started. Das Spiel hat begonnen. - + %1 shuffles his library. %1 mischt seine Bibliothek. @@ -2158,72 +2158,72 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversion stimmt nicht überein. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. Protokollfehler. - + You have joined game #%1. Sie sind dem Spiel %1 beigetreten. - + %1 has joined the game. %1 ist dem Spiel beigetreten. - + %1 has left the game. %1 hat das Spiel verlassen. - + The game has been closed. Das Spiel wurde geschlossen. - + %1 is now watching the game. %1 schaut nun dem Spiel zu. - + %1 is not watching the game any more. %1 schaut dem Spiel nicht mehr zu. - + %1 has loaded a local deck. %1 hat ein lokales Deck geladen. - + %1 has loaded deck #%2. %1 hat das Deck Nr. %2 geladen. - + %1 is ready to start the game. %1 ist bereit, das Spiel zu starten. - + %1 is not ready to start the game any more. %1 ist nicht mehr bereit, das Spiel zu starten. - + %1 has conceded the game. %1 hat das Spiel aufgegeben. - + %1 rolls a %2 with a %3-sided die. %1 würfelt eine %2 mit einem %3-seitigen Würfel. @@ -2236,7 +2236,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten. - + %1 draws %n card(s). %1 zieht eine Karte. @@ -2244,167 +2244,180 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 undoes his last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes his last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + from the bottom of his library , die unterste Karte seiner Bibliothek, - + the top card of his library die oberste Karte seiner Bibliothek - + from the top of his library , die oberste Karte seiner Bibliothek, - + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + from the stack vom Stapel - + %1 gives %2 control over %3. %1 überlässt %2 die Kontrolle über %3. - + %1 puts %2 into play tapped%3. %1 bringt %2 getappt%3 ins Spiel. - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 plays %2%3. %1 spielt %2%3 aus. + + + %1 takes a mulligan to %n. + + %1 nimmt einen Mulligan auf %n. + %1 nimmt einen Mulligan auf %n. + + - + + %1 draws his initial hand. + %1 zieht seine Starthand. + + + %1 flips %2 face-down. %1 wendet %2 auf die Rückseite. - + %1 flips %2 face-up. %1 wendet %2 auf die Vorderseite. - + %1 destroys %2. %1 zerstört %2. - + %1 attaches %2 to %3's %4. %1 legt %2 an %3s %4 an. - + %1 unattaches %2. %1 löst %2 ab. - + %1 creates token: %2%3. %1 erstellt Token: %2%3. - + %1 points from %2's %3 to %4. %1 zeigt von %2s %3 auf %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 legt eine %2 Marke auf %3 (jetzt %4). @@ -2412,7 +2425,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 entfernt eine %2 Marke von %3 (jetzt %4). @@ -2420,22 +2433,22 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 randomly reveals %2%3 to %4. %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3. %1 zeigt zufällig %2%3 offen vor. - + %1 reveals %2%3 to %4. %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3. %1 zeigt %2%3 offen vor. @@ -2444,7 +2457,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 erstellt einen Spielstein: %2 (%3). - + %1 points from %2's %3 to %4's %5. %1 zeigt von %2s %3 auf %4s %5. @@ -2463,7 +2476,7 @@ Lokale Version ist %1, Serverversion ist %2. - + red rote @@ -2471,7 +2484,7 @@ Lokale Version ist %1, Serverversion ist %2. - + yellow gelbe @@ -2479,7 +2492,7 @@ Lokale Version ist %1, Serverversion ist %2. - + green grüne @@ -2487,22 +2500,22 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 sets counter %2 to %3 (%4%5). %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets PT of %2 to %3. %1 setzt Kampfwerte von %2 auf %3. - + %1 sets annotation of %2 to %3. %1 versieht %2 mit dem Hinweis %3. - + %1 is looking at the top %2 cards %3. %1 sieht sich die obersten %2 Karten %3 an. @@ -2599,7 +2612,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4). - + %1 %2 %3. %1 %2 %3. @@ -2612,22 +2625,22 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. %1 sieht sich %2 an. - + %1 stops looking at %2. %1 sieht sich %2 nicht mehr an. - + %1 reveals %2 to %3. %1 zeigt %3 %2. - + %1 reveals %2. %1 zeigt %2 offen vor. @@ -2648,7 +2661,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zeigt %2 aus %3 offen vor. - + ending phase die Zugendphase @@ -2677,57 +2690,57 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich %2s %3 nicht mehr an - + It is now %1's turn. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -2736,7 +2749,7 @@ Lokale Version ist %1, Serverversion ist %2. das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -2745,12 +2758,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 bewegt %2 %3 nach %4 - + taps tappt - + untaps enttappt @@ -2775,7 +2788,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4) - + his permanents seine bleibenden Karten @@ -2788,12 +2801,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 setzt Zähler "%2" auf %3 (%4%5) - + %1 sets %2 to not untap normally. %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. %1 setzt %2 auf normales Enttappen. @@ -2809,12 +2822,12 @@ Lokale Version ist %1, Serverversion ist %2. MessagesSettingsPage - + &Add &Hinzufügen - + &Remove &Entfernen @@ -2827,12 +2840,12 @@ Lokale Version ist %1, Serverversion ist %2. Entfernen - + Add message Nachricht hinzufügen - + Message: Nachricht: @@ -3308,7 +3321,7 @@ Lokale Version ist %1, Serverversion ist %2. - + Number: Anzahl: @@ -3323,27 +3336,27 @@ Lokale Version ist %1, Serverversion ist %2. Oberste Karten ins Exil schicken - + Set power/toughness Kampfwerte setzen - + Please enter the new PT: Bitte die neuen Kampfwerte eingeben: - + Set annotation Hinweis setzen - + Please enter the new annotation: Bitte den Hinweis eingeben: - + Set counters Setze Zählmarken @@ -3781,7 +3794,7 @@ Bitte geben Sie einen Namen ein: Ctrl+Q - Ctrl+Q + Ctrl+Q @@ -3998,25 +4011,40 @@ Bitte geben Sie einen Namen ein: UserInterfaceSettingsPage - + General interface settings Allgemeine Bedienung - + &Double-click cards to play them (instead of single-click) Karten durch &Doppelklick ausspielen (statt Einzelklick) - + Animation settings Animationseinstellungen - + &Tap/untap animation Animiertes &Tappen/Enttappen + + + Enable &sounds + &Sound anschalten + + + + Path to sounds directory: + Pfad zum Verzeichnis mit den Sounddateien: + + + + Choose path + Pfad auswählen + UserList diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index e80e16593..f3e26b6ac 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -890,54 +890,54 @@ DlgSettings - - - + + + Error - + Your card database is invalid. Would you like to go back and set the correct path? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User interface - + Messages - + &Close @@ -1374,52 +1374,52 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). %1 draws a card. @@ -1427,158 +1427,158 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes his last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + from the bottom of his library - + the top card of his library - + from the top of his library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 into his library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1597,7 +1597,7 @@ Local version is %1, remote version is %2. - + red @@ -1605,7 +1605,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1613,7 +1613,7 @@ Local version is %1, remote version is %2. - + green @@ -1621,92 +1621,105 @@ Local version is %1, remote version is %2. - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. + + + %1 takes a mulligan to %n. + + + + + - + + %1 draws his initial hand. + + + + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 places a %2 counter on %3 (now %4). @@ -1714,7 +1727,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 removes a %2 counter from %3 (now %4). @@ -1722,142 +1735,142 @@ Local version is %1, remote version is %2. - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 shuffles his library. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -1865,22 +1878,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + &Add - + &Remove - + Add message - + Message: @@ -2216,7 +2229,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2241,27 +2254,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -2772,25 +2785,40 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + &Double-click cards to play them (instead of single-click) - + Animation settings - + &Tap/untap animation + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + + UserList diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 7bd5eaf02..fa4beae2f 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -1089,9 +1089,9 @@ DlgSettings - - - + + + Error Error @@ -1108,47 +1108,47 @@ La ruta a tu directorio de imagenes de las cartas es invalida. - + Your card database is invalid. Would you like to go back and set the correct path? Tu base de datos de cartas es invalida. ¿Deseas volver y seleccionar la ruta correcta? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? La ruta a tu directorio de mazos es invalida. ¿Deseas volver y seleccionar la ruta correcta? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? La ruta a tu directorio de imagenes de las cartas es invalida.¿Deseas volver y seleccionar la ruta correcta? - + Settings Preferencias - + General General - + Appearance Apariencia - + User interface Interfaz de usuario - + Messages Mensajes - + &Close &Cerrar @@ -1597,52 +1597,52 @@ La versión local es %1, la versión remota es %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado del servidor. - + Invalid password. Contraseña incorrecta. - + Protocol error. Error del protocolo. - + The game has been closed. La partida ha sido cerrada. - + %1 is now watching the game. %1 está ahora observando la partida. - + %1 is not watching the game any more. %1 ya no está observado más la partida. - + %1 is not ready to start the game any more. %1 ya no está listo para empezar el juego. - + %1 rolls a %2 with a %3-sided die. %1 sacó un %2 con un dado de %3 caras. - + %1 draws %n card(s). %1 roba %n carta. @@ -1650,158 +1650,158 @@ La versión local es %1, la versión remota es %2. - + %1 undoes his last draw. %1 deshace su último robo. - + %1 undoes his last draw (%2). %1 deshace su último robo (%2). - + from table de la mesa - + from graveyard del cementerio - + from exile del exilio - + from hand de la mano - + the bottom card of his library el fondo de la biblioteca - + from the bottom of his library del fondo de la biblioteca - + the top card of his library la parte superior de la biblioteca - + from the top of his library de la parte superior de la biblioteca - + from library de la biblioteca - + from sideboard de la reserva - + from the stack de la pila - + %1 gives %2 control over %3. %1 entrega a %2 el control sobre %3. - + %1 puts %2 into play tapped%3. %1 pone %2 en juego%3 girado. - + %1 puts %2 into play%3. %1 pone %2 en juego%3. - + %1 puts %2%3 into graveyard. %1 pone %2%3 en el cementerio. - + %1 exiles %2%3. %1 exilia %2%3. - + %1 moves %2%3 to hand. %1 mueve %2%3 a la mano. - + %1 puts %2%3 into his library. %1 pone %2%3 en la biblioteca. - + %1 puts %2%3 on bottom of his library. %1 pone %2%3 en la parte inferior de su biblioteca. - + %1 puts %2%3 on top of his library. %1 pone %2%3 en la parte superior de su biblioteca. - + %1 puts %2%3 into his library at position %4. %1 pone %2%3 en su biblioteca en la posición %4. - + %1 moves %2%3 to sideboard. %1 mueve %2%3 a la reserva. - + %1 plays %2%3. %1 juega %2%3. - - + + a card una carta - + %1 flips %2 face-down. %1 voltea %2 boca abajo. - + %1 flips %2 face-up. %1 voltea %2 boca arriba. - + %1 attaches %2 to %3's %4. %1 anexa %2 a el %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 apunta desde el %3 de %2 al %5 de %4. @@ -1820,7 +1820,7 @@ La versión local es %1, la versión remota es %2. - + red rojo @@ -1828,7 +1828,7 @@ La versión local es %1, la versión remota es %2. - + yellow amarillo @@ -1836,7 +1836,7 @@ La versión local es %1, la versión remota es %2. - + green verde @@ -1844,72 +1844,72 @@ La versión local es %1, la versión remota es %2. - + %1 sets counter %2 to %3 (%4%5). %1 establece los contadores de %2 a %3 (%4%5). - + %1 sets PT of %2 to %3. %1 establece F/R de %2 a %3. - + %1 sets annotation of %2 to %3. %1 establece la anotación de %2 a %3. - + %1 is looking at the top %2 cards %3. %1 esta mirando las primeras %2 cartas de %3. - + The game has started. La partida ha comenzado. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 La versión del protocolo es diferente. Cliente: %1, Servidor: %2 - + You have joined game #%1. Te has unido a la partida #%1. - + %1 has joined the game. %1 se ha unido a la partida. - + %1 has left the game. %1 ha dejado la partida. - + %1 has loaded a local deck. %1 ha cargado un mazo local. - + %1 has loaded deck #%2. %1 ha cargado el mazo #%2. - + %1 is ready to start the game. %1 está preparado para empezar la partida. - + %1 has conceded the game. %1 ha concedido la partida. @@ -1922,22 +1922,22 @@ La versión local es %1, la versión remota es %2. %1 roba %2 cartas. - + %1 destroys %2. %1 destruye %2. - + %1 creates token: %2%3. %1 crea una ficha: %2%3. - + %1 points from %2's %3 to %4. %1 apunta desde el %3 de %2 a %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 pone %n %2 contador en %3 (ahora %4). @@ -1945,7 +1945,7 @@ La versión local es %1, la versión remota es %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remueve %n %2 contador en %3 (ahora %4). @@ -1953,142 +1953,155 @@ La versión local es %1, la versión remota es %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está mirando: %2. - + %1 stops looking at %2. %1 termina de mirar: %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase de fin de turno - + It is now %1's turn. Es el turno de %1. - + %1 shuffles his library. %1 baraja su biblioteca. + + + %1 takes a mulligan to %n. + + + + + - + + %1 draws his initial hand. + + + + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3 a %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step paso de enderezar - + upkeep step paso de mantenimiento - + draw step paso de robar - + first main phase primera fase principal - + beginning of combat step paso de inicio de combate - + declare attackers step paso de declarar atacantes - + declare blockers step paso de declarar bloqueadores - + combat damage step paso de daño de combate - + end of combat step paso de fin de combate - + second main phase segunda fase principal - + It is now the %1. Ahora es el %1. - + taps gira - + untaps endereza - + %1 sets %2 to not untap normally. %1 establece que %2 no se endereze normalmente. - + %1 sets %2 to untap normally. %1 establece que %2 se endereze normalmente. - + his permanents sus permanentes @@ -2096,22 +2109,22 @@ La versión local es %1, la versión remota es %2. MessagesSettingsPage - + &Add &Añadir - + &Remove &Quitar - + Add message Añadir mensaje - + Message: Mensaje: @@ -2455,7 +2468,7 @@ La versión local es %1, la versión remota es %2. - + Number: Número: @@ -2480,27 +2493,27 @@ La versión local es %1, la versión remota es %2. Número de caras: - + Set power/toughness Establecer fuerza/resistencia - + Please enter the new PT: Por favor, introduzca la nueva F/R: - + Set annotation Escribir anotación - + Please enter the new annotation: Por favor, introduza la nueva anotación: - + Set counters Establecer contadores @@ -3074,25 +3087,40 @@ Por favor, introduzca un nombre: UserInterfaceSettingsPage - + General interface settings Preferencias generales de la interfaz - + &Double-click cards to play them (instead of single-click) &Doble click en las cartas para jugarlas (en lugar de un solo click) - + Animation settings Opciones de animación - + &Tap/untap animation Animación de &girar/enderezar + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + Elija ruta + UserList diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index f78ae31e8..9ade97a4f 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -951,54 +951,54 @@ DlgSettings - - - + + + Error Erreur - + Your card database is invalid. Would you like to go back and set the correct path? Votre base de carte est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Le chemin d'accès pour le répertoire de votre deck est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Le chemin d'accès pour le répertoire de vos images est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + Settings Paramètres - + General Géneral - + Appearance Apparence - + User interface Interface utilisateur - + Messages Messages - + &Close &Fermer @@ -1454,103 +1454,103 @@ La version la plus récente est %1, l'ancienne version est %2. MessageLogWidget - + Connecting to %1... Connexion à %1... - + Connected. Connecté. - + Disconnected from server. Déconnecté du serveur. - + Invalid password. Mot de passe invalide. - + Protocol version mismatch. Client: %1, Server: %2 Version de protocole différente. Version locale: %1 ,version distante: %2 - + Protocol error. Erreur de protocole. - + You have joined game #%1. Vous avez rejoint la partie #%1. - + %1 has joined the game. %1 a rejoint la partie. - + %1 has left the game. %1 a quitté la partie. - + The game has been closed. La partie a été fermée. - + %1 is now watching the game. %1 est maintenant spectateur. - + %1 is not watching the game any more. %1 n'est plus spectateur. - + %1 has loaded a local deck. %1 a chargé un deck local. - + %1 has loaded deck #%2. %1 a chargé le deck #%2. - + %1 is ready to start the game. %1 est prêt à démarrer la partie. - + %1 is not ready to start the game any more. %1 n'est plus prêt à démarrer la partie. - + %1 has conceded the game. partie ou jeu %1 a concédé la partie. - + The game has started. La partie commence. - + %1 shuffles his library. %1 mélange sa bibliothèque. - + %1 rolls a %2 with a %3-sided die. is it always a dice? %1 lance un %2 à %3 faces. @@ -1564,124 +1564,124 @@ La version la plus récente est %1, l'ancienne version est %2.%1 pioche %2 cartes. - + from table depuis le champ de bataille - + from graveyard depuis son cimetière - + from exile depuis la zone exil - + from hand depuis sa main - + the bottom card of his library la carte du dessous de sa bibliothèque - + from the bottom of his library du dessous de sa bibliothèque - + the top card of his library le carte du dessus de sa bibliothèque - + from the top of his library du dessus de sa bibliothèque - + from library depuis sa bibliothèque - + from sideboard depuis sa réserve - + from the stack depuis la pile - + %1 puts %2 into play tapped%3. %1 met %2 en jeu engagé%3. - + %1 puts %2 into play%3. what is %3? plz exemple (resp. by Ranma : XX met island en jeu -depuis sa main-.) %1 met %2 en jeu %3. - + %1 puts %2%3 into graveyard. %1 met %2%3 dans son cimetière. - + %1 exiles %2%3. %1 exile %2%3. - + %1 moves %2%3 to hand. %1 met %2%3 dans sa main. - + %1 puts %2%3 into his library. %1 met %2%3 dans sa bibliothèque. - + %1 puts %2%3 on bottom of his library. %1 met %2%3 en-dessous de sa bibliothèque. - + %1 puts %2%3 on top of his library. %1 met %2%3 au-dessus de sa bibliothèque. - + %1 puts %2%3 into his library at position %4. %1 met %2%3 dans sa bibliothèque à la position n°%4. - + %1 moves %2%3 to sideboard. %1 met %2%3 à sa réserve. - + %1 plays %2%3. %1 joue %2%3. - - + + a card une carte - + %1 draws %n card(s). %1 pioche %n carte. @@ -1689,59 +1689,72 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 undoes his last draw. %1 annule sa dernière pioche. - + %1 undoes his last draw (%2). %1 annule sa dernière pioche (%2). - + %1 gives %2 control over %3. %1 donne le contrôle de %2 à %3. + + + %1 takes a mulligan to %n. + + + + + - + + %1 draws his initial hand. + + + + %1 flips %2 face-down. %1 retourne %2 face cachée. - + %1 flips %2 face-up. %1 retourne %2 face visible. - + %1 destroys %2. %1 détruit %2. - + %1 attaches %2 to %3's %4. need exemple (Resp'.by Ranma: JoueurA attache Adventuring Gear sur -Plated Geopede- de -JoueurB-.) %1 attache %2 sur %4 de %3. - + %1 unattaches %2. %1 détache %2. - + %1 creates token: %2%3. %1 crée un jeton %2%3. - + %1 points from %2's %3 to %4. need exemple %1 désigne le %3 de %2 à %4. - + %1 points from %2's %3 to %4's %5. need exemple %1 désigne le %3 de %2 à %5 de %4. @@ -1763,7 +1776,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 places %n %2 counter(s) on %3 (now %4). %1 met %n %2 marqueur sur %3 (maintenant %4). @@ -1771,7 +1784,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 retire %n %2 marqueur de %3 (maintenant %4). @@ -1779,7 +1792,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + red rouge @@ -1787,7 +1800,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + yellow jaune @@ -1795,7 +1808,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + green vert @@ -1803,164 +1816,164 @@ La version la plus récente est %1, l'ancienne version est %2. - + his permanents ses permanents - + %1 %2 %3. wtf ? %1 %2 %3. - + taps engage - + untaps dégage - + %1 sets counter %2 to %3 (%4%5). need exemple %1 met les marqueurs %2 à %3 (%4%5). - + %1 sets %2 to not untap normally. need exemple %2 de %1 ne se dégagera pas lors de l'étape de dégagement. - + %1 sets %2 to untap normally. %2 de %1 se dégagera lors de l'étape de dégagement. - + %1 sets PT of %2 to %3. exemple plz %1 change la F/E de %2 à %3. - + %1 sets annotation of %2 to %3. %1 met l'annotation %3 à %2. - + %1 is looking at the top %2 cards %3. exemple plz %1 regarde les %2 cartes du dessus %3. - + %1 is looking at %2. exemple plz %1 regarde %2. - + %1 stops looking at %2. need exemple to be sure %1 arrête de regarder %2. - + %1 reveals %2 to %3. %1 révèle %2 à %3. - + %1 reveals %2. %1 révèle %2. - + %1 randomly reveals %2%3 to %4. %1 révèle au hasard %2%3 à %4. - + %1 randomly reveals %2%3. %1 révèle au hasard %2%3. - + %1 reveals %2%3 to %4. %1 révèle %2%3 à %4. - + %1 reveals %2%3. %1 révèle %2%3. - + It is now %1's turn. C'est maintenant le tour de %1. - + untap step étape de dégagement - + upkeep step étape d'entretien - + draw step étape de pioche - + first main phase première phase principale - + beginning of combat step étape de début du combat - + declare attackers step étape de déclaration des attaquants - + declare blockers step étape de déclaration des bloqueurs - + combat damage step étape de répartition et de résolution des blessures - + end of combat step étape de fin de combat - + second main phase seconde phase principale - + ending phase phase de fin de tour - + It is now the %1. need exemple C'est maintenant %1. @@ -1969,22 +1982,22 @@ La version la plus récente est %1, l'ancienne version est %2. MessagesSettingsPage - + Add message Ajouter message - + Message: Message: - + &Add &Ajouter - + &Remove &Enlever @@ -2320,7 +2333,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + Number: Nombre: @@ -2345,28 +2358,28 @@ La version la plus récente est %1, l'ancienne version est %2.Nombre de faces: - + Set power/toughness Fixer force/endurance - + Please enter the new PT: maybe better with / Entrer la nouvelle F/E: - + Set annotation Mettre une note - + Please enter the new annotation: Entrez la nouvelle note: - + Set counters Mettre des marqueurs @@ -2935,25 +2948,40 @@ Entrez un nom s'il vous plaît: UserInterfaceSettingsPage - + General interface settings Réglages généraux de l'interface - + &Double-click cards to play them (instead of single-click) &Double cliquer sur la carte pour la jouer (au lieu d'un simple clic) - + Animation settings Réglage des animations - + &Tap/untap animation &Animation d'engagement et de dégagement + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + + UserList diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index cea482a4d..eaed4215b 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -938,54 +938,54 @@ DlgSettings - - - + + + Error エラー - + Your card database is invalid. Would you like to go back and set the correct path? あなたのカードデータベースは無効です.前に戻って正しいパスを設定してください. - + The path to your deck directory is invalid. Would you like to go back and set the correct path? あなたのデッキディレクトリへのパスは無効です.前に戻って正しいパスを設定してください. - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? あなたのカード画像ディレクトリへのパスは無効です.前に戻って正しいパスを設定してください. - + Settings 設定 - + General 全般 - + Appearance 外観 - + User interface ユーザーインターフェース - + Messages メッセージ - + &Close @@ -1431,210 +1431,210 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). - + %1 undoes his last draw. - + %1 undoes his last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + from the bottom of his library - + the top card of his library - + from the top of his library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 into his library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1651,262 +1651,274 @@ Local version is %1, remote version is %2. - + red - + yellow - + green - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. + + + %1 takes a mulligan to %n. + + + + - + + %1 draws his initial hand. + + + + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). - + %1 removes %n %2 counter(s) from %3 (now %4). - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 shuffles his library. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -1914,22 +1926,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + &Add 追加 - + &Remove 削除 - + Add message メッセージを追加する - + Message: メッセージ: @@ -2265,7 +2277,7 @@ Local version is %1, remote version is %2. - + Number: 枚数 @@ -2290,27 +2302,27 @@ Local version is %1, remote version is %2. 面の数: - + Set power/toughness パワーとタフネスを設定する - + Please enter the new PT: 新しいP/Tを入力してください - + Set annotation 補足を付ける - + Please enter the new annotation: 新しい補足を付けてください - + Set counters カウンターを設定する @@ -2867,25 +2879,40 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings インターフェース総合設定 - + &Double-click cards to play them (instead of single-click) ダブルクリックでカードをプレイする(シングルクリックの代わり) - + Animation settings アニメーション設定 - + &Tap/untap animation タップ/アンタップアニメーション + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + + UserList diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 4e9b7d752..507edcb34 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -955,54 +955,54 @@ DlgSettings - - - + + + Error Erro - + Your card database is invalid. Would you like to go back and set the correct path? O seu banco de dados de cards é inválido. Você gostaria de voltar e corrigir o caminho? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? O caminho para a sua pasta de decks é inválido. Você gostaria de voltar e corrigir o caminho? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? O caminho para a sua pasta de imagens de cards é inválido. Você gostaria de voltar e corrigir o caminho? - + Settings Configurações - + General Geral - + Appearance Aparência - + User interface Interface do usuário - + Messages Mensagens - + &Close &Fechar @@ -1455,52 +1455,52 @@ A versão local é %1 e a versão remota é %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado do servidor. - + Invalid password. Senha incorreta. - + Protocol error. Erro de protocolo. - + The game has been closed. O jogo foi fechado. - + %1 is now watching the game. %1 está assistindo o jogo agora. - + %1 is not watching the game any more. %1 não está mais assistindo o jogo. - + %1 is not ready to start the game any more. %1 não está mais pronto para começar o jogo. - + %1 rolls a %2 with a %3-sided die. %1 tirou um %2 com um dado de %3 lados. - + %1 draws %n card(s). %1 compra %n card. @@ -1508,158 +1508,158 @@ A versão local é %1 e a versão remota é %2. - + %1 undoes his last draw. %1 desfaz sua última compra. - + %1 undoes his last draw (%2). %1 desfaz sua última compra (%2). - + from table vindo do campo de batalha - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library o card do fundo do seu grimório - + from the bottom of his library vindo do fundo do seu grimório - + the top card of his library o card do topo do seu grimório - + from the top of his library vindo do topo do seu grimório - + from library vindo do grimório - + from sideboard vindo do sideboard - + from the stack vindo da pilha - + %1 gives %2 control over %3. %1 dá controle para %2 sobre %3. - + %1 puts %2 into play tapped%3. %1 põe %2 em jogo virado%3. - + %1 puts %2 into play%3. %1 põe %2 no campo de batalha %3. - + %1 puts %2%3 into graveyard. %1 põe %2 no cemitério%3. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2 para a mão%3. - + %1 puts %2%3 into his library. %1 põe %2 no seu grimório%3. - + %1 puts %2%3 on bottom of his library. %1 põe %2 no fundo do seu grimório%3. - + %1 puts %2%3 on top of his library. %1 põe %2 no topo do seu grimório%3. - + %1 puts %2%3 into his library at position %4. %1 põe %2 no seu grimório na posição %4%3. - + %1 moves %2%3 to sideboard. %1 move %2 para o sideboard%3. - + %1 plays %2%3. %1 põe %2 na pilha%3. - - + + a card um card - + %1 flips %2 face-down. %1 vira %2 para baixo. - + %1 flips %2 face-up. %1 vira %2 para cima. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 aponta para %5 de %4 com %3 de %2. @@ -1678,7 +1678,7 @@ A versão local é %1 e a versão remota é %2. - + red vermelho @@ -1686,7 +1686,7 @@ A versão local é %1 e a versão remota é %2. - + yellow amarelo @@ -1694,7 +1694,7 @@ A versão local é %1 e a versão remota é %2. - + green verde @@ -1702,72 +1702,72 @@ A versão local é %1 e a versão remota é %2. - + %1 sets counter %2 to %3 (%4%5). %1 altera o marcador %2 para %3 (%4%5). - + %1 sets PT of %2 to %3. %1 altera o P/R de %2 para %3. - + %1 sets annotation of %2 to %3. %1 altera a nota de %2 para%3. - + %1 is looking at the top %2 cards %3. %1 está olhando para os %2 cards do topo %3. - + The game has started. O jogo começou. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + You have joined game #%1. Você entrou no jogo nº %1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 saiu do jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck nº %2. - + %1 is ready to start the game. %1 está pronto para começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. @@ -1780,22 +1780,22 @@ A versão local é %1 e a versão remota é %2. %1 compra %2 cards. - + %1 destroys %2. %1 destrói %2. - + %1 creates token: %2%3. %1 cria a ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta para %4 com %3 de %2 . - + %1 places %n %2 counter(s) on %3 (now %4). %1 põe %n marcador %2 em %3 (agora %4). @@ -1803,7 +1803,7 @@ A versão local é %1 e a versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 tira %n marcador %2 em %3 (agora %4). @@ -1811,142 +1811,155 @@ A versão local é %1 e a versão remota é %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está olhando para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 para %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase final - + It is now %1's turn. Agora é o turno de %1. - + %1 shuffles his library. %1 embaralha o seu grimório. + + + %1 takes a mulligan to %n. + + + + + - + + %1 draws his initial hand. + + + + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3. para %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 para %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step etapa de desvirar - + upkeep step etapa de manutenção - + draw step etapa de compra - + first main phase primeira fase principal - + beginning of combat step etapa de início de combate - + declare attackers step etapa de declaracão de atacantes - + declare blockers step etapa de declaração de bloqueadores - + combat damage step etapa de dano de combate - + end of combat step etapa de fim de combate - + second main phase segunda fase principal - + It is now the %1. Agora é a %1. - + taps vira - + untaps desvira - + %1 sets %2 to not untap normally. %1 define que %2 não desvira normalmente. - + %1 sets %2 to untap normally. %1 define que %2 desvira normalmente. - + his permanents as suas permanentes @@ -1954,22 +1967,22 @@ A versão local é %1 e a versão remota é %2. MessagesSettingsPage - + &Add &Adicionar - + &Remove &Remover - + Add message Adicionar mensagem - + Message: Mensagem: @@ -2305,7 +2318,7 @@ A versão local é %1 e a versão remota é %2. - + Number: Número: @@ -2330,27 +2343,27 @@ A versão local é %1 e a versão remota é %2. Número de lados: - + Set power/toughness Alterar poder/resistência - + Please enter the new PT: Por favor, entre com o novo P/R: - + Set annotation Alterar nota - + Please enter the new annotation: Por favor, entre com a nova nota: - + Set counters Alterar marcadores @@ -2916,25 +2929,40 @@ Por favor, entre um nome: UserInterfaceSettingsPage - + General interface settings Configurações gerais de interface - + &Double-click cards to play them (instead of single-click) &Duplo clique nos cards para jogá-los (ao invés de clique simples) - + Animation settings Configurações de animação - + &Tap/untap animation Animação de &virar/desvirar + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + Escolher caminho + UserList diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 4c85f4c83..cef7cf2c6 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -955,54 +955,54 @@ DlgSettings - - - + + + Error Erro - + Your card database is invalid. Would you like to go back and set the correct path? A sua base de dados é inválida. Gostaria de voltar atrás e corrigir o directório? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? O directório do seu deck é inválido. Gostaria de voltar atrás e corrigir o directório? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? O directório das imagens das cartas é inválido. Gostaria de voltar atrás e corrigir o directório? - + Settings Definições - + General Geral - + Appearance Aparência - + User interface Interface do utilizador - + Messages Mensagens - + &Close &Fechar @@ -1459,102 +1459,102 @@ Versão local é %1, versão remota é %2. MessageLogWidget - + Connecting to %1... Ligando a %1... - + Connected. Ligado. - + Disconnected from server. Desligado do servidor. - + Invalid password. Password incorrecto. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + Protocol error. Erro de protocolo. - + You have joined game #%1. Você entrou no jogo #%1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 abandonou o jogo. - + The game has been closed. Este jogo foi encerrado. - + %1 is now watching the game. %1 está agora a ver o jogo. - + %1 is not watching the game any more. %1 já não está a ver o jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck #%2. - + %1 is ready to start the game. %1 está pronto a começar o jogo. - + %1 is not ready to start the game any more. %1 já não está pronto a começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. - + The game has started. O jogo começou. - + %1 shuffles his library. %1 baralha o grimório. - + %1 rolls a %2 with a %3-sided die. %1 obteve %2 com um dado de %3 faces. @@ -1567,117 +1567,130 @@ Versão local é %1, versão remota é %2. %1 compra %2 cartas. - + from table vindo da mesa - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library a carta do fundo do seu grimório - + from the bottom of his library do fundo do seu grimório - + the top card of his library a carta do topo do seu grimório - + from the top of his library do topo do seu grimório - + from library do grimório - + from sideboard do sideboard - + from the stack da pilha - + %1 puts %2 into play tapped%3. %1 coloca %2 em jogo virado(a)%3. - + %1 puts %2 into play%3. %1 coloca %2 em jogo %3. - + %1 puts %2%3 into graveyard. %1 coloca %2%3 no cemitério. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2%3 para a mão. - + %1 puts %2%3 into his library. %1 coloca %2%3 no seu grimório. - + %1 puts %2%3 on bottom of his library. %1 coloca %2%3 no fundo do seu grimório. - + %1 puts %2%3 on top of his library. %1 coloca %2%3 no topo do seu grimório. - + %1 puts %2%3 into his library at position %4. %1 coloca %2%3 no seu grimório na posição %4. - + %1 moves %2%3 to sideboard. %1 move %2%3 para o sideboard. - + %1 plays %2%3. %1 joga %2%3. - + + %1 takes a mulligan to %n. + + + + + + + + %1 draws his initial hand. + + + + %1 places %n %2 counter(s) on %3 (now %4). %1 coloca %n %2 marcador em %3 (agora com %4). @@ -1685,7 +1698,7 @@ Versão local é %1, versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remove %n %2 marcador de %3 (agora com %4). @@ -1693,13 +1706,13 @@ Versão local é %1, versão remota é %2. - - + + a card uma carta - + %1 draws %n card(s). %1 compra %n carta. @@ -1707,57 +1720,57 @@ Versão local é %1, versão remota é %2. - + %1 undoes his last draw. %1 desfaz a sua última compra. - + %1 undoes his last draw (%2). %1 desfaz a sua última compra (%2). - + %1 gives %2 control over %3. %1 dá controlo sobre %3 a %2. - + %1 flips %2 face-down. %1 volta a face de %2 para baixo. - + %1 flips %2 face-up. %1 volta a face de %2 para cima. - + %1 destroys %2. %1 destrói %2. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 creates token: %2%3. %1 cria ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta de %3 de %2 para %4. - + %1 points from %2's %3 to %4's %5. %1 aponta de %3 de %2 para %5 de %4. @@ -1776,7 +1789,7 @@ Versão local é %1, versão remota é %2. - + red vermelho @@ -1784,7 +1797,7 @@ Versão local é %1, versão remota é %2. - + yellow amarelo @@ -1792,7 +1805,7 @@ Versão local é %1, versão remota é %2. - + green verde @@ -1800,157 +1813,157 @@ Versão local é %1, versão remota é %2. - + his permanents as suas permanentes - + %1 %2 %3. %1 %2 %3. - + taps vira - + untaps desvira - + %1 sets counter %2 to %3 (%4%5). %1 altera o número de marcadores %2 para %3(%4%5). - + %1 sets %2 to not untap normally. %1 define %2 para não desvirar normalmente. - + %1 sets %2 to untap normally. %1 define %2 para desvirar normalmente. - + %1 sets PT of %2 to %3. %1 define o P/R de %2 como %3. - + %1 sets annotation of %2 to %3. %1 coloca uma nota de %2 em%3. - + %1 is looking at the top %2 cards %3. %1 está a olhar para as %2 cartas do topo %3. - + %1 is looking at %2. %1 está a olhar para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + %1 randomly reveals %2%3 to %4. %1 revela aleatoreamente %2%3. a %4. - + %1 randomly reveals %2%3. %1 revela aleatoreamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + It is now %1's turn. É agora o turno de %1. - + untap step Etapa de Desvirar - + upkeep step Etapa de Manutenção - + draw step Etapa de Compra - + first main phase 1ª Fase Principal (pré-combate) - + beginning of combat step Etapa de Início de Combate - + declare attackers step Etapa de Declaração de Atacantes - + declare blockers step Etapa de Declaração de Bloqueadores - + combat damage step Etapa de Dano de Combate - + end of combat step Etapa de Fim de Combate - + second main phase 2ª Fase Principal (pós-combate) - + ending phase Fase Final - + It is now the %1. É agora a %1. @@ -1958,22 +1971,22 @@ Versão local é %1, versão remota é %2. MessagesSettingsPage - + Add message Adicionar mensagem - + Message: Mensagem: - + &Add &Adicionar - + &Remove &Remover @@ -2309,7 +2322,7 @@ Versão local é %1, versão remota é %2. - + Number: Número: @@ -2334,27 +2347,27 @@ Versão local é %1, versão remota é %2. Número de faces: - + Set power/toughness Definir poder/resistência - + Please enter the new PT: Por favor introduza o novo P/R: - + Set annotation Colocar nota - + Please enter the new annotation: Por favor introduza a nova nota: - + Set counters Definir marcadores @@ -2920,25 +2933,40 @@ Por favor introduza um nome: UserInterfaceSettingsPage - + General interface settings Configurações gerais da interface - + &Double-click cards to play them (instead of single-click) Clicar &duas vezes nas cartas para as jogar (ao invés de clicar apenas uma vez) - + Animation settings Configurações de Animações - + &Tap/untap animation Animação de &virar/desvirar + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + Escolher directório + UserList diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index b0f24d6aa..0f21ddfd0 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -894,54 +894,54 @@ DlgSettings - - - + + + Error Ошибка - + Your card database is invalid. Would you like to go back and set the correct path? База карт не найдена. Вернуться и задать правильный путь? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Ваши колоды отсутствуют в указанной папке. Вернуться и задать правильный путь? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Изображения карт не найдены. Вернуться и задать правильный путь? - + Settings Настройки - + General Основные - + Appearance Внешний вид - + User interface Интерфейс - + Messages Сообщения - + &Close &Закрыть @@ -1382,102 +1382,102 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... Подключение к %1... - + Connected. Подключено. - + Disconnected from server. Нет соединения с сервером. - + Invalid password. Неверный пароль. - + Protocol version mismatch. Client: %1, Server: %2 Несовпадение версий. Клиент: %1, Сервер: %2 - + Protocol error. Ошибка протокола. - + You have joined game #%1. Вы присоединились к игре #%1. - + %1 has joined the game. %1 присоединился к игре. - + %1 has left the game. %1 покиул игру. - + The game has been closed. Игра закрыта. - + %1 is now watching the game. %1 вошел как зритель. - + %1 is not watching the game any more. %1 покинул зрительскую ложу. - + %1 has loaded a local deck. %1 загрузил колоду с диска. - + %1 has loaded deck #%2. %1 загрузил колоду #%2. - + %1 is ready to start the game. %1 готов начать игру. - + %1 is not ready to start the game any more. %1 все еще не готов. - + %1 has conceded the game. %1 решил сдаться. - + The game has started. Игра началась. - + %1 shuffles his library. %1 размешивает библиотеку. - + %1 rolls a %2 with a %3-sided die. %1 выкинул %2 / %3. @@ -1490,168 +1490,168 @@ Local version is %1, remote version is %2. %1 взял %2 карт. - + %1 undoes his last draw. %1 отменил последнее взятие. - + %1 undoes his last draw (%2). %1 отменил %2 последних взятий. - + from table с поля битвы - + from graveyard из кладбища - + from exile из изгнания - + from hand из руки - + the bottom card of his library нижнюю карту своей библиотеки - + from the bottom of his library со дна своей библиотеки - + the top card of his library верхнюю карту своей библиотеки - + from the top of his library с верха своей библиотеки - + from library из библиотеки - + from sideboard из сайда - + from the stack из стека - - + + a card карту - + %1 gives %2 control over %3. %1 передает %2 контроль над %3. - + %1 puts %2 into play%3. %1 поместил %2 на поле битвы %3. - + %1 puts %2%3 into graveyard. %1 поместил %2%3 на кладбище. - + %1 exiles %2%3. %1 изгоняет %2%3. - + %1 moves %2%3 to hand. %1 поместил %2%3 в руку. - + %1 puts %2%3 into his library. %1 поместил %2%3 в свою библиотеку. - + %1 puts %2%3 on bottom of his library. %1 поместил %2%3 на дно своей библиотеки. - + %1 puts %2%3 on top of his library. %1 поместил %2%3 на верх своей библиотеки. - + %1 puts %2%3 into his library at position %4. %1 поместил %2%3 в свою библиотеку %4 сверху. - + %1 moves %2%3 to sideboard. %1 поместил %2%3 в сайд. - + %1 plays %2%3. %1 разыгрывает %2%3. - + %1 flips %2 face-down. %1 перевернул %2 лицом вниз. - + %1 flips %2 face-up. %1 перевернул %2 лицом вверх. - + %1 destroys %2. %1 уничтожил %2. - + %1 attaches %2 to %3's %4. %1 присоединил %2 к %4 игрока %3. - + %1 unattaches %2. %1 отсоединил %2. - + %1 creates token: %2%3. %1 создал фишку: %2%3. - + %1 points from %2's %3 to %4. %1 указывает с %3 контролируемого %2 на %4. - + %1 points from %2's %3 to %4's %5. %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. @@ -1672,7 +1672,7 @@ Local version is %1, remote version is %2. - + %1 draws %n card(s). %1 взял %n карту. @@ -1681,12 +1681,26 @@ Local version is %1, remote version is %2. - + %1 puts %2 into play tapped%3. %1 положил %2 повернутым на поле битвы%3. - + + %1 takes a mulligan to %n. + + + + + + + + + %1 draws his initial hand. + + + + %1 places %n %2 counter(s) on %3 (now %4). %1 поместил %n %2 жетон на %3 (теперь %4). @@ -1695,7 +1709,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 снял %n %2 жетон с %3 (теперь %4). @@ -1704,7 +1718,7 @@ Local version is %1, remote version is %2. - + red красный @@ -1713,7 +1727,7 @@ Local version is %1, remote version is %2. - + yellow желтый @@ -1722,7 +1736,7 @@ Local version is %1, remote version is %2. - + green зеленый @@ -1731,157 +1745,157 @@ Local version is %1, remote version is %2. - + his permanents свои перманенты - + %1 %2 %3. %1 %2 %3. - + taps повернул - + untaps развернул - + %1 sets counter %2 to %3 (%4%5). %1 установил жетон %2 на %3 (%4%5). - + %1 sets %2 to not untap normally. %2 теперь не разворачивается как обычно (%1). - + %1 sets %2 to untap normally. %2 теперь разворачивается как обычно (%1). - + %1 sets PT of %2 to %3. %1 установил Силу/Защиту %2 %3. - + %1 sets annotation of %2 to %3. %1 сделал пометку на %2 "%3". - + %1 is looking at the top %2 cards %3. %1 смотрит верхние %2 карт библиотеки %3. - + %1 is looking at %2. %1 просматривает %2. - + %1 stops looking at %2. %1 закончил просматривать %2. - + %1 reveals %2 to %3. %1 показывает его %2 %3. - + %1 reveals %2. %1 открыл его %2. - + %1 randomly reveals %2%3 to %4. %1 показывает случайно выбранную%3 карту (%2) %4. - + %1 randomly reveals %2%3. %1 открывает случайно выбранную%3 карту (%2). - + %1 reveals %2%3 to %4. %1 показывает%2%3 %4. - + %1 reveals %2%3. %1 открывает%2%3. - + It is now %1's turn. Ход игрока %1. - + untap step шаг разворота - + upkeep step шаг поддержки - + draw step шаг взятия карты - + first main phase первая главная фаза - + beginning of combat step шаг начала битвы - + declare attackers step шаг назначения атакующих - + declare blockers step шаг назначения блокирующих - + combat damage step шаг нанесения повреждений - + end of combat step шаг завершения битвы - + second main phase вторая главная фаза - + ending phase заключительный шаг - + It is now the %1. Сейчас %1. @@ -1889,22 +1903,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Add message Добавить сообщение - + Message: Сообщение: - + &Add &Добавить - + &Remove &Удалить @@ -2240,7 +2254,7 @@ Local version is %1, remote version is %2. - + Number: Количество: @@ -2265,27 +2279,27 @@ Local version is %1, remote version is %2. Количество граней: - + Set power/toughness Установить Силу/Защиту - + Please enter the new PT: Введите новые Силу/Защиту: - + Set annotation Пометка - + Please enter the new annotation: Введите текст: - + Set counters Установить жетоны @@ -2809,25 +2823,40 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings Основные настройки интерфейса - + &Double-click cards to play them (instead of single-click) &Двойной клик чтобы разыграть карту (вместо одинарного) - + Animation settings Настройки анимации - + &Tap/untap animation &Анимировать поворот/разворот карты + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + + UserList diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h index d45045d02..2d89e883c 100644 --- a/common/protocol_item_ids.h +++ b/common/protocol_item_ids.h @@ -76,7 +76,8 @@ ItemId_Context_Concede = 1074, ItemId_Context_DeckSelect = 1075, ItemId_Context_UndoDraw = 1076, ItemId_Context_MoveCard = 1077, -ItemId_Command_UpdateServerMessage = 1078, -ItemId_Command_BanFromServer = 1079, -ItemId_Other = 1080 +ItemId_Context_Mulligan = 1078, +ItemId_Command_UpdateServerMessage = 1079, +ItemId_Command_BanFromServer = 1080, +ItemId_Other = 1081 }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index c75a991ed..17aea3839 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -458,6 +458,11 @@ Context_MoveCard::Context_MoveCard() : GameEventContext("move_card") { } +Context_Mulligan::Context_Mulligan(int _number) + : GameEventContext("mulligan") +{ + insertItem(new SerializableItem_Int("number", _number)); +} Command_UpdateServerMessage::Command_UpdateServerMessage() : AdminCommand("update_server_message") { @@ -547,6 +552,7 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("game_event_contextdeck_select", Context_DeckSelect::newItem); itemNameHash.insert("game_event_contextundo_draw", Context_UndoDraw::newItem); itemNameHash.insert("game_event_contextmove_card", Context_MoveCard::newItem); + itemNameHash.insert("game_event_contextmulligan", Context_Mulligan::newItem); itemNameHash.insert("cmdupdate_server_message", Command_UpdateServerMessage::newItem); itemNameHash.insert("cmdban_from_server", Command_BanFromServer::newItem); } diff --git a/common/protocol_items.dat b/common/protocol_items.dat index 4e37333df..73369c6b4 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -75,5 +75,6 @@ 6:deck_select:i,deck_id 6:undo_draw 6:move_card +6:mulligan:i,number 7:update_server_message 7:ban_from_server:s,user_name:i,minutes \ No newline at end of file diff --git a/common/protocol_items.h b/common/protocol_items.h index 14d6eb1ff..d58d3dec8 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -691,6 +691,14 @@ public: static SerializableItem *newItem() { return new Context_MoveCard; } int getItemId() const { return ItemId_Context_MoveCard; } }; +class Context_Mulligan : public GameEventContext { + Q_OBJECT +public: + Context_Mulligan(int _number = -1); + int getNumber() const { return static_cast(itemMap.value("number"))->getData(); }; + static SerializableItem *newItem() { return new Context_Mulligan; } + int getItemId() const { return ItemId_Context_Mulligan; } +}; class Command_UpdateServerMessage : public AdminCommand { Q_OBJECT public: diff --git a/common/server_player.cpp b/common/server_player.cpp index 0a6dc8aca..e56953803 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -402,6 +402,7 @@ ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *st if (card->getDestroyOnZoneChange() && (startzone->getName() != targetzone->getName())) { cont->enqueueGameEventPrivate(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), -1, new Context_MoveCard); + cont->enqueueGameEventOmniscient(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), new Context_MoveCard); cont->enqueueGameEventPublic(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), new Context_MoveCard); card->deleteLater(); } else { diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index dd5d0dd8f..8580ef283 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -632,9 +632,16 @@ ResponseCode Server_ProtocolHandler::cmdMulligan(Command_Mulligan * /*cmd*/, Com deck->shuffle(); cont->enqueueGameEventPrivate(new Event_Shuffle(player->getPlayerId()), game->getGameId()); + cont->enqueueGameEventOmniscient(new Event_Shuffle(player->getPlayerId()), game->getGameId()); cont->enqueueGameEventPublic(new Event_Shuffle(player->getPlayerId()), game->getGameId()); player->drawCards(cont, number); + + if (number == player->getInitialCards()) + number = -1; + cont->getGameEventQueuePrivate()->setContext(new Context_Mulligan(number)); + cont->getGameEventQueuePublic()->setContext(new Context_Mulligan(number)); + cont->getGameEventQueueOmniscient()->setContext(new Context_Mulligan(number)); return RespOk; } From 04a96be84a50e3279c08cd94418d22c9d24c40a9 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Fri, 27 May 2011 21:56:16 +0200 Subject: [PATCH 40/87] fixed doesntUntap bug (with protocol change) --- cockatrice/src/carditem.cpp | 1 + common/protocol_datastructures.cpp | 3 ++- common/protocol_datastructures.h | 3 ++- common/server_game.cpp | 2 +- common/server_protocolhandler.cpp | 6 +++--- servatrice/src/servatrice.cpp | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index 57cef89fe..861943907 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -380,6 +380,7 @@ void CardItem::processCardInfo(ServerInfo_Card *info) setColor(info->getColor()); setTapped(info->getTapped()); setDestroyOnZoneChange(info->getDestroyOnZoneChange()); + setDoesntUntap(info->getDoesntUntap()); } CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown) diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index 687bf8dfa..547c5b937 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -115,7 +115,7 @@ ServerInfo_CardCounter::ServerInfo_CardCounter(int _id, int _value) insertItem(new SerializableItem_Int("value", _value)); } -ServerInfo_Card::ServerInfo_Card(int _id, const QString &_name, int _x, int _y, bool _tapped, bool _attacking, const QString &_color, const QString &_pt, const QString &_annotation, bool _destroyOnZoneChange, const QList &_counters, int _attachPlayerId, const QString &_attachZone, int _attachCardId) +ServerInfo_Card::ServerInfo_Card(int _id, const QString &_name, int _x, int _y, bool _tapped, bool _attacking, const QString &_color, const QString &_pt, const QString &_annotation, bool _destroyOnZoneChange, bool _doesntUntap, const QList &_counters, int _attachPlayerId, const QString &_attachZone, int _attachCardId) : SerializableItem_Map("card") { insertItem(new SerializableItem_Int("id", _id)); @@ -128,6 +128,7 @@ ServerInfo_Card::ServerInfo_Card(int _id, const QString &_name, int _x, int _y, insertItem(new SerializableItem_String("pt", _pt)); insertItem(new SerializableItem_String("annotation", _annotation)); insertItem(new SerializableItem_Bool("destroy_on_zone_change", _destroyOnZoneChange)); + insertItem(new SerializableItem_Bool("doesnt_untap", _doesntUntap)); insertItem(new SerializableItem_Int("attach_player_id", _attachPlayerId)); insertItem(new SerializableItem_String("attach_zone", _attachZone)); insertItem(new SerializableItem_Int("attach_card_id", _attachCardId)); diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 8e3d9826a..066bbc338 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -118,7 +118,7 @@ public: class ServerInfo_Card : public SerializableItem_Map { public: - ServerInfo_Card(int _id = -1, const QString &_name = QString(), int _x = -1, int _y = -1, bool _tapped = false, bool _attacking = false, const QString &_color = QString(), const QString &_pt = QString(), const QString &_annotation = QString(), bool _destroyOnZoneChange = false, const QList &_counterList = QList(), int attachPlayerId = -1, const QString &_attachZone = QString(), int attachCardId = -1); + ServerInfo_Card(int _id = -1, const QString &_name = QString(), int _x = -1, int _y = -1, bool _tapped = false, bool _attacking = false, const QString &_color = QString(), const QString &_pt = QString(), const QString &_annotation = QString(), bool _destroyOnZoneChange = false, bool _doesntUntap = false, const QList &_counterList = QList(), int attachPlayerId = -1, const QString &_attachZone = QString(), int attachCardId = -1); static SerializableItem *newItem() { return new ServerInfo_Card; } int getId() const { return static_cast(itemMap.value("id"))->getData(); } QString getName() const { return static_cast(itemMap.value("name"))->getData(); } @@ -130,6 +130,7 @@ public: QString getPT() const { return static_cast(itemMap.value("pt"))->getData(); } QString getAnnotation() const { return static_cast(itemMap.value("annotation"))->getData(); } bool getDestroyOnZoneChange() const { return static_cast(itemMap.value("destroy_on_zone_change"))->getData(); } + bool getDoesntUntap() const { return static_cast(itemMap.value("doesnt_untap"))->getData(); } QList getCounters() const { return typecastItemList(); } int getAttachPlayerId() const { return static_cast(itemMap.value("attach_player_id"))->getData(); } QString getAttachZone() const { return static_cast(itemMap.value("attach_zone"))->getData(); } diff --git a/common/server_game.cpp b/common/server_game.cpp index a23c2bcb5..74e65ed92 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -415,7 +415,7 @@ QList Server_Game::getGameState(Server_Player *playerWhosAs attachZone = card->getParentCard()->getZone()->getName(); attachCardId = card->getParentCard()->getId(); } - cardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList, attachPlayerId, attachZone, attachCardId)); + cardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterList, attachPlayerId, attachZone, attachCardId)); } } zoneList.append(new ServerInfo_Zone(zone->getName(), zone->getType(), zone->hasCoords(), zone->cards.size(), cardList)); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 8580ef283..a3ced63a5 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -1139,7 +1139,7 @@ ResponseCode Server_ProtocolHandler::cmdDumpZone(Command_DumpZone *cmd, CommandC attachCardId = card->getParentCard()->getId(); } - respCardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterList, attachPlayerId, attachZone, attachCardId)); + respCardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterList, attachPlayerId, attachZone, attachCardId)); } } if (zone->getType() == HiddenZone) { @@ -1227,8 +1227,8 @@ ResponseCode Server_ProtocolHandler::cmdRevealCards(Command_RevealCards *cmd, Co } if (cmd->getPlayerId() != -1) - respCardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterListPrivate, attachPlayerId, attachZone, attachCardId)); - respCardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), cardCounterListOmniscient, attachPlayerId, attachZone, attachCardId)); + respCardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListPrivate, attachPlayerId, attachZone, attachCardId)); + respCardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListOmniscient, attachPlayerId, attachZone, attachCardId)); } if (cmd->getPlayerId() == -1) diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index ca5ef443e..505c6fd0f 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -376,4 +376,4 @@ void Servatrice::statusUpdate() execSqlQuery(query); } -const QString Servatrice::versionString = "Servatrice 0.20110421"; +const QString Servatrice::versionString = "Servatrice 0.20110527"; From 15ca28bf370a4bed1c67c2b71bc17b92354f9f96 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 30 May 2011 15:54:33 +0200 Subject: [PATCH 41/87] hopefully fixed CardInfoPopup freeze --- cockatrice/src/abstractcarditem.cpp | 3 +++ cockatrice/src/messagelogwidget.cpp | 3 ++- cockatrice/src/tab_game.cpp | 3 +-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index 0deed4ea3..020b6dfc0 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -212,6 +212,9 @@ void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + if (event->button() == Qt::MidButton) + emit deleteCardInfoPopup(); + // This function ensures the parent function doesn't mess around with our selection. event->accept(); } diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index a7ab151b6..deafc1751 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -572,7 +572,8 @@ void MessageLogWidget::mousePressEvent(QMouseEvent *event) void MessageLogWidget::mouseReleaseEvent(QMouseEvent *event) { - emit deleteCardInfoPopup(); + if (event->button() == Qt::MidButton) + emit deleteCardInfoPopup(); QTextEdit::mouseReleaseEvent(event); } diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index fd6c76f03..d4aa7b453 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -783,7 +783,7 @@ Player *TabGame::getActiveLocalPlayer() const void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName) { infoPopup = new CardInfoWidget(CardInfoWidget::ModePopUp, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint); - connect(infoPopup, SIGNAL(mouseReleased()), this, SLOT(deleteCardInfoPopup())); + infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents); infoPopup->setCard(cardName); QRect screenRect = qApp->desktop()->screenGeometry(this); infoPopup->show(); @@ -791,7 +791,6 @@ void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName) qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())), qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height())) ); - infoPopup->grabMouse(); } void TabGame::deleteCardInfoPopup() From 7cd4cef9d398213fbfce369430539f0dcc476e88 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 30 May 2011 16:15:01 +0200 Subject: [PATCH 42/87] banning bug fixed --- cockatrice/src/userlist.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index b63c68054..c904513cb 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -217,7 +217,8 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) else if (actionClicked == aBan) { bool ok; int minutes = QInputDialog::getInt(this, tr("Duration"), tr("Please enter the duration of the ban (in minutes).\nEnter 0 for an indefinite ban."), 0, 0, 2147483647, 10, &ok); - client->sendCommand(new Command_BanFromServer(userName, minutes)); + if (ok) + client->sendCommand(new Command_BanFromServer(userName, minutes)); } delete menu; From caf39bc7d36c79b454d2d7648ba0a567b18ba280 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 30 May 2011 23:33:21 +0200 Subject: [PATCH 43/87] fixed CardInfoWidget weirdness --- cockatrice/src/tab_game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index d4aa7b453..e8018c984 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -786,11 +786,11 @@ void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName) infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents); infoPopup->setCard(cardName); QRect screenRect = qApp->desktop()->screenGeometry(this); - infoPopup->show(); infoPopup->move( qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())), qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height())) ); + infoPopup->show(); } void TabGame::deleteCardInfoPopup() From a03bf8884f3469f3e9a09d9fcde61d6c4725a781 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 30 May 2011 23:36:38 +0200 Subject: [PATCH 44/87] updated windows installer --- nsis/cockatrice.nsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nsis/cockatrice.nsi b/nsis/cockatrice.nsi index 6e182a600..8c4c31a68 100644 --- a/nsis/cockatrice.nsi +++ b/nsis/cockatrice.nsi @@ -40,6 +40,7 @@ Section "Application" SecApplication File data\QtNetwork4.dll File data\QtSvg4.dll File data\QtXml4.dll + File data\QtMultimedia4.dll SetOutPath "$INSTDIR\zonebg" File /r ..\zonebg\*.* @@ -47,6 +48,9 @@ Section "Application" SecApplication SetOutPath "$INSTDIR\plugins" File /r data\plugins\*.* + SetOutPath "$INSTDIR\sounds" + File /r ..\sounds\*.* + SetOutPath "$INSTDIR\pics" SetOutPath "$INSTDIR\decks" @@ -77,6 +81,7 @@ SectionEnd Section Uninstall RMDir /r "$INSTDIR\zonebg" RMDir /r "$INSTDIR\plugins" + RMDir /r "$INSTDIR\sounds" RMDir "$INSTDIR\decks" RMDir /r "$INSTDIR\pics\downloadedPics" RMDir "$INSTDIR\pics" From 1bc05562ccc3f9f5ef609cffcf3ef59857dfa34c Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 Jun 2011 19:45:37 +0200 Subject: [PATCH 45/87] Mulligan crash fix, multi-column screen alignment for multiplayer, Server Win32 compile fix --- cockatrice/src/gamescene.cpp | 116 +++++++++++++++++----------- cockatrice/src/gamescene.h | 3 +- cockatrice/src/messagelogwidget.cpp | 6 +- cockatrice/src/player.cpp | 8 +- cockatrice/src/player.h | 2 +- servatrice/src/main.cpp | 2 + servatrice/src/server_logger.cpp | 11 ++- servatrice/src/server_logger.h | 2 + 8 files changed, 93 insertions(+), 57 deletions(-) diff --git a/cockatrice/src/gamescene.cpp b/cockatrice/src/gamescene.cpp index 7b62db5d6..8785adcc8 100644 --- a/cockatrice/src/gamescene.cpp +++ b/cockatrice/src/gamescene.cpp @@ -3,6 +3,7 @@ #include "zoneviewwidget.h" #include "zoneviewzone.h" #include "phasestoolbar.h" +#include #include #include #include @@ -31,7 +32,6 @@ void GameScene::addPlayer(Player *player) qDebug("GameScene::addPlayer"); players << player; addItem(player); - rearrange(); connect(player, SIGNAL(sizeChanged()), this, SLOT(rearrange())); connect(player, SIGNAL(gameConceded()), this, SLOT(rearrange())); } @@ -46,44 +46,63 @@ void GameScene::removePlayer(Player *player) void GameScene::rearrange() { - struct PlayerProcessor { - static void processPlayer(Player *p, qreal &w, QPointF &b, bool singlePlayer) - { - if (p->getConceded()) - return; - - const QRectF br = p->boundingRect(); - if (br.width() > w) - w = br.width(); - p->setPos(b); - p->setMirrored((b.y() < playerAreaSpacing) && !singlePlayer); - b += QPointF(0, br.height() + playerAreaSpacing); - } - }; - - qreal sceneHeight = -playerAreaSpacing; + playersByColumn.clear(); + + QList playersPlaying; + int firstPlayer = -1; for (int i = 0; i < players.size(); ++i) - if (!players[i]->getConceded()) - sceneHeight += players[i]->boundingRect().height() + playerAreaSpacing; + if (!players[i]->getConceded()) { + playersPlaying.append(players[i]); + if ((firstPlayer == -1) && (players[i]->getLocal())) + firstPlayer = playersPlaying.size() - 1; + } + if (firstPlayer == -1) + firstPlayer = 0; + const int playersCount = playersPlaying.size(); + const int columns = playersCount < 4 ? 1 : 2; + const int rows = ceil((qreal) playersCount / columns); + + qreal sceneHeight = 0, sceneWidth = -playerAreaSpacing; + QList columnWidth; + int firstPlayerOfColumn = firstPlayer; + for (int col = 0; col < columns; ++col) { + playersByColumn.append(QList()); + columnWidth.append(0); + qreal thisColumnHeight = -playerAreaSpacing; + const int rowsInColumn = rows - (playersCount % columns); + for (int j = 0; j < rowsInColumn; ++j) { + Player *player = playersPlaying[(firstPlayerOfColumn + j) % playersCount]; + if (col == 0) + playersByColumn[col].prepend(player); + else + playersByColumn[col].append(player); + thisColumnHeight += player->boundingRect().height() + playerAreaSpacing; + if (player->boundingRect().width() > columnWidth[col]) + columnWidth[col] = player->boundingRect().width(); + } + if (thisColumnHeight > sceneHeight) + sceneHeight = thisColumnHeight; + sceneWidth += columnWidth[col] + playerAreaSpacing; + + firstPlayerOfColumn += rowsInColumn; + } + phasesToolbar->setHeight(sceneHeight); qreal phasesWidth = phasesToolbar->getWidth(); - - QPointF base(phasesWidth, 0); - qreal sceneWidth; - QList localPlayers; - - for (int i = 0; i < players.size(); ++i) - if (!players[i]->getLocal()) - PlayerProcessor::processPlayer(players[i], sceneWidth, base, players.size() == 1); - else - localPlayers.append(players[i]); - - for (int i = 0; i < localPlayers.size(); ++i) - PlayerProcessor::processPlayer(localPlayers[i], sceneWidth, base, players.size() == 1); - sceneWidth += phasesWidth; - playersRect = QRectF(0, 0, sceneWidth, sceneHeight); - + + qreal x = phasesWidth; + for (int col = 0; col < columns; ++col) { + qreal y = 0; + for (int row = 0; row < playersByColumn[col].size(); ++row) { + Player *player = playersByColumn[col][row]; + player->setPos(x, y); + player->setMirrored(row != rows - 1); + y += player->boundingRect().height() + playerAreaSpacing; + } + x += columnWidth[col] + playerAreaSpacing; + } + setSceneRect(sceneRect().x(), sceneRect().y(), sceneWidth, sceneHeight); processViewSizeChange(viewSize); } @@ -139,24 +158,33 @@ void GameScene::processViewSizeChange(const QSize &newSize) qreal newRatio = ((qreal) newSize.width()) / newSize.height(); qreal minWidth = 0; - for (int i = 0; i < players.size(); ++i) { - qreal w = players[i]->getMinimumWidth(); - if (w > minWidth) - minWidth = w; + QList minWidthByColumn; + for (int col = 0; col < playersByColumn.size(); ++col) { + minWidthByColumn.append(0); + for (int row = 0; row < playersByColumn[col].size(); ++row) { + qreal w = playersByColumn[col][row]->getMinimumWidth(); + if (w > minWidthByColumn[col]) + minWidthByColumn[col] = w; + } + minWidth += minWidthByColumn[col]; } minWidth += phasesToolbar->getWidth(); qreal minRatio = minWidth / sceneRect().height(); + qreal newWidth; if (minRatio > newRatio) { // Aspect ratio is dominated by table width. - setSceneRect(0, 0, minWidth, sceneRect().height()); + newWidth = minWidth; } else { // Aspect ratio is dominated by window dimensions. - setSceneRect(0, 0, newRatio * sceneRect().height(), sceneRect().height()); + newWidth = newRatio * sceneRect().height(); } - - for (int i = 0; i < players.size(); ++i) - players[i]->processSceneSizeChange(sceneRect().size() - QSizeF(phasesToolbar->getWidth(), 0)); + setSceneRect(0, 0, newWidth, sceneRect().height()); + + qreal extraWidthPerColumn = (newWidth - minWidth) / playersByColumn.size(); + for (int col = 0; col < playersByColumn.size(); ++col) + for (int row = 0; row < playersByColumn[col].size(); ++row) + playersByColumn[col][row]->processSceneSizeChange(minWidthByColumn[col] + extraWidthPerColumn); } void GameScene::updateHover(const QPointF &scenePos) diff --git a/cockatrice/src/gamescene.h b/cockatrice/src/gamescene.h index eee167be5..7b93a35f7 100644 --- a/cockatrice/src/gamescene.h +++ b/cockatrice/src/gamescene.h @@ -22,7 +22,7 @@ private: PhasesToolbar *phasesToolbar; QList players; - QRectF playersRect; + QList > playersByColumn; QList views; QSize viewSize; QPointer hoveredCard; @@ -33,7 +33,6 @@ public: GameScene(PhasesToolbar *_phasesToolbar, QObject *parent = 0); ~GameScene(); void retranslateUi(); - const QRectF &getPlayersRect() const { return playersRect; } void processViewSizeChange(const QSize &newSize); void startRubberBand(const QPointF &selectionOrigin); diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index deafc1751..18cf52b8e 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -4,7 +4,6 @@ #include "cardinfowidget.h" #include "protocol_items.h" #include "soundengine.h" -#include #include #include @@ -264,6 +263,9 @@ void MessageLogWidget::logMoveCard(Player *player, CardItem *card, CardZone *sta void MessageLogWidget::logMulligan(Player *player, int number) { + if (!player) + return; + if (number > -1) append(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); else @@ -468,6 +470,7 @@ void MessageLogWidget::containerProcessingStarted(GameEventContext *_context) currentContext = MessageContext_MoveCard; else if (qobject_cast(_context)) { currentContext = MessageContext_Mulligan; + mulliganPlayer = 0; mulliganNumber = static_cast(_context)->getNumber(); } } @@ -482,6 +485,7 @@ void MessageLogWidget::containerProcessingDone() moveCardTapped.clear(); } else if (currentContext == MessageContext_Mulligan) { logMulligan(mulliganPlayer, mulliganNumber); + mulliganPlayer = 0; mulliganNumber = 0; } diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 1b8ec25bb..d6a349788 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -1007,7 +1007,6 @@ void Player::eventDrawCards(Event_DrawCards *event) hand->reorganizeCards(); deck->reorganizeCards(); - emit logDrawCards(this, event->getNumberCards()); } @@ -1545,12 +1544,9 @@ void Player::setMirrored(bool _mirrored) } } -void Player::processSceneSizeChange(const QSizeF &newSize) +void Player::processSceneSizeChange(int newPlayerWidth) { - // This will need to be changed if player areas are displayed side by side (e.g. 2x2 for a 4-player game) - qreal fullPlayerWidth = newSize.width(); - - qreal tableWidth = fullPlayerWidth - CARD_HEIGHT - 15 - counterAreaWidth - stack->boundingRect().width(); + qreal tableWidth = newPlayerWidth - CARD_HEIGHT - 15 - counterAreaWidth - stack->boundingRect().width(); if (!settingsCache->getHorizontalHand()) tableWidth -= hand->boundingRect().width(); diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index c30fc3760..4096c1e98 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -245,7 +245,7 @@ public: qreal getMinimumWidth() const; void setMirrored(bool _mirrored); - void processSceneSizeChange(const QSizeF &newSize); + void processSceneSizeChange(int newPlayerWidth); void processPlayerInfo(ServerInfo_Player *info); void processCardAttachment(ServerInfo_Player *info); diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index a5ebe207c..a36e33320 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -73,6 +73,7 @@ void myMessageOutput(QtMsgType /*type*/, const char *msg) logger->logMessage(msg); } +#ifdef Q_OS_UNIX void sigSegvHandler(int sig) { if (sig == SIGSEGV) @@ -82,6 +83,7 @@ void sigSegvHandler(int sig) delete loggerThread; raise(sig); } +#endif int main(int argc, char *argv[]) { diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index 0b59c46ab..de08c2881 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -3,8 +3,10 @@ #include #include #include -#include -#include +#ifdef Q_OS_UNIX +# include +# include +#endif ServerLogger::ServerLogger(const QString &logFileName, QObject *parent) : QObject(parent), flushRunning(false) @@ -14,9 +16,10 @@ ServerLogger::ServerLogger(const QString &logFileName, QObject *parent) logFile->open(QIODevice::Append); #ifdef Q_OS_UNIX ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); -#endif + snHup = new QSocketNotifier(sigHupFD[1], QSocketNotifier::Read, this); connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup())); +#endif } else logFile = 0; @@ -62,6 +65,7 @@ void ServerLogger::flushBuffer() } } +#ifdef Q_OS_UNIX void ServerLogger::hupSignalHandler(int /*unused*/) { if (!logFile) @@ -85,6 +89,7 @@ void ServerLogger::handleSigHup() snHup->setEnabled(true); } +#endif QFile *ServerLogger::logFile; int ServerLogger::sigHupFD[2]; diff --git a/servatrice/src/server_logger.h b/servatrice/src/server_logger.h index 3d3d46834..62d785372 100644 --- a/servatrice/src/server_logger.h +++ b/servatrice/src/server_logger.h @@ -19,7 +19,9 @@ public: public slots: void logMessage(QString message); private slots: +#ifdef Q_OS_UNIX void handleSigHup(); +#endif void flushBuffer(); signals: void sigFlushBuffer(); From 9cfe4bea59c8150889545c0b6cc4526e721615e6 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 13 Jun 2011 19:15:12 +0200 Subject: [PATCH 46/87] CardInfoWidget improvement by Absinthe and Hellkeepa --- cockatrice/src/cardinfowidget.cpp | 62 +++++++++++++++++++++++++++++-- cockatrice/src/cardinfowidget.h | 16 +++++++- cockatrice/src/settingscache.cpp | 7 ++++ cockatrice/src/settingscache.h | 3 ++ 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/cockatrice/src/cardinfowidget.cpp b/cockatrice/src/cardinfowidget.cpp index cd51f2350..37b14edfd 100644 --- a/cockatrice/src/cardinfowidget.cpp +++ b/cockatrice/src/cardinfowidget.cpp @@ -11,8 +11,24 @@ #include "settingscache.h" CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlags flags) - : QFrame(parent, flags), pixmapWidth(160), aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH), minimized(false), mode(_mode), info(0) + : QFrame(parent, flags) + , pixmapWidth(160) + , aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH) + , minimized(settingsCache->getCardInfoMinimized()) // Initialize the cardinfo view status from cache. + , mode(_mode) + , info(0) { + if (mode == ModeGameTab) { + // Create indexed list of status views for card. + const QStringList cardInfoStatus = QStringList() << tr("Hide card info") << tr("Show card only") << tr("Show text only") << tr("Show full info"); + + // Create droplist for cardinfo view selection, and set right current index. + dropList = new QComboBox(); + dropList->addItems(cardInfoStatus); + dropList->setCurrentIndex(minimized); + connect(dropList, SIGNAL(currentIndexChanged(int)), this, SLOT(minimizeClicked(int))); + } + cardPicture = new QLabel; cardPicture->setAlignment(Qt::AlignCenter); @@ -33,6 +49,8 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlag QGridLayout *grid = new QGridLayout(this); int row = 0; + if (mode == ModeGameTab) + grid->addWidget(dropList, row++, 1, 1, 1, Qt::AlignRight); grid->addWidget(cardPicture, row++, 0, 1, 2); grid->addWidget(nameLabel1, row, 0); grid->addWidget(nameLabel2, row++, 1); @@ -51,15 +69,51 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlag retranslateUi(); setFrameStyle(QFrame::Panel | QFrame::Raised); - setMinimumHeight(350); if (mode == ModeGameTab) { textLabel->setFixedHeight(100); setFixedWidth(sizeHint().width()); - setMaximumHeight(580); + setMinimized(settingsCache->getCardInfoMinimized()); } else if (mode == ModePopUp) setFixedWidth(350); else setFixedWidth(250); + if (mode != ModeDeckEditor) + setFixedHeight(sizeHint().height()); +} + +void CardInfoWidget::minimizeClicked(int newMinimized) +{ + // Set new status, and store it in the settings cache. + setMinimized(newMinimized); + settingsCache->setCardInfoMinimized(newMinimized); +} + +void CardInfoWidget::setMinimized(int _minimized) +{ + minimized = _minimized; + + // Set the picture to be shown only at "card only" (1) and "full info" (3) + if (minimized == 1 || minimized == 3) { + cardPicture->setVisible(true); + } else { + cardPicture->setVisible(false); + } + + // Set the rest of the fields to be shown only at "full info" (3) and "oracle only" (2) + bool showAll = (minimized == 2 || minimized == 3) ? true : false; + + // Toggle oracle fields as according to selected view. + nameLabel2->setVisible(showAll); + nameLabel1->setVisible(showAll); + manacostLabel1->setVisible(showAll); + manacostLabel2->setVisible(showAll); + cardtypeLabel1->setVisible(showAll); + cardtypeLabel2->setVisible(showAll); + powtoughLabel1->setVisible(showAll); + powtoughLabel2->setVisible(showAll); + textLabel->setVisible(showAll); + + setFixedHeight(sizeHint().height()); } void CardInfoWidget::setCard(CardInfo *card) @@ -112,7 +166,7 @@ void CardInfoWidget::retranslateUi() void CardInfoWidget::resizeEvent(QResizeEvent * /*event*/) { - if ((mode == ModeDeckEditor) || (mode == ModeGameTab)) { + if (mode == ModeDeckEditor) { pixmapWidth = qMin(width() * 0.95, (height() - 200) / aspectRatio); updatePixmap(); } diff --git a/cockatrice/src/cardinfowidget.h b/cockatrice/src/cardinfowidget.h index f71a6c1f5..819f514b0 100644 --- a/cockatrice/src/cardinfowidget.h +++ b/cockatrice/src/cardinfowidget.h @@ -2,6 +2,8 @@ #define CARDINFOWIDGET_H #include +#include +#include class QLabel; class QTextEdit; @@ -13,34 +15,44 @@ class QMouseEvent; class CardInfoWidget : public QFrame { Q_OBJECT + public: enum ResizeMode { ModeDeckEditor, ModeGameTab, ModePopUp }; + private: int pixmapWidth; qreal aspectRatio; - bool minimized; + int minimized; // 0 - minimized, 1 - card, 2 - oracle only, 3 - full ResizeMode mode; + QComboBox *dropList; QLabel *cardPicture; QLabel *nameLabel1, *nameLabel2; QLabel *manacostLabel1, *manacostLabel2; QLabel *cardtypeLabel1, *cardtypeLabel2; QLabel *powtoughLabel1, *powtoughLabel2; QTextEdit *textLabel; - + CardInfo *info; + void setMinimized(int _minimized); + public: CardInfoWidget(ResizeMode _mode, QWidget *parent = 0, Qt::WindowFlags f = 0); void retranslateUi(); + public slots: void setCard(CardInfo *card); void setCard(const QString &cardName); void setCard(AbstractCardItem *card); + private slots: void clear(); void updatePixmap(); + void minimizeClicked(int newMinimized); + signals: void mouseReleased(); + protected: void resizeEvent(QResizeEvent *event); void mouseReleaseEvent(QMouseEvent *event); diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index bb0ecdae7..d3416fe68 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -19,6 +19,7 @@ SettingsCache::SettingsCache() picDownload = settings->value("personal/picturedownload", true).toBool(); doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool(); + cardInfoMinimized = settings->value("interface/cardinfominimized", 0).toInt(); tabGameSplitterSizes = settings->value("interface/tabgame_splittersizes").toByteArray(); displayCardNames = settings->value("cards/displaycardnames", true).toBool(); horizontalHand = settings->value("hand/horizontal", true).toBool(); @@ -107,6 +108,12 @@ void SettingsCache::setDoubleClickToPlay(int _doubleClickToPlay) settings->setValue("interface/doubleclicktoplay", doubleClickToPlay); } +void SettingsCache::setCardInfoMinimized(int _cardInfoMinimized) +{ + cardInfoMinimized = _cardInfoMinimized; + settings->setValue("interface/cardinfominimized", cardInfoMinimized); +} + void SettingsCache::setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes) { tabGameSplitterSizes = _tabGameSplitterSizes; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 6a8f1a99c..a74e2a617 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -29,6 +29,7 @@ private: QString handBgPath, stackBgPath, tableBgPath, playerBgPath, cardBackPicturePath; bool picDownload; bool doubleClickToPlay; + int cardInfoMinimized; QByteArray tabGameSplitterSizes; bool displayCardNames; bool horizontalHand; @@ -50,6 +51,7 @@ public: QString getCardBackPicturePath() const { return cardBackPicturePath; } bool getPicDownload() const { return picDownload; } bool getDoubleClickToPlay() const { return doubleClickToPlay; } + int getCardInfoMinimized() const { return cardInfoMinimized; } QByteArray getTabGameSplitterSizes() const { return tabGameSplitterSizes; } bool getDisplayCardNames() const { return displayCardNames; } bool getHorizontalHand() const { return horizontalHand; } @@ -71,6 +73,7 @@ public slots: void setCardBackPicturePath(const QString &_cardBackPicturePath); void setPicDownload(int _picDownload); void setDoubleClickToPlay(int _doubleClickToPlay); + void setCardInfoMinimized(int _cardInfoMinimized); void setTabGameSplitterSizes(const QByteArray &_tabGameSplitterSizes); void setDisplayCardNames(int _displayCardNames); void setHorizontalHand(int _horizontalHand); From a3b7ed719f9ce2c28ec82226964b62ae7767dc3b Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 13 Jun 2011 20:04:10 +0200 Subject: [PATCH 47/87] QSplitter in TabRoom --- cockatrice/src/tab_room.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index 5c4409413..f40458cdd 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "dlg_creategame.h" #include "tab_supervisor.h" #include "tab_room.h" @@ -153,12 +154,12 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q chatGroupBox = new QGroupBox; chatGroupBox->setLayout(chatVbox); - QVBoxLayout *vbox = new QVBoxLayout; - vbox->addWidget(gameSelector); - vbox->addWidget(chatGroupBox); + QSplitter *splitter = new QSplitter(Qt::Vertical); + splitter->addWidget(gameSelector); + splitter->addWidget(chatGroupBox); QHBoxLayout *hbox = new QHBoxLayout; - hbox->addLayout(vbox, 3); + hbox->addWidget(splitter, 3); hbox->addWidget(userList, 1); aLeaveRoom = new QAction(this); From 9f85074ca30427245780555410ca41984c8feb55 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 13 Jun 2011 22:47:14 +0200 Subject: [PATCH 48/87] colon after sender name in chat view --- cockatrice/src/chatview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index 92696cf01..625301e39 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -32,7 +32,7 @@ void ChatView::appendMessage(QString sender, const QString &message) senderFormat.setForeground(Qt::blue); cursor.setCharFormat(senderFormat); if (!sender.isEmpty()) - sender.append(" "); + sender.append(": "); cursor.insertText(sender); QTextCharFormat messageFormat; From 6226e381de8f14251db6aa49bf5de62a563c8a8c Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 16 Jun 2011 16:43:01 +0200 Subject: [PATCH 49/87] price tag feature by Marcio Ribeiro --- cockatrice/cockatrice.pro | 4 +- cockatrice/cockatrice.qrc | 1 + cockatrice/src/decklistmodel.cpp | 65 ++++++++++++++++++++++------ cockatrice/src/decklistmodel.h | 5 ++- cockatrice/src/dlg_settings.cpp | 31 +++++++++++++ cockatrice/src/dlg_settings.h | 12 ++++- cockatrice/src/settingscache.cpp | 8 ++++ cockatrice/src/settingscache.h | 3 ++ cockatrice/src/window_deckeditor.cpp | 38 ++++++++++++++++ cockatrice/src/window_deckeditor.h | 5 ++- common/decklist.cpp | 23 ++++++++-- common/decklist.h | 12 ++++- 12 files changed, 184 insertions(+), 23 deletions(-) diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 7d84a2280..d4133d4a1 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -5,7 +5,7 @@ INCLUDEPATH += . src ../common MOC_DIR = build OBJECTS_DIR = build RESOURCES = cockatrice.qrc -QT += network svg multimedia +QT += network script svg multimedia HEADERS += src/abstractcounter.h \ src/counter_general.h \ @@ -71,6 +71,7 @@ HEADERS += src/abstractcounter.h \ src/localserverinterface.h \ src/localclient.h \ src/translation.h \ + src/priceupdater.h \ src/soundengine.h \ ../common/color.h \ ../common/serializable_item.h \ @@ -154,6 +155,7 @@ SOURCES += src/abstractcounter.cpp \ src/localserver.cpp \ src/localserverinterface.cpp \ src/localclient.cpp \ + src/priceupdater.cpp \ src/soundengine.cpp \ ../common/serializable_item.cpp \ ../common/decklist.cpp \ diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index d57e461e4..b7517dabb 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -23,6 +23,7 @@ resources/pencil.svg resources/icon_search.svg resources/icon_clearsearch.svg + resources/icon_update.png resources/hr.jpg resources/appicon.svg resources/add_to_sideboard.svg diff --git a/cockatrice/src/decklistmodel.cpp b/cockatrice/src/decklistmodel.cpp index 1084f3457..82a443264 100644 --- a/cockatrice/src/decklistmodel.cpp +++ b/cockatrice/src/decklistmodel.cpp @@ -10,6 +10,7 @@ #include "main.h" #include "decklistmodel.h" #include "carddatabase.h" +#include "settingscache.h" DeckListModel::DeckListModel(QObject *parent) : QAbstractItemModel(parent) @@ -65,12 +66,20 @@ int DeckListModel::rowCount(const QModelIndex &parent) const return 0; } +int DeckListModel::columnCount(const QModelIndex &/*parent*/) const +{ + if (settingsCache->getPriceTagFeature()) + return 3; + else + return 2; +} + QVariant DeckListModel::data(const QModelIndex &index, int role) const { // debugIndexInfo("data", index); if (!index.isValid()) return QVariant(); - if (index.column() >= 2) + if (index.column() >= columnCount()) return QVariant(); AbstractDecklistNode *temp = static_cast(index.internalPointer()); @@ -86,8 +95,9 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: case Qt::EditRole: switch (index.column()) { - case 0: return node->recursiveCount(true); - case 1: return node->getVisibleName(); + case 0: return node->recursiveCount(true); + case 1: return node->getVisibleName(); + case 2: return QString().sprintf("$%.2f", node->recursivePrice(true)); default: return QVariant(); } case Qt::BackgroundRole: { @@ -101,8 +111,9 @@ QVariant DeckListModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: case Qt::EditRole: { switch (index.column()) { - case 0: return card->getNumber(); - case 1: return card->getName(); + case 0: return card->getNumber(); + case 1: return card->getName(); + case 2: return QString().sprintf("$%.2f", card->getTotalPrice()); default: return QVariant(); } } @@ -119,9 +130,12 @@ QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int { if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal)) return QVariant(); + if (section >= columnCount()) + return QVariant(); switch (section) { - case 0: return tr("Number"); - case 1: return tr("Card"); + case 0: return tr("Number"); + case 1: return tr("Card"); + case 2: return tr("Price"); default: return QVariant(); } } @@ -174,8 +188,9 @@ bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int return false; switch (index.column()) { - case 0: node->setNumber(value.toInt()); break; - case 1: node->setName(value.toString()); break; + case 0: node->setNumber(value.toInt()); break; + case 1: node->setName(value.toString()); break; + case 2: node->setPrice(value.toFloat()); break; default: return false; } emitRecursiveUpdates(index); @@ -300,7 +315,7 @@ void DeckListModel::setDeckList(DeckList *_deck) void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node) { - static const int totalColumns = 3; + const int totalColumns = settingsCache->getPriceTagFeature() ? 3 : 2; if (node->height() == 1) { QTextBlockFormat blockFormat; @@ -308,13 +323,16 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no charFormat.setFontPointSize(11); charFormat.setFontWeight(QFont::Bold); cursor->insertBlock(blockFormat, charFormat); - cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true))); + QString priceStr; + if (settingsCache->getPriceTagFeature()) + priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true)); + cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr)); QTextTableFormat tableFormat; tableFormat.setCellPadding(0); tableFormat.setCellSpacing(0); tableFormat.setBorder(0); - QTextTable *table = cursor->insertTable(node->size() + 1, 2, tableFormat); + QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat); for (int i = 0; i < node->size(); i++) { AbstractDecklistCardNode *card = dynamic_cast(node->at(i)); @@ -330,6 +348,13 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no cell.setFormat(cellCharFormat); cellCursor = cell.firstCursorPosition(); cellCursor.insertText(card->getName()); + + if (settingsCache->getPriceTagFeature()) { + cell = table->cellAt(i, 2); + cell.setFormat(cellCharFormat); + cellCursor = cell.firstCursorPosition(); + cellCursor.insertText(QString().sprintf("$%.2f ", card->getTotalPrice())); + } } } else if (node->height() == 2) { QTextBlockFormat blockFormat; @@ -338,7 +363,10 @@ void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *no charFormat.setFontWeight(QFont::Bold); cursor->insertBlock(blockFormat, charFormat); - cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true))); + QString priceStr; + if (settingsCache->getPriceTagFeature()) + priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true)); + cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr)); QTextTableFormat tableFormat; tableFormat.setCellPadding(10); @@ -391,3 +419,14 @@ void DeckListModel::printDeckList(QPrinter *printer) doc.print(printer); } + +void DeckListModel::pricesUpdated(InnerDecklistNode *node) +{ + if (!node) + node = root; + + if (node->isEmpty()) + return; + + emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last())); +} diff --git a/cockatrice/src/decklistmodel.h b/cockatrice/src/decklistmodel.h index f66f509de..a8a22c78b 100644 --- a/cockatrice/src/decklistmodel.h +++ b/cockatrice/src/decklistmodel.h @@ -17,6 +17,8 @@ public: DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { } int getNumber() const { return dataNode->getNumber(); } void setNumber(int _number) { dataNode->setNumber(_number); } + float getPrice() const { return dataNode->getPrice(); } + void setPrice(float _price) { dataNode->setPrice(_price); } QString getName() const { return dataNode->getName(); } void setName(const QString &_name) { dataNode->setName(_name); } DecklistCardNode *getDataNode() const { return dataNode; } @@ -32,7 +34,7 @@ public: DeckListModel(QObject *parent = 0); ~DeckListModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 2; } + int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; @@ -45,6 +47,7 @@ public: void cleanList(); DeckList *getDeckList() const { return deckList; } void setDeckList(DeckList *_deck); + void pricesUpdated(InnerDecklistNode *node = 0); private: DeckList *deckList; InnerDecklistNode *root; diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index a07fff6cb..0f295af2a 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -455,6 +455,30 @@ void UserInterfaceSettingsPage::soundPathButtonClicked() settingsCache->setSoundPath(path); } +DeckEditorSettingsPage::DeckEditorSettingsPage() +{ + priceTagsCheckBox = new QCheckBox; + priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature()); + connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int))); + + QGridLayout *generalGrid = new QGridLayout; + generalGrid->addWidget(priceTagsCheckBox, 0, 0); + + generalGroupBox = new QGroupBox; + generalGroupBox->setLayout(generalGrid); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(generalGroupBox); + + setLayout(mainLayout); +} + +void DeckEditorSettingsPage::retranslateUi() +{ + priceTagsCheckBox->setText(tr("Enable &price tag feature (using data from blacklotusproject.com)")); + generalGroupBox->setTitle(tr("General")); +} + MessagesSettingsPage::MessagesSettingsPage() { aAdd = new QAction(this); @@ -533,6 +557,7 @@ DlgSettings::DlgSettings(QWidget *parent) pagesWidget->addWidget(new GeneralSettingsPage); pagesWidget->addWidget(new AppearanceSettingsPage); pagesWidget->addWidget(new UserInterfaceSettingsPage); + pagesWidget->addWidget(new DeckEditorSettingsPage); pagesWidget->addWidget(new MessagesSettingsPage); closeButton = new QPushButton; @@ -577,6 +602,11 @@ void DlgSettings::createIcons() userInterfaceButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); userInterfaceButton->setIcon(QIcon(":/resources/icon_config_interface.svg")); + deckEditorButton = new QListWidgetItem(contentsWidget); + deckEditorButton->setTextAlignment(Qt::AlignHCenter); + deckEditorButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + deckEditorButton->setIcon(QIcon(":/resources/icon_deckeditor.svg")); + messagesButton = new QListWidgetItem(contentsWidget); messagesButton->setTextAlignment(Qt::AlignHCenter); messagesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); @@ -633,6 +663,7 @@ void DlgSettings::retranslateUi() generalButton->setText(tr("General")); appearanceButton->setText(tr("Appearance")); userInterfaceButton->setText(tr("User interface")); + deckEditorButton->setText(tr("Deck editor")); messagesButton->setText(tr("Messages")); closeButton->setText(tr("&Close")); diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index 54648482b..859376d62 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -93,6 +93,16 @@ public: void retranslateUi(); }; +class DeckEditorSettingsPage : public AbstractSettingsPage { + Q_OBJECT +public: + DeckEditorSettingsPage(); + void retranslateUi(); +private: + QCheckBox *priceTagsCheckBox; + QGroupBox *generalGroupBox; +}; + class MessagesSettingsPage : public AbstractSettingsPage { Q_OBJECT public: @@ -118,7 +128,7 @@ private slots: private: QListWidget *contentsWidget; QStackedWidget *pagesWidget; - QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *messagesButton; + QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *deckEditorButton, *messagesButton; QPushButton *closeButton; void createIcons(); void retranslateUi(); diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index d3416fe68..f7494d767 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -31,6 +31,8 @@ SettingsCache::SettingsCache() soundEnabled = settings->value("sound/enabled", false).toBool(); soundPath = settings->value("sound/path").toString(); + + priceTagFeature = settings->value("deckeditor/pricetags", false).toBool(); } void SettingsCache::setLang(const QString &_lang) @@ -171,3 +173,9 @@ void SettingsCache::setSoundPath(const QString &_soundPath) settings->setValue("sound/path", soundPath); emit soundPathChanged(); } + +void SettingsCache::setPriceTagFeature(int _priceTagFeature) +{ + priceTagFeature = _priceTagFeature; + settings->setValue("deckeditor/pricetags", priceTagFeature); +} diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index a74e2a617..c834716a6 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -38,6 +38,7 @@ private: bool zoneViewSortByName, zoneViewSortByType; bool soundEnabled; QString soundPath; + bool priceTagFeature; public: SettingsCache(); QString getLang() const { return lang; } @@ -61,6 +62,7 @@ public: bool getZoneViewSortByType() const { return zoneViewSortByType; } bool getSoundEnabled() const { return soundEnabled; } QString getSoundPath() const { return soundPath; } + bool getPriceTagFeature() const { return priceTagFeature; } public slots: void setLang(const QString &_lang); void setDeckPath(const QString &_deckPath); @@ -83,6 +85,7 @@ public slots: void setZoneViewSortByType(int _zoneViewSortByType); void setSoundEnabled(int _soundEnabled); void setSoundPath(const QString &_soundPath); + void setPriceTagFeature(int _priceTagFeature); }; extern SettingsCache *settingsCache; diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp index e540aad6c..b3dfdc85a 100644 --- a/cockatrice/src/window_deckeditor.cpp +++ b/cockatrice/src/window_deckeditor.cpp @@ -26,6 +26,7 @@ #include "dlg_load_deck_from_clipboard.h" #include "main.h" #include "settingscache.h" +#include "priceupdater.h" void SearchLineEdit::keyPressEvent(QKeyEvent *event) { @@ -113,15 +114,37 @@ WndDeckEditor::WndDeckEditor(QWidget *parent) commentsEdit->setMaximumHeight(70); commentsLabel->setBuddy(commentsEdit); connect(commentsEdit, SIGNAL(textChanged()), this, SLOT(updateComments())); + QGridLayout *grid = new QGridLayout; grid->addWidget(nameLabel, 0, 0); grid->addWidget(nameEdit, 0, 1); + grid->addWidget(commentsLabel, 1, 0); grid->addWidget(commentsEdit, 1, 1); + // Update price + aUpdatePrices = new QAction(tr("&Update prices"), this); + aUpdatePrices->setShortcut(tr("Ctrl+U")); + aUpdatePrices->setIcon(QIcon(":/resources/icon_update.png")); + connect(aUpdatePrices, SIGNAL(triggered()), this, SLOT(actUpdatePrices())); + if (!settingsCache->getPriceTagFeature()) + aUpdatePrices->setVisible(false); + + QToolBar *deckToolBar = new QToolBar; + deckToolBar->setOrientation(Qt::Vertical); + deckToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + deckToolBar->setIconSize(QSize(24, 24)); + deckToolBar->addAction(aUpdatePrices); + QHBoxLayout *deckToolbarLayout = new QHBoxLayout; + deckToolbarLayout->addStretch(); + deckToolbarLayout->addWidget(deckToolBar); + deckToolbarLayout->addStretch(); + + QVBoxLayout *rightFrame = new QVBoxLayout; rightFrame->addLayout(grid); rightFrame->addWidget(deckView); + rightFrame->addLayout(deckToolbarLayout); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addLayout(leftFrame, 10); @@ -456,6 +479,21 @@ void WndDeckEditor::actDecrement() setWindowModified(true); } +void WndDeckEditor::actUpdatePrices() +{ + aUpdatePrices->setDisabled(true); + PriceUpdater *up = new PriceUpdater(deckModel->getDeckList()); + connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices())); + up->updatePrices(); +} + +void WndDeckEditor::finishedUpdatingPrices() +{ + deckModel->pricesUpdated(); + setWindowModified(true); + aUpdatePrices->setDisabled(false); +} + void WndDeckEditor::setDeck(DeckList *_deck, const QString &_lastFileName, DeckList::FileFormat _lastFileFormat) { deckModel->setDeckList(_deck); diff --git a/cockatrice/src/window_deckeditor.h b/cockatrice/src/window_deckeditor.h index e14c16331..92a90bb99 100644 --- a/cockatrice/src/window_deckeditor.h +++ b/cockatrice/src/window_deckeditor.h @@ -52,6 +52,9 @@ private slots: void actRemoveCard(); void actIncrement(); void actDecrement(); + void actUpdatePrices(); + + void finishedUpdatingPrices(); private: void addCardHelper(const QString &zoneName); void recursiveExpand(const QModelIndex &index); @@ -74,7 +77,7 @@ private: QMenu *deckMenu, *dbMenu; QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, *aPrintDeck, *aClose; QAction *aEditSets, *aSearch, *aClearSearch; - QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement; + QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement, *aUpdatePrices; public: WndDeckEditor(QWidget *parent = 0); ~WndDeckEditor(); diff --git a/common/decklist.cpp b/common/decklist.cpp index 75a26514a..6aed8f89f 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -127,6 +127,19 @@ int InnerDecklistNode::recursiveCount(bool countTotalCards) const return result; } +float InnerDecklistNode::recursivePrice(bool countTotalCards) const +{ + float result = 0; + for (int i = 0; i < size(); i++) { + InnerDecklistNode *node = dynamic_cast(at(i)); + if (node) + result += node->recursivePrice(countTotalCards); + else if (countTotalCards) + result += dynamic_cast(at(i))->getTotalPrice(); + } + return result; +} + bool InnerDecklistNode::compare(AbstractDecklistNode *other) const { InnerDecklistNode *other2 = dynamic_cast(other); @@ -165,11 +178,12 @@ bool InnerDecklistNode::readElement(QXmlStreamReader *xml) } if (xml->isStartElement() && (xml->name() == "zone")) currentItem = new InnerDecklistNode(xml->attributes().value("name").toString(), this); - else if (xml->isStartElement() && (xml->name() == "card")) - currentItem = new DecklistCardNode(xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(), this); - else if (xml->isEndElement() && (xml->name() == "zone")) + else if (xml->isStartElement() && (xml->name() == "card")) { + float price = (xml->attributes().value("price") != NULL) ? xml->attributes().value("price").toString().toFloat() : 0; + currentItem = new DecklistCardNode(xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(), price, this); + } else if (xml->isEndElement() && (xml->name() == "zone")) return true; - + return false; } @@ -194,6 +208,7 @@ void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml) { xml->writeEmptyElement("card"); xml->writeAttribute("number", QString::number(getNumber())); + xml->writeAttribute("price", QString::number(getPrice())); xml->writeAttribute("name", getName()); } diff --git a/common/decklist.h b/common/decklist.h index 379421743..d0f2b7cf7 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -69,6 +69,7 @@ public: AbstractDecklistNode *findChild(const QString &name); int height() const; int recursiveCount(bool countTotalCards = false) const; + float recursivePrice(bool countTotalCards = false) const; bool compare(AbstractDecklistNode *other) const; QVector > sort(Qt::SortOrder order = Qt::AscendingOrder); @@ -83,6 +84,9 @@ public: virtual void setNumber(int _number) = 0; virtual QString getName() const = 0; virtual void setName(const QString &_name) = 0; + virtual float getPrice() const = 0; + virtual void setPrice(float _price) = 0; + float getTotalPrice() const { return getNumber() * getPrice(); } int height() const { return 0; } bool compare(AbstractDecklistNode *other) const; @@ -94,14 +98,18 @@ class DecklistCardNode : public AbstractDecklistCardNode { private: QString name; int number; + float price; public: - DecklistCardNode(const QString &_name = QString(), int _number = 1, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number) { } + DecklistCardNode(const QString &_name = QString(), int _number = 1, float _price = 0, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number), price(_price) { } + DecklistCardNode(const QString &_name = QString(), int _number = 1, InnerDecklistNode *_parent = 0) : AbstractDecklistCardNode(_parent), name(_name), number(_number), price(0) { } DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent); int getNumber() const { return number; } void setNumber(int _number) { number = _number; } QString getName() const { return name; } void setName(const QString &_name) { name = _name; } -}; + float getPrice() const { return price; } + void setPrice(const float _price) { price = _price; } + }; class DeckList : public SerializableItem { Q_OBJECT From 4444a0c16cbd7f594a803c86ccea2e3325c1a0c1 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Thu, 16 Jun 2011 16:43:26 +0200 Subject: [PATCH 50/87] extra files --- cockatrice/resources/icon_update.png | Bin 0 -> 7262 bytes cockatrice/src/priceupdater.cpp | 81 +++++++++++++++++++++++++++ cockatrice/src/priceupdater.h | 28 +++++++++ 3 files changed, 109 insertions(+) create mode 100644 cockatrice/resources/icon_update.png create mode 100644 cockatrice/src/priceupdater.cpp create mode 100644 cockatrice/src/priceupdater.h diff --git a/cockatrice/resources/icon_update.png b/cockatrice/resources/icon_update.png new file mode 100644 index 0000000000000000000000000000000000000000..825c0aee757322230b41bc9ef0be3ed08260a5d9 GIT binary patch literal 7262 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 literal 0 HcmV?d00001 diff --git a/cockatrice/src/priceupdater.cpp b/cockatrice/src/priceupdater.cpp new file mode 100644 index 000000000..e9f1a6953 --- /dev/null +++ b/cockatrice/src/priceupdater.cpp @@ -0,0 +1,81 @@ +/** + * @author Marcio Ribeiro + * @version 1.0 + */ +#include +#include + +#include +#include +#include "priceupdater.h" + +/** + * Constructor. + * + * @param _deck deck. + */ +PriceUpdater::PriceUpdater(const DeckList *_deck) +{ + nam = new QNetworkAccessManager(this); + deck = _deck; +} + +/** + * Update the prices of the cards in deckList. + */ +void PriceUpdater::updatePrices() +{ + QString q = "http://blacklotusproject.com/json/?cards="; + QStringList cards = deck->getCardList(); + for (int i = 0; i < cards.size(); ++i) { + q += cards[i] + "|"; + } + QUrl url(q.replace(' ', '+')); + + QNetworkReply *reply = nam->get(QNetworkRequest(url)); + connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished())); +} + +/** + * Called when the download of the json file with the prices is finished. + */ +void PriceUpdater::downloadFinished() +{ + QMap cmap; + InnerDecklistNode *listRoot = deck->getRoot(); + for (int i = 0; i < listRoot->size(); i++) { + InnerDecklistNode *currentZone = dynamic_cast(listRoot->at(i)); + for (int j = 0; j < currentZone->size(); j++) { + DecklistCardNode *currentCard = dynamic_cast(currentZone->at(j)); + if (!currentCard) + continue; + cmap.insert(currentCard->getName().toLower(), currentCard); + currentCard->setPrice(0); + } + } + + QNetworkReply *reply = static_cast(sender()); + QByteArray result = reply->readAll(); + QScriptValue sc; + QScriptEngine engine; + sc = engine.evaluate("value = " + result); + + if (sc.property("cards").isArray()) { + QScriptValueIterator it(sc.property("cards")); + while (it.hasNext()) { + it.next(); + QString name = it.value().property("name").toString().toLower(); + float price = it.value().property("average").toString().toFloat(); + DecklistCardNode *c = cmap[name]; + if (!c) + continue; + if (c->getPrice() == 0 || c->getPrice() > price) { + c->setPrice(price); + } + } + } + + reply->deleteLater(); + deleteLater(); + emit finishedUpdate(); +} diff --git a/cockatrice/src/priceupdater.h b/cockatrice/src/priceupdater.h new file mode 100644 index 000000000..a95252eb8 --- /dev/null +++ b/cockatrice/src/priceupdater.h @@ -0,0 +1,28 @@ +#ifndef PRICEUPDATER_H +#define PRICEUPDATER_H + +#include +#include "decklist.h" + +class QNetworkAccessManager; + +/** + * Price Updater. + * + * @author Marcio Ribeiro + */ +class PriceUpdater : public QObject +{ + Q_OBJECT +private: + const DeckList *deck; + QNetworkAccessManager *nam; +signals: + void finishedUpdate(); +private slots: + void downloadFinished(); +public: + PriceUpdater(const DeckList *deck); + void updatePrices(); +}; +#endif From f6f5abccca3fb7a45536f34a6c461024b6721dc8 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 18 Jun 2011 11:42:32 +0200 Subject: [PATCH 51/87] added Czech translation stub --- cockatrice/cockatrice.pro | 3 +- cockatrice/cockatrice.qrc | 1 + cockatrice/src/window_main.cpp | 1 + cockatrice/translations/cockatrice_cz.ts | 3142 +++++++++++++++++++ cockatrice/translations/cockatrice_de.ts | 278 +- cockatrice/translations/cockatrice_en.ts | 278 +- cockatrice/translations/cockatrice_es.ts | 278 +- cockatrice/translations/cockatrice_fr.ts | 278 +- cockatrice/translations/cockatrice_ja.ts | 278 +- cockatrice/translations/cockatrice_pt-br.ts | 278 +- cockatrice/translations/cockatrice_pt.ts | 278 +- cockatrice/translations/cockatrice_ru.ts | 278 +- 12 files changed, 4490 insertions(+), 881 deletions(-) create mode 100644 cockatrice/translations/cockatrice_cz.ts diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index d4133d4a1..4d5f966d4 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -181,7 +181,8 @@ TRANSLATIONS += \ translations/cockatrice_pt-br.ts \ translations/cockatrice_fr.ts \ translations/cockatrice_ja.ts \ - translations/cockatrice_ru.ts + translations/cockatrice_ru.ts \ + translations/cockatrice_cz.ts win32 { RC_FILE = cockatrice.rc } diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index b7517dabb..6c63285dd 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -46,6 +46,7 @@ translations/cockatrice_fr.qm translations/cockatrice_ja.qm translations/cockatrice_ru.qm + translations/cockatrice_cz.qm resources/countries/at.svg resources/countries/au.svg diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index df1fedbc4..fed1e75a9 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -178,6 +178,7 @@ void MainWindow::actAbout() + tr("French:") + " Yannick Hammer, Arnaud Faes
" + tr("Japanese:") + " Nagase Task
" + tr("Russian:") + " Alexander Davidov
" + + tr("Czech:") + " Ondřej Trhoň
" )); } diff --git a/cockatrice/translations/cockatrice_cz.ts b/cockatrice/translations/cockatrice_cz.ts new file mode 100644 index 000000000..f3731f0cf --- /dev/null +++ b/cockatrice/translations/cockatrice_cz.ts @@ -0,0 +1,3142 @@ + + + + + AbstractCounter + + + &Set counter... + + + + + Ctrl+L + + + + + F11 + + + + + F12 + + + + + Set counter + + + + + New value for counter '%1': + + + + + AppearanceSettingsPage + + + Zone background pictures + + + + + Path to hand background: + + + + + Path to stack background: + + + + + Path to table background: + + + + + Path to player info background: + + + + + Path to picture of card back: + + + + + Card rendering + + + + + Display card names on cards having a picture + + + + + Hand layout + + + + + Display hand horizontally (wastes space) + + + + + Table grid layout + + + + + Invert vertical coordinate + + + + + Zone view layout + + + + + Sort by name + + + + + Sort by type + + + + + + + + + Choose path + + + + + CardDatabaseModel + + + Name + + + + + Sets + + + + + Mana cost + + + + + Card type + + + + + P/T + + + + + CardInfoWidget + + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + + Name: + + + + + Mana cost: + + + + + Card type: + + + + + P / T: + + + + + CardItem + + + &Play + + + + + &Hide + + + + + &Tap + + + + + &Untap + + + + + Toggle &normal untapping + + + + + &Flip + + + + + &Clone + + + + + Ctrl+H + + + + + &Attach to card... + + + + + Ctrl+A + + + + + Unattac&h + + + + + &Power / toughness + + + + + &Increase power + + + + + Ctrl++ + + + + + &Decrease power + + + + + Ctrl+- + + + + + I&ncrease toughness + + + + + Alt++ + + + + + D&ecrease toughness + + + + + Alt+- + + + + + In&crease power and toughness + + + + + Ctrl+Alt++ + + + + + Dec&rease power and toughness + + + + + Ctrl+Alt+- + + + + + Set &power and toughness... + + + + + Ctrl+P + + + + + &Set annotation... + + + + + red + + + + + yellow + + + + + green + + + + + &Add counter (%1) + + + + + &Remove counter (%1) + + + + + &Set counters (%1)... + + + + + &top of library + + + + + &bottom of library + + + + + &graveyard + + + + + Ctrl+Del + + + + + &exile + + + + + &Move to + + + + + CardZone + + + his hand + nominative + + + + + %1's hand + nominative + + + + + of his hand + genitive + + + + + of %1's hand + genitive + + + + + his hand + accusative + + + + + %1's hand + accusative + + + + + his library + nominative + + + + + %1's library + nominative + + + + + of his library + genitive + + + + + of %1's library + genitive + + + + + his library + accusative + + + + + %1's library + accusative + + + + + his graveyard + nominative + + + + + %1's graveyard + nominative + + + + + of his graveyard + genitive + + + + + of %1's graveyard + genitive + + + + + his graveyard + accusative + + + + + %1's graveyard + accusative + + + + + his exile + nominative + + + + + %1's exile + nominative + + + + + of his exile + genitive + + + + + of %1's exile + genitive + + + + + his exile + accusative + + + + + %1's exile + accusative + + + + + his sideboard + nominative + + + + + %1's sideboard + nominative + + + + + of his sideboard + genitive + + + + + of %1's sideboard + genitive + + + + + his sideboard + accusative + + + + + %1's sideboard + accusative + + + + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + + + + + DeckListModel + + + Number + + + + + Card + + + + + Price + + + + + DeckViewContainer + + + Load &local deck + + + + + Load d&eck from server + + + + + Ready to s&tart + + + + + Load deck + + + + + DlgCardSearch + + + Card name: + + + + + Card text: + + + + + Card type (OR): + + + + + Color (OR): + + + + + O&K + + + + + &Cancel + + + + + Card search + + + + + DlgConnect + + + &Host: + + + + + &Port: + + + + + Player &name: + + + + + P&assword: + + + + + &OK + + + + + &Cancel + + + + + Connect to server + + + + + DlgCreateGame + + + &Description: + + + + + P&layers: + + + + + Game type + + + + + &Password: + + + + + Only &buddies can join + + + + + Only &registered users can join + + + + + Joining restrictions + + + + + &Spectators allowed + + + + + Spectators &need a password to join + + + + + Spectators can &chat + + + + + Spectators see &everything + + + + + Spectators + + + + + &OK + + + + + &Cancel + + + + + Create game + + + + + Error + + + + + Server error. + + + + + DlgCreateToken + + + &Name: + + + + + Token + + + + + C&olor: + + + + + white + + + + + blue + + + + + black + + + + + red + + + + + green + + + + + multicolor + + + + + colorless + + + + + &P/T: + + + + + &Annotation: + + + + + &Destroy token when it leaves the table + + + + + &OK + + + + + &Cancel + + + + + Create token + + + + + DlgLoadDeckFromClipboard + + + &Refresh + + + + + &OK + + + + + &Cancel + + + + + Load deck from clipboard + + + + + Error + + + + + Invalid deck list. + + + + + DlgLoadRemoteDeck + + + O&K + + + + + &Cancel + + + + + Load deck + + + + + DlgSettings + + + + + Error + + + + + Your card database is invalid. Would you like to go back and set the correct path? + + + + + The path to your deck directory is invalid. Would you like to go back and set the correct path? + + + + + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? + + + + + Settings + + + + + General + + + + + Appearance + + + + + User interface + + + + + Deck editor + + + + + Messages + + + + + &Close + + + + + GameSelector + + + + + + + + + Error + + + + + Wrong password. + + + + + Spectators are not allowed in this game. + + + + + The game is already full. + + + + + The game does not exist any more. + + + + + This game is only open to registered users. + + + + + This game is only open to its creator's buddies. + + + + + You are being ignored by the creator of this game. + + + + + Join game + + + + + Password: + + + + + Games + + + + + Show &full games + + + + + C&reate + + + + + &Join + + + + + J&oin as spectator + + + + + GameView + + + Esc + + + + + GamesModel + + + yes + + + + + yes, free for spectators + + + + + no + + + + + buddies only + + + + + reg. users only + + + + + not allowed + + + + + Description + + + + + Creator + + + + + Game type + + + + + Password + + + + + Restrictions + + + + + Players + + + + + Spectators + + + + + GeneralSettingsPage + + + + English + + + + + + + Choose path + + + + + Personal settings + + + + + Language: + + + + + Download card pictures on the fly + + + + + Paths + + + + + Decks directory: + + + + + Pictures directory: + + + + + Path to card database: + + + + + MainWindow + + + There are too many concurrent connections from your address. + + + + + Banned by moderator. + + + + + Unknown reason. + + + + + Connection closed + + + + + The server has terminated your connection. +Reason: %1 + + + + + Number of players + + + + + Please enter the number of players. + + + + + + Player %1 + + + + + About Cockatrice + + + + + Version %1 + + + + + Authors: + + + + + Translators: + + + + + Spanish: + + + + + Portugese (Portugal): + + + + + Portugese (Brazil): + + + + + French: + + + + + Japanese: + + + + + Russian: + + + + + Czech: + + + + + + + + + + Error + + + + + Server timeout + + + + + Invalid login data. + + + + + There is already an active session using this user name. +Please close that session first and re-login. + + + + + Socket error: %1 + + + + + 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. + + + + + Your Cockatrice client is obsolete. Please update your Cockatrice version. +Local version is %1, remote version is %2. + + + + + Connecting to %1... + + + + + Disconnected + + + + + Logged in at %1 + + + + + &Connect... + + + + + &Disconnect + + + + + Start &local game... + + + + + &Deck editor + + + + + &Full screen + + + + + Ctrl+F + + + + + &Settings... + + + + + &Exit + + + + + &Cockatrice + + + + + &About Cockatrice + + + + + &Help + + + + + Are you sure? + + + + + There are still open games. Are you sure you want to quit? + + + + + MessageLogWidget + + + Connecting to %1... + + + + + Connected. + + + + + Disconnected from server. + + + + + Invalid password. + + + + + Protocol version mismatch. Client: %1, Server: %2 + + + + + Protocol error. + + + + + You have joined game #%1. + + + + + %1 has joined the game. + + + + + %1 has left the game. + + + + + The game has been closed. + + + + + %1 is now watching the game. + + + + + %1 is not watching the game any more. + + + + + %1 has loaded a local deck. + + + + + %1 has loaded deck #%2. + + + + + %1 is ready to start the game. + + + + + %1 is not ready to start the game any more. + + + + + %1 has conceded the game. + + + + + The game has started. + + + + + %1 shuffles his library. + + + + + %1 rolls a %2 with a %3-sided die. + + + + + %1 draws %n card(s). + + + + + + + %1 undoes his last draw. + + + + + %1 undoes his last draw (%2). + + + + + from table + + + + + from graveyard + + + + + from exile + + + + + from hand + + + + + the bottom card of his library + + + + + from the bottom of his library + + + + + the top card of his library + + + + + from the top of his library + + + + + from library + + + + + from sideboard + + + + + from the stack + + + + + + a card + + + + + %1 gives %2 control over %3. + + + + + %1 puts %2 into play tapped%3. + + + + + %1 puts %2 into play%3. + + + + + %1 puts %2%3 into graveyard. + + + + + %1 exiles %2%3. + + + + + %1 moves %2%3 to hand. + + + + + %1 puts %2%3 into his library. + + + + + %1 puts %2%3 on bottom of his library. + + + + + %1 puts %2%3 on top of his library. + + + + + %1 puts %2%3 into his library at position %4. + + + + + %1 moves %2%3 to sideboard. + + + + + %1 plays %2%3. + + + + + %1 takes a mulligan to %n. + + + + + + + %1 draws his initial hand. + + + + + %1 flips %2 face-down. + + + + + %1 flips %2 face-up. + + + + + %1 destroys %2. + + + + + %1 attaches %2 to %3's %4. + + + + + %1 unattaches %2. + + + + + %1 creates token: %2%3. + + + + + %1 points from %2's %3 to %4. + + + + + %1 points from %2's %3 to %4's %5. + + + + + %1 places %n %2 counter(s) on %3 (now %4). + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + + + + + + + red + + + + + + + yellow + + + + + + + green + + + + + + + his permanents + + + + + %1 %2 %3. + + + + + taps + + + + + untaps + + + + + %1 sets counter %2 to %3 (%4%5). + + + + + %1 sets %2 to not untap normally. + + + + + %1 sets %2 to untap normally. + + + + + %1 sets PT of %2 to %3. + + + + + %1 sets annotation of %2 to %3. + + + + + %1 is looking at the top %2 cards %3. + + + + + %1 is looking at %2. + + + + + %1 stops looking at %2. + + + + + %1 reveals %2 to %3. + + + + + %1 reveals %2. + + + + + %1 randomly reveals %2%3 to %4. + + + + + %1 randomly reveals %2%3. + + + + + %1 reveals %2%3 to %4. + + + + + %1 reveals %2%3. + + + + + It is now %1's turn. + + + + + untap step + + + + + upkeep step + + + + + draw step + + + + + first main phase + + + + + beginning of combat step + + + + + declare attackers step + + + + + declare blockers step + + + + + combat damage step + + + + + end of combat step + + + + + second main phase + + + + + ending phase + + + + + It is now the %1. + + + + + MessagesSettingsPage + + + Add message + + + + + Message: + + + + + &Add + + + + + &Remove + + + + + PhasesToolbar + + + Untap step + + + + + Upkeep step + + + + + Draw step + + + + + First main phase + + + + + Beginning of combat step + + + + + Declare attackers step + + + + + Declare blockers step + + + + + Combat damage step + + + + + End of combat step + + + + + Second main phase + + + + + End of turn step + + + + + Player + + + &View graveyard + + + + + &View exile + + + + + Player "%1" + + + + + &Graveyard + + + + + &Exile + + + + + + + Move to &top of library + + + + + + + Move to &bottom of library + + + + + + Move to &graveyard + + + + + + Move to &exile + + + + + + Move to &hand + + + + + &View library + + + + + View &top cards of library... + + + + + Reveal &library to + + + + + Reveal t&op card to + + + + + &View sideboard + + + + + &Draw card + + + + + D&raw cards... + + + + + &Undo last draw + + + + + Take &mulligan + + + + + &Shuffle + + + + + Move top cards to &graveyard... + + + + + Move top cards to &exile... + + + + + Put top card on &bottom + + + + + &Hand + + + + + &Reveal to + + + + + Reveal r&andom card to + + + + + &Sideboard + + + + + &Library + + + + + &Counters + + + + + &Untap all permanents + + + + + R&oll die... + + + + + &Create token... + + + + + C&reate another token + + + + + S&ay + + + + + C&ard + + + + + &All players + + + + + Ctrl+F3 + + + + + F3 + + + + + Ctrl+W + + + + + F4 + + + + + Ctrl+D + + + + + Ctrl+E + + + + + Ctrl+Shift+D + + + + + Ctrl+M + + + + + Ctrl+S + + + + + Ctrl+U + + + + + Ctrl+I + + + + + Ctrl+T + + + + + Ctrl+G + + + + + View top cards of library + + + + + Number of cards: + + + + + Draw cards + + + + + + + + Number: + + + + + Move top cards to grave + + + + + Move top cards to exile + + + + + Roll die + + + + + Number of sides: + + + + + Set power/toughness + + + + + Please enter the new PT: + + + + + Set annotation + + + + + Please enter the new annotation: + + + + + Set counters + + + + + PlayerListWidget + + + local deck + + + + + deck #%1 + + + + + User &details + + + + + Direct &chat + + + + + Add to &buddy list + + + + + Remove from &buddy list + + + + + Add to &ignore list + + + + + Remove from &ignore list + + + + + Kick from &game + + + + + QObject + + + Maindeck + + + + + Sideboard + + + + + Cockatrice decks (*.cod) + + + + + Plain text decks (*.dec *.mwDeck) + + + + + All files (*.*) + + + + + RemoteDeckList_TreeModel + + + Name + + + + + ID + + + + + Upload time + + + + + RoomSelector + + + Rooms + + + + + Joi&n + + + + + Room + + + + + Description + + + + + Players + + + + + Games + + + + + SetsModel + + + Short name + + + + + Long name + + + + + TabAdmin + + + Update server &message + + + + + Server administration functions + + + + + &Unlock functions + + + + + &Lock functions + + + + + Unlock administration functions + + + + + Do you really want to unlock the administration functions? + + + + + Administration + + + + + TabDeckStorage + + + Local file system + + + + + Server deck storage + + + + + + Open in deck editor + + + + + Upload deck + + + + + Download deck + + + + + + New folder + + + + + Delete + + + + + Enter deck name + + + + + This decklist does not have a name. +Please enter a name: + + + + + + Unnamed deck + + + + + Name of new folder: + + + + + Deck storage + + + + + TabGame + + + F5 + + + + + F6 + + + + + F7 + + + + + F8 + + + + + F9 + + + + + F10 + + + + + &Phases + + + + + &Game + + + + + Next &phase + + + + + Ctrl+Space + + + + + Next &turn + + + + + Ctrl+Return + + + + + Ctrl+Enter + + + + + &Remove all local arrows + + + + + Ctrl+R + + + + + &Concede + + + + + F2 + + + + + &Leave game + + + + + Ctrl+Q + + + + + &Say: + + + + + Concede + + + + + Are you sure you want to concede this game? + + + + + Leave game + + + + + Are you sure you want to leave this game? + + + + + Kicked + + + + + You have been kicked out of the game. + + + + + Game %1: %2 + + + + + TabMessage + + + Personal &talk + + + + + &Leave + + + + + This user is ignoring you. + + + + + %1 has left the server. + + + + + %1 has joined the server. + + + + + Talking to %1 + + + + + TabRoom + + + &Say: + + + + + Chat + + + + + &Room + + + + + &Leave room + + + + + You are flooding the chat. Please wait a couple of seconds. + + + + + TabServer + + + Server + + + + + TabUserLists + + + User lists + + + + + UserInfoBox + + + User information + + + + + Real name: + + + + + Location: + + + + + User level: + + + + + Administrator + + + + + Judge + + + + + Registered user + + + + + Unregistered user + + + + + UserInterfaceSettingsPage + + + General interface settings + + + + + &Double-click cards to play them (instead of single-click) + + + + + Animation settings + + + + + &Tap/untap animation + + + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + + + + + UserList + + + Users online: %1 + + + + + Users in this room: %1 + + + + + Buddies online: %1 / %2 + + + + + Ignored users online: %1 / %2 + + + + + User &details + + + + + Direct &chat + + + + + Add to &buddy list + + + + + Remove from &buddy list + + + + + Add to &ignore list + + + + + Remove from &ignore list + + + + + Ban from &server + + + + + Duration + + + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + + + + + WndDeckEditor + + + &Search... + + + + + &Clear search + + + + + &Search for: + + + + + Deck &name: + + + + + &Comments: + + + + + &Update prices + + + + + Ctrl+U + + + + + Deck editor [*] + + + + + &New deck + + + + + &Load deck... + + + + + &Save deck + + + + + Save deck &as... + + + + + Load deck from cl&ipboard... + + + + + Save deck to clip&board + + + + + &Print deck... + + + + + &Close + + + + + Ctrl+Q + + + + + &Edit sets... + + + + + &Deck + + + + + &Card database + + + + + Add card to &maindeck + + + + + Return + + + + + Enter + + + + + Add card to &sideboard + + + + + Ctrl+Return + + + + + Ctrl+Enter + + + + + &Remove row + + + + + Del + + + + + &Increment number + + + + + + + + + + + &Decrement number + + + + + - + + + + + Are you sure? + + + + + The decklist has been modified. +Do you want to save the changes? + + + + + Load deck + + + + + + Error + + + + + + The deck could not be saved. +Please check that the directory is writable and try again. + + + + + Save deck + + + + + WndSets + + + Edit sets + + + + + ZoneViewWidget + + + sort by name + + + + + sort by type + + + + + shuffle when closing + + + + diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 21f6d2639..8dc03b81b 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -187,22 +187,42 @@ CardInfoWidget - + + Hide card info + Nichts anzeigen + + + + Show card only + nur Kartenbild + + + + Show text only + nur Kartentext + + + + Show full info + Alles anzeigen + + + Name: Name: - + Mana cost: Manakosten: - + Card type: Kartentyp: - + P / T: S/W: @@ -810,6 +830,19 @@ Neuer Wert für den Zähler '%1': + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + Karten&preisfunktionen anschalten (benutzt Daten von blacklotusproject.com) + + + + General + Allgemeines + + DeckList @@ -828,15 +861,20 @@ DeckListModel - + Number Nummer - + Card Karte + + + Price + Preis + DeckViewContainer @@ -1208,9 +1246,9 @@ DlgSettings - - - + + + Error Fehler @@ -1227,47 +1265,52 @@ Der Pfad zum Kartenbilderverzeichnis ist ungültig. - + Your card database is invalid. Would you like to go back and set the correct path? Ihre Kartendatenbank ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Der Pfad zu Ihrem Deckordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Der Pfad zu Ihrem Kartenbilderordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + Settings Einstellungen - + General Allgemeines - + Appearance Erscheinungsbild - + User interface Bedienung - + + Deck editor + Deckeditor + + + Messages Nachrichten - + &Close S&chließen @@ -1533,23 +1576,23 @@ GameSelector - + C&reate Spiel e&rstellen - + &Join &Teilnehmen - + Error Fehler @@ -1558,57 +1601,57 @@ XXX - + Wrong password. Falsches Passwort. - + Spectators are not allowed in this game. In diesem Spiel sind keine Zuschauer zugelassen. - + The game is already full. Das Spiel ist bereits voll. - + The game does not exist any more. Dieses Spiel gibt es nicht mehr. - + This game is only open to registered users. Dieses Spiel kann nur von registrierten Benutzern betreten werden. - + This game is only open to its creator's buddies. Dieses Spiel kann nur von Freunden des Erstellers betreten werden. - + You are being ignored by the creator of this game. Der Ersteller dieses Spiels ignoriert Sie. - + Join game Spiel beitreten - + Password: Passwort: - + Games Spiele - + Show &full games &Volle Spiele anzeigen @@ -1617,7 +1660,7 @@ &Volle Spiele anzeigen - + J&oin as spectator &Zuschauen @@ -1849,46 +1892,51 @@ Grund: %1 Russisch: - - + + Czech: + Tschechisch: + + + - - - + + + + Error Fehler - + Server timeout Server Zeitüberschreitung - + Invalid login data. Ungültige Anmeldedaten. - + There is already an active session using this user name. Please close that session first and re-login. Es gibt bereits eine aktive Verbindung mit diesem Benutzernamen. Bitte schließen Sie diese Verbindung zuerst und versuchen Sie es dann erneut. - + Socket error: %1 Netzwerkfehler: %1 - + 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. Sie versuchen sich an einem veralteten Server anzumelden. Bitte verwenden Sie eine ältere Cockatrice-Version oder melden Sie sich an einem aktuellen Server an. Lokale Version ist %1, Serverversion ist %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Ihr Cockatrice-Client ist veraltet. Bitte laden Sie sich die neueste Version herunter. @@ -1899,52 +1947,52 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversionen stimmen nicht überein. Lokale Version: %1, Serverversion: %2. - + Connecting to %1... Verbinde zu %1... - + Disconnected nicht verbunden - + Logged in at %1 Angemeldet bei %1 - + &Connect... &Verbinden... - + &Disconnect Verbindung &trennen - + Start &local game... &Lokales Spiel starten... - + &About Cockatrice &Über Cockatrice - + &Help &Hilfe - + Are you sure? Sind Sie sicher? - + There are still open games. Are you sure you want to quit? Es gibt noch offene Spiele. Wollen Sie das Programm wirklich beenden? @@ -1961,27 +2009,27 @@ Lokale Version ist %1, Serverversion ist %2. Spiel ver&lassen - + &Deck editor &Deck-Editor - + &Full screen &Vollbild - + Ctrl+F Ctrl+F - + &Settings... &Einstellungen... - + &Exit &Beenden @@ -1994,7 +2042,7 @@ Lokale Version ist %1, Serverversion ist %2. Esc - + &Cockatrice &Cockatrice @@ -2822,12 +2870,12 @@ Lokale Version ist %1, Serverversion ist %2. MessagesSettingsPage - + &Add &Hinzufügen - + &Remove &Entfernen @@ -2840,12 +2888,12 @@ Lokale Version ist %1, Serverversion ist %2. Entfernen - + Add message Nachricht hinzufügen - + Message: Nachricht: @@ -3488,17 +3536,17 @@ Lokale Version ist %1, Serverversion ist %2. Sideboard - + Cockatrice decks (*.cod) Cockatrice Decks (*.cod) - + Plain text decks (*.dec *.mwDeck) Text Decks (*.dec *.mwDeck) - + All files (*.*) Alle Dateien (*.*) @@ -3901,27 +3949,27 @@ Bitte geben Sie einen Namen ein: TabRoom - + &Say: &Sagen: - + Chat Unterhaltung - + &Room &Raum - + &Leave room Raum ver&lassen - + You are flooding the chat. Please wait a couple of seconds. Sie überfluten den Chatraum. Bitte warten Sie ein paar Sekunden. @@ -4119,37 +4167,37 @@ Geben Sie 0 ein für einen unbefristeten Bann. WndDeckEditor - + &Search for: &Suchen nach: - + Deck &name: Deck &Name: - + &Comments: &Kommentare: - + Deck editor [*] Deck-Editor [*] - + &New deck &Neues Deck - + &Load deck... Deck &laden... - + &Save deck Deck &speichern @@ -4158,37 +4206,37 @@ Geben Sie 0 ein für einen unbefristeten Bann. Deck &speichern unter... - + Save deck &as... Deck s&peichern unter... - + Save deck to clip&board Deck in Z&wischenablage speichern - + &Print deck... Deck &drucken... - + &Close S&chließen - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editionen bearbeiten... - + &Deck &Deck @@ -4197,27 +4245,27 @@ Geben Sie 0 ein für einen unbefristeten Bann. &Editionen - + Add card to &maindeck Karte zu&m Hauptdeck hinzufügen - + Return Return - + Enter Enter - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter @@ -4226,7 +4274,7 @@ Geben Sie 0 ein für einen unbefristeten Bann. Ctrl+M - + Add card to &sideboard Karte zum &Sideboard hinzufügen @@ -4235,88 +4283,98 @@ Geben Sie 0 ein für einen unbefristeten Bann. Ctrl+N - + &Search... &Suchen... - + &Clear search Suche a&ufheben - + + &Update prices + &Preise aktualisieren + + + + Ctrl+U + Ctrl+U + + + Load deck from cl&ipboard... Deck aus &Zwischenablage laden... - + &Card database &Kartendatenbank - + &Remove row Zeile entfe&rnen - + Del Entf - + &Increment number Anzahl er&höhen - + + + - + &Decrement number Anzahl v&erringern - + - - - + Are you sure? Bist du sicher? - + The decklist has been modified. Do you want to save the changes? Die Deckliste wurde verändert. Willst du die Änderungen speichern? - + Load deck Deck laden - - + + Error Fehler - - + + The deck could not be saved. Please check that the directory is writable and try again. Das Deck konnte nicht gespeichert werden. Bitte überprüfen Sie, dass Sie Schreibrechte in dem Verzeichnis haben, und versuchen Sie es erneut. - + Save deck Deck speichern diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index f3e26b6ac..901534114 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -152,22 +152,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: - + Mana cost: - + Card type: - + P / T: @@ -553,18 +573,36 @@ + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + + + DeckListModel - + Number - + Card + + + Price + + DeckViewContainer @@ -890,54 +928,59 @@ DlgSettings - - - + + + Error - + Your card database is invalid. Would you like to go back and set the correct path? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User interface - + + Deck editor + + + + Messages - + &Close @@ -945,83 +988,83 @@ GameSelector - + C&reate - + &Join - + Error - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + J&oin as spectator @@ -1248,125 +1291,130 @@ Reason: %1 - - + + Czech: + + + + - - - + + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -1878,22 +1926,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + &Add - + &Remove - + Add message - + Message: @@ -2340,17 +2388,17 @@ Local version is %1, remote version is %2. - + Cockatrice decks (*.cod) - + Plain text decks (*.dec *.mwDeck) - + All files (*.*) @@ -2698,27 +2746,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -2892,185 +2940,195 @@ Enter 0 for an indefinite ban. WndDeckEditor - + &Search for: - + Deck &name: - + &Comments: - + Deck editor [*] - + &New deck - + &Load deck... - + Load deck from cl&ipboard... - + &Save deck - + + &Update prices + + + + + Ctrl+U + + + + Save deck &as... - + Save deck to clip&board - + &Print deck... - + &Close - + Ctrl+Q - + &Edit sets... - + &Deck - + Load deck - - + + Error - - + + The deck could not be saved. Please check that the directory is writable and try again. - + Save deck - + Add card to &maindeck - + Return - + Enter - + Ctrl+Return - + Ctrl+Enter - + Add card to &sideboard - + &Search... - + &Clear search - + &Card database - + &Remove row - + Del - + &Increment number - + + - + &Decrement number - + - - + Are you sure? - + The decklist has been modified. Do you want to save the changes? diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index fa4beae2f..582079f11 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -160,22 +160,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: Nombre: - + Mana cost: Coste de mana: - + Card type: Tipo de carta: - + P / T: F / R: @@ -745,18 +765,36 @@ Nuevo valor para el contador '%1': + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + General + + DeckListModel - + Number Número - + Card Carta + + + Price + + DeckViewContainer @@ -1089,9 +1127,9 @@ DlgSettings - - - + + + Error Error @@ -1108,47 +1146,52 @@ La ruta a tu directorio de imagenes de las cartas es invalida. - + Your card database is invalid. Would you like to go back and set the correct path? Tu base de datos de cartas es invalida. ¿Deseas volver y seleccionar la ruta correcta? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? La ruta a tu directorio de mazos es invalida. ¿Deseas volver y seleccionar la ruta correcta? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? La ruta a tu directorio de imagenes de las cartas es invalida.¿Deseas volver y seleccionar la ruta correcta? - + Settings Preferencias - + General General - + Appearance Apariencia - + User interface Interfaz de usuario - + + Deck editor + + + + Messages Mensajes - + &Close &Cerrar @@ -1156,78 +1199,78 @@ GameSelector - + C&reate C&rear - + &Join E&ntrar - + Error Error - + Wrong password. Contraseña incorrecta. - + Spectators are not allowed in this game. No se permiten espectadores en esta partida. - + The game is already full. La partida no tiene plazas libres. - + The game does not exist any more. La partida ya no existe. - + This game is only open to registered users. Esta partida está abierta sólo a usuarios registrados. - + This game is only open to its creator's buddies. Esta partida está abierta sólo a los amigos del creador. - + You are being ignored by the creator of this game. Estas siendo ignorado por el creador de la partida. - + Join game Entrar en la partida - + Password: Contraseña: - + Games Partidas - + Show &full games Ver partidas &sin plazas libres @@ -1236,7 +1279,7 @@ &Ver partidas sin plazas libres - + J&oin as spectator Entrar como e&spectador @@ -1464,46 +1507,51 @@ Motivo: %1 Ruso: - - + + Czech: + + + + - - - + + + + Error Error - + Server timeout Tiempo de espera del servidor agotado - + Invalid login data. Datos de conexión invalidos. - + There is already an active session using this user name. Please close that session first and re-login. Ya existe una sesión activa usando ese nombre de usuario. Por favor, cierra esa sesión primero y reintentalo. - + Socket error: %1 Error del Socket: %1 - + 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. Estás intentando conectar a un servidor obsoleto. Por favor, usa una versión anterior de Cockatrice o conecta a un servidor apropiado. La versión local es %1, la versión remota es %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Tu cliente de Cockatrice esta obsoleto. Por favor, actualiza tu versión de Cockatrice. @@ -1514,82 +1562,82 @@ La versión local es %1, la versión remota es %2. La versión del protocolo es diferente. Version local: %1, version remota: %2. - + Connecting to %1... Conectando a %1... - + Disconnected Desconectado - + Logged in at %1 Conectado en %1 - + &Connect... &Conectar... - + &Disconnect &Desconectar - + Start &local game... Empezar partida &local... - + &Deck editor Editor de &mazos - + &Full screen &Pantalla completa - + Ctrl+F CTRL+F - + &Settings... &Preferencias... - + &Exit &Salir - + &Cockatrice &Cockatrice - + &About Cockatrice &Acerca de Cockatrice - + &Help A&yuda - + Are you sure? ¿Estás seguro? - + There are still open games. Are you sure you want to quit? Todavía hay partidas abiertas. ¿Estás seguro que quieres salir? @@ -2109,22 +2157,22 @@ La versión local es %1, la versión remota es %2. MessagesSettingsPage - + &Add &Añadir - + &Remove &Quitar - + Add message Añadir mensaje - + Message: Mensaje: @@ -2607,17 +2655,17 @@ La versión local es %1, la versión remota es %2. Reserva - + Cockatrice decks (*.cod) Mazos de Cockatrice (*.cod) - + Plain text decks (*.dec *.mwDeck) Archivos de texto plano (*.dec *.mwDeck) - + All files (*.*) Todos los archivos (*.*) @@ -2992,27 +3040,27 @@ Por favor, introduzca un nombre: TabRoom - + &Say: &Decir: - + Chat Chat - + &Room &Sala - + &Leave room &Dejar sala - + You are flooding the chat. Please wait a couple of seconds. Estás floodeando el chat. Por favor, espera unos segundos. @@ -3195,186 +3243,196 @@ Indica 0 para un ban indefinido. WndDeckEditor - + &Search for: &Buscar por: - + Deck &name: &Nombre del mazo: - + &Comments: &Comentarios: - + Deck editor [*] Editor de mazos [*] - + &New deck &Nuevo mazo - + &Load deck... &Cargar mazo... - + Load deck from cl&ipboard... Cargar mazo del &portapapeles... - + &Save deck &Guardar mazo - + + &Update prices + + + + + Ctrl+U + Ctrl+U + + + Save deck &as... Guardar mazo &como... - + Save deck to clip&board Guardar mazo al p&ortapales - + &Print deck... Im&primir mazo... - + &Close &Cerrar - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editar ediciones... - + &Deck &Mazo - + Load deck Cargar mazo - - + + Error Error - - + + The deck could not be saved. Please check that the directory is writable and try again. El mazo no puede guardarse Por favor, compruebe que tiene permisos de escritura en el directorio e intentelo de nuevo. - + Save deck Guardar mazo - + Add card to &maindeck Añadir carta al &mazo principal - + Return Return - + Enter Enter - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + Add card to &sideboard Añadir carta a la &reserva - + &Search... &Buscar... - + &Clear search &Limpiar busqueda - + &Card database &Base de datos de cartas - + &Remove row &Eliminar columna - + Del Del - + &Increment number &Incrementar número - + + + - + &Decrement number &Decrementar número - + - - - + Are you sure? ¿Estás seguro? - + The decklist has been modified. Do you want to save the changes? La lista del mazo ha sido modificada diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 9ade97a4f..7b65d7f3d 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -152,22 +152,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: Nom: - + Mana cost: Cout de mana: - + Card type: Type de carte: - + P / T: F / E: @@ -607,18 +627,36 @@ Nouvelle valeur pour le compteur '%1': + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + Géneral + + DeckListModel - + Number Nombre - + Card Carte + + + Price + + DeckViewContainer @@ -951,54 +989,59 @@ DlgSettings - - - + + + Error Erreur - + Your card database is invalid. Would you like to go back and set the correct path? Votre base de carte est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Le chemin d'accès pour le répertoire de votre deck est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Le chemin d'accès pour le répertoire de vos images est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + Settings Paramètres - + General Géneral - + Appearance Apparence - + User interface Interface utilisateur - + + Deck editor + + + + Messages Messages - + &Close &Fermer @@ -1006,68 +1049,68 @@ GameSelector - + Error Erreur - + Wrong password. Mot de passe erroné. - + Spectators are not allowed in this game. Les spectateurs ne sont pas autorisés dans cette partie. - + The game is already full. Cette partie est déjà pleine. - + The game does not exist any more. La partie n'existe plus. - + This game is only open to registered users. Cette partie n'est accessible qu'aux joueurs enregistrés. - + This game is only open to its creator's buddies. Cette partie n'est accessible qu'aux amis. - + You are being ignored by the creator of this game. Vous avez été ignoré par le créateur de la partie. - + Join game Rejoindre partie - + Password: Mot de passe: - + Games Parties - + Show &full games Montrer &toutes les parties @@ -1077,17 +1120,17 @@ &Montrer toutes les parties - + C&reate C&réer - + &Join Re&joindre - + J&oin as spectator Rej&oindre en tant que spectateur @@ -1287,27 +1330,27 @@ Japonais: - - + - - - + + + + Error Erreur - + Server timeout Délai de la demande dépassé - + Invalid login data. Information de connexion érronée. - + Socket error: %1 Erreur de socket: %1 @@ -1349,104 +1392,109 @@ Raison: %1 France: - + + Czech: + + + + There is already an active session using this user name. Please close that session first and re-login. Il y a déjà une session ouvert avec le même pseudo. Fermez cette session puis re-connectez-vous. - + 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. Vous tentez de vous connecter à un serveur obsolète. Chargez la nouvelle version de Cockatrice ou connectez-vous à un serveur approprié. La version la plus récente est %1, l'ancienne version est %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Votre client Cockatrice est obsolète. Veuillez charger la nouvelle version. La version la plus récente est %1, l'ancienne version est %2. - + Connecting to %1... Connexion à %1... - + Disconnected Déconnecté - + Logged in at %1 Connecté à %1 - + &Connect... à verifier &Connecter... - + &Disconnect &Déconnecter - + Start &local game... Démarrer une partie &locale... - + &Deck editor Éditeur de &deck - + &Full screen &Plein écran - + Ctrl+F Ctrl+F - + &Settings... &Paramètres... - + &Exit &Quitter - + &Cockatrice &Cockatrice - + &About Cockatrice À propos de Cock&atrice - + &Help A&ide - + Are you sure? Êtes-vous sûr? - + There are still open games. Are you sure you want to quit? Il y a encore des parties en cours. Êtes-vous sûr de vouloir quitter? @@ -1982,22 +2030,22 @@ La version la plus récente est %1, l'ancienne version est %2. MessagesSettingsPage - + Add message Ajouter message - + Message: Message: - + &Add &Ajouter - + &Remove &Enlever @@ -2465,17 +2513,17 @@ La version la plus récente est %1, l'ancienne version est %2.Réserve - + Cockatrice decks (*.cod) Decks format Cockatrice (*.cod) - + Plain text decks (*.dec *.mwDeck) Decks au format texte (*.dec *.mwDeck) - + All files (*.*) Tous les fichiers (*.*) @@ -2852,27 +2900,27 @@ Entrez un nom s'il vous plaît: TabRoom - + &Say: &Dire: - + Chat Chat - + &Room &Salon - + &Leave room &Quitter le salon - + You are flooding the chat. Please wait a couple of seconds. Vous floodez le chat. Veuillez patienter quelques secondes. @@ -3056,190 +3104,200 @@ Entrez 0 pour une durée illimitée du ban. WndDeckEditor - + &Search... &Chercher... - + &Clear search &Effacer la recherche - + &Search for: &Rechercher: - + Deck &name: &Nom du deck: - + &Comments: &Commentaires: - + + &Update prices + + + + + Ctrl+U + Ctrl+U + + + Deck editor [*] Editeur de deck [*] - + &New deck &Nouveau deck - + &Load deck... Char&ger deck... - + &Save deck &Sauvegarder le deck - + Save deck &as... S&auvegarder le deck sous... - + Load deck from cl&ipboard... Charger deck depuis le presse-pap&ier... - + Save deck to clip&board Sauve&garder le deck dans le presse-papier - + &Print deck... Im&primer le deck... - + &Close &Fermer - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editer les editions... - + &Deck &Deck - + &Card database Base de &cartes - + Add card to &maindeck Ajouter carte au &deck - + Return Retour - + Enter Entrer - + Add card to &sideboard Ajouter carte à la ré&serve - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove row &Retirer la ligne - + Del Supprimer - + &Increment number to check &Augmenter quantité - + + + - + &Decrement number to check &Diminuer quantité - + - - - + Are you sure? Êtes-vous sûr? - + The decklist has been modified. Do you want to save the changes? Le deck a été modifié. Voulez vous enregistrer les modifications? - + Load deck Charger deck - - + + Error Erreur - - + + The deck could not be saved. Please check that the directory is writable and try again. Le deck n'a pas pu être enregistré. Vérifiez que le répertoire ne soit pas en lecture seule et réessayez. - + Save deck Sauvegarder le deck diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index eaed4215b..ae2fddf75 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -157,22 +157,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: カード名: - + Mana cost: マナコスト: - + Card type: カードタイプ: - + P / T: @@ -601,18 +621,36 @@ カウンター '%1'の新しい値を設定する: + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + 全般 + + DeckListModel - + Number カード枚数 - + Card カード名 + + + Price + + DeckViewContainer @@ -938,54 +976,59 @@ DlgSettings - - - + + + Error エラー - + Your card database is invalid. Would you like to go back and set the correct path? あなたのカードデータベースは無効です.前に戻って正しいパスを設定してください. - + The path to your deck directory is invalid. Would you like to go back and set the correct path? あなたのデッキディレクトリへのパスは無効です.前に戻って正しいパスを設定してください. - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? あなたのカード画像ディレクトリへのパスは無効です.前に戻って正しいパスを設定してください. - + Settings 設定 - + General 全般 - + Appearance 外観 - + User interface ユーザーインターフェース - + + Deck editor + + + + Messages メッセージ - + &Close @@ -993,78 +1036,78 @@ GameSelector - + C&reate 部屋を作る - + &Join 参加する - + Error エラー - + Wrong password. パスワードが間違っています. - + Spectators are not allowed in this game. この試合は観戦者は許可されていません. - + The game is already full. このゲームはすでに満員です. - + The game does not exist any more. このゲームはもう存在しません. - + This game is only open to registered users. このゲームは登録済みプレイヤーにのみ公開されています. - + This game is only open to its creator's buddies. このゲームは作成者のフレンドのみに公開されています. - + You are being ignored by the creator of this game. あなたはこのゲームの作成者によって拒否されています. - + Join game 参加 - + Password: パスワード: - + Games ゲーム - + Show &full games 全てのゲームを見る @@ -1073,7 +1116,7 @@ 全てのゲームを見る - + J&oin as spectator 観戦者として参加 @@ -1302,128 +1345,133 @@ Reason: %1 ロシア語: - - + + Czech: + + + + - - - + + + + Error エラー - + Server timeout サーバータイムアウト - + Invalid login data. 無効なログインデータです. - + There is already an active session using this user name. Please close that session first and re-login. これはすでにこのユーザー名で使われているアクティブなセッションです. まずこのセッションを閉じてログインしなおしてください. - + Socket error: %1 ソケットエラー: %1 - + 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. あなたは古いVerのサーバーに接続しようとしています.CockatriceのVerをダウングレードするか適正なサーバーに接続してください. ローカルVer %1,リモートVer %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. あなたのCockatriceのVerが古いです.Cockatriceをアップデートしてください. ローカルVer %1,リモートVer %2. - + Connecting to %1... %1へ接続しています... - + Disconnected 切断されました - + Logged in at %1 %1にログイン中 - + &Connect... 接続... - + &Disconnect 切断 - + Start &local game... ローカルゲームを開始... - + &Deck editor デッキエディター - + &Full screen フルスクリーン - + Ctrl+F - + &Settings... 設定... - + &Exit 終了 - + &Cockatrice - + &About Cockatrice - + &Help ヘルプ - + Are you sure? よろしいですか? - + There are still open games. Are you sure you want to quit? ゲームがまだ開いています.本当に退出しますか? @@ -1926,22 +1974,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + &Add 追加 - + &Remove 削除 - + Add message メッセージを追加する - + Message: メッセージ: @@ -2400,17 +2448,17 @@ Local version is %1, remote version is %2. サイドボード - + Cockatrice decks (*.cod) - + Plain text decks (*.dec *.mwDeck) - + All files (*.*) 全てのファイル (*.*) @@ -2784,27 +2832,27 @@ Please enter a name: TabRoom - + &Say: 発言する - + Chat チャット - + &Room 部屋 - + &Leave room 部屋から出る - + You are flooding the chat. Please wait a couple of seconds. あなたはチャットルームから弾かれました.少々お待ちください. @@ -2986,186 +3034,196 @@ Enter 0 for an indefinite ban. WndDeckEditor - + &Search for: 検索: - + Deck &name: デッキ名: - + &Comments: コメント: - + Deck editor [*] デッキエディター [*] - + &New deck 新しいデッキ - + &Load deck... デッキをロード... - + Load deck from cl&ipboard... クリップボードからデッキをロード... - + &Save deck デッキを保存 - + + &Update prices + + + + + Ctrl+U + + + + Save deck &as... 名前を付けてデッキを保存... - + Save deck to clip&board クリップボードにデッキを保存 - + &Print deck... デッキを印刷... - + &Close 閉じる - + Ctrl+Q - + &Edit sets... セットの設定... - + &Deck デッキ - + Load deck デッキをロード - - + + Error エラー - - + + The deck could not be saved. Please check that the directory is writable and try again. 要検証 このデッキは保存されていません. ディレクトリをチェックして再度上書きしてください. - + Save deck デッキを保存 - + Add card to &maindeck メインデッキにカードを加える - + Return - + Enter - + Ctrl+Return - + Ctrl+Enter - + Add card to &sideboard サイドボードにカードを加える - + &Search... 検索... - + &Clear search 検索を解除 - + &Card database カードデータベース - + &Remove row 全て取り除く - + Del - + &Increment number 枚数を増やす - + + - + &Decrement number 枚数を減らす - + - - + Are you sure? 本当によろしいですか? - + The decklist has been modified. Do you want to save the changes? このデッキリストは変更されています.変更を保存しますか? diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 507edcb34..f3efd5608 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -156,22 +156,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: Nome: - + Mana cost: Custo de mana: - + Card type: Tipo de card: - + P / T: P / R: @@ -611,18 +631,36 @@ Novo valor para o marcador '%1': + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + Geral + + DeckListModel - + Number Número - + Card Card + + + Price + + DeckViewContainer @@ -955,54 +993,59 @@ DlgSettings - - - + + + Error Erro - + Your card database is invalid. Would you like to go back and set the correct path? O seu banco de dados de cards é inválido. Você gostaria de voltar e corrigir o caminho? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? O caminho para a sua pasta de decks é inválido. Você gostaria de voltar e corrigir o caminho? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? O caminho para a sua pasta de imagens de cards é inválido. Você gostaria de voltar e corrigir o caminho? - + Settings Configurações - + General Geral - + Appearance Aparência - + User interface Interface do usuário - + + Deck editor + + + + Messages Mensagens - + &Close &Fechar @@ -1010,78 +1053,78 @@ GameSelector - + C&reate &Criar - + &Join &Entrar - + Error Erro - + Wrong password. Senha incorreta. - + Spectators are not allowed in this game. Não são permitidos visitantes neste jogo. - + The game is already full. O jogo está cheio. - + The game does not exist any more. O jogo não existe mais. - + This game is only open to registered users. Este jogo é aberto apenas para usuários registrados. - + This game is only open to its creator's buddies. Este jogo é aberto apenas para os amigos de quem criou o jogo. - + You are being ignored by the creator of this game. Você está sendo ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Senha: - + Games Jogos - + Show &full games &Mostrar os jogos cheios @@ -1090,7 +1133,7 @@ &Mostrar os jogos cheios - + J&oin as spectator E&ntrar como visitante @@ -1295,27 +1338,27 @@ Russo: - - + - - - + + + + Error Erro - + Server timeout Tempo esgotado do servidor - + Invalid login data. Informações de login inválidas. - + Socket error: %1 Erro de ligação:%1 @@ -1351,103 +1394,108 @@ Reason: %1 Razão: %1 - + + Czech: + + + + There is already an active session using this user name. Please close that session first and re-login. Já existe uma sessão ativa usando este nome de usuário. Por favor, feche a sessão primeiro e logue novamente. - + 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. Você está tentando conectar a um servidor obsoleto. Por favor, faça um downgrade na versão do seu Cockatrice ou conecte-se ao servidor correto. A versão local é %1 e a versão remota é %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. A versão do seu Cockatrice é obsoleta. Por favor, atualize a sua versão. A versão local é %1 e a versão remota é %2. - + Connecting to %1... Conectando a %1... - + Disconnected Desconectado - + Logged in at %1 Logado em %1 - + &Connect... &Conectar... - + &Disconnect &Desconectar - + Start &local game... Iniciar jogo &local... - + &Deck editor Editor de &decks - + &Full screen Tela &cheia - + Ctrl+F Ctrl+F - + &Settings... &Configurações... - + &Exit &Sair - + &Cockatrice &Cockatrice - + &About Cockatrice So&bre o Cockatrice - + &Help &Ajuda - + Are you sure? Você tem certeza? - + There are still open games. Are you sure you want to quit? Ainda existem jogos abertos. Você tem certeza que deseja sair? @@ -1967,22 +2015,22 @@ A versão local é %1 e a versão remota é %2. MessagesSettingsPage - + &Add &Adicionar - + &Remove &Remover - + Add message Adicionar mensagem - + Message: Mensagem: @@ -2449,17 +2497,17 @@ A versão local é %1 e a versão remota é %2. Sideboard - + Cockatrice decks (*.cod) Decks Cockatrice (*.cod) - + Plain text decks (*.dec *.mwDeck) Decks de texto simples (*.dec *.mwDeck) - + All files (*.*) Todos os arquivos (*.*) @@ -2834,27 +2882,27 @@ Por favor, entre um nome: TabRoom - + &Say: &Falar: - + Chat Chat - + &Room &Sala - + &Leave room S&air da sala - + You are flooding the chat. Please wait a couple of seconds. Você está flodando o chat. Por favor, espere alguns segundos. @@ -3037,186 +3085,196 @@ Digite 0 para banir indefinidamente. WndDeckEditor - + &Search for: &Buscar por: - + Deck &name: Nome do &deck: - + &Comments: &Comentários: - + Deck editor [*] Editor de decks [*] - + &New deck &Novo deck - + &Load deck... &Abrir deck... - + Load deck from cl&ipboard... Carregar deck da área de &transferência... - + &Save deck &Salvar deck - + + &Update prices + + + + + Ctrl+U + Ctrl+U + + + Save deck &as... Salvar deck c&omo... - + Save deck to clip&board Salvar deck para a área de t&ransferência - + &Print deck... &Imprimir deck... - + &Close &Fechar - + Ctrl+Q Ctrl+Q - + &Edit sets... E&ditar expansões... - + &Deck &Deck - + Load deck Abrir deck - - + + Error Erro - - + + The deck could not be saved. Please check that the directory is writable and try again. O deck não pôde ser salvo. Por favor, verifique se o diretório não é somente leitura e tente novamente. - + Save deck Salvar deck - + Add card to &maindeck Incluir no deck &principal - + Return Return - + Enter Enter - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + Add card to &sideboard Incluir no side&board - + &Search... B&uscar... - + &Clear search &Limpar busca - + &Card database Banco de dados de &cards - + &Remove row &Apagar linha - + Del Del - + &Increment number &Aumentar quantidade - + + + - + &Decrement number &Diminuir quantidade - + - - - + Are you sure? Você tem certeza? - + The decklist has been modified. Do you want to save the changes? O deck foi modificado. diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index cef7cf2c6..99b8005fd 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -156,22 +156,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: Nome: - + Mana cost: Custo de Mana: - + Card type: Tipo de carta: - + P / T: P / R: @@ -611,18 +631,36 @@ Novo valor para o marcador '%1': + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + Geral + + DeckListModel - + Number Número - + Card Carta + + + Price + + DeckViewContainer @@ -955,54 +993,59 @@ DlgSettings - - - + + + Error Erro - + Your card database is invalid. Would you like to go back and set the correct path? A sua base de dados é inválida. Gostaria de voltar atrás e corrigir o directório? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? O directório do seu deck é inválido. Gostaria de voltar atrás e corrigir o directório? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? O directório das imagens das cartas é inválido. Gostaria de voltar atrás e corrigir o directório? - + Settings Definições - + General Geral - + Appearance Aparência - + User interface Interface do utilizador - + + Deck editor + + + + Messages Mensagens - + &Close &Fechar @@ -1010,68 +1053,68 @@ GameSelector - + Error Erro - + Wrong password. Password incorrecta. - + Spectators are not allowed in this game. Não são permitidos espectadores neste jogo. - + The game is already full. O jogo já se encontra cheio. - + The game does not exist any more. O jogo já não existe. - + This game is only open to registered users. Este jogo só está aberto a utilizadores registados. - + This game is only open to its creator's buddies. Este jogo só está aberto aos amigos do seu criador. - + You are being ignored by the creator of this game. Você está a ser ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Password: - + Games Jogos - + Show &full games &Mostrar jogos cheios @@ -1080,17 +1123,17 @@ &Mostrar jogos cheios - + C&reate &Criar - + &Join &Entrar - + J&oin as spectator Entrar como &espectador @@ -1299,27 +1342,27 @@ Russo: - - + - - - + + + + Error Erro - + Server timeout Tempo do servidor esgotado - + Invalid login data. Informação de login incorrecta. - + Socket error: %1 Erro de ligação:%1 @@ -1355,103 +1398,108 @@ Reason: %1 Motivo: %1 - + + Czech: + + + + There is already an active session using this user name. Please close that session first and re-login. Já existe uma sessão activa com este nome de utilizador. Por favor termine essa sessão e volte a ligar-se. - + 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. Está a tentar ligar-se a um servidor obsoleto. Por favor faça downgrade à sua versão do Cockatrice ou ligue-se a servidor adequado. Versão local é %1, versão remota é %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. A sua versão do Cockatrice é obsoleta. Por favor actualize-a. Versão local é %1, versão remota é %2. - + Connecting to %1... Ligando a %1... - + Disconnected Desligado - + Logged in at %1 Logado em %1 - + &Connect... &Ligar... - + &Disconnect &Desligar - + Start &local game... Começar &jogo local... - + &Deck editor &Editor de decks - + &Full screen Ecrã &inteiro - + Ctrl+F Ctrl+F - + &Settings... &Configurações... - + &Exit &Sair - + &Cockatrice &Cockatrice - + &About Cockatrice S&obre o Cockatrice - + &Help &Ajuda - + Are you sure? Tens a certeza? - + There are still open games. Are you sure you want to quit? Ainda há jogos abertos. Tem a certeza que deseja sair? @@ -1971,22 +2019,22 @@ Versão local é %1, versão remota é %2. MessagesSettingsPage - + Add message Adicionar mensagem - + Message: Mensagem: - + &Add &Adicionar - + &Remove &Remover @@ -2453,17 +2501,17 @@ Versão local é %1, versão remota é %2. Sideboard - + Cockatrice decks (*.cod) Decks do Cockatrice (*.cod) - + Plain text decks (*.dec *.mwDeck) Decks baseados em texto simples (*.dec *.mwDeck) - + All files (*.*) Todos os ficheiros (*.*) @@ -2838,27 +2886,27 @@ Por favor introduza um nome: TabRoom - + &Say: &Dizer: - + Chat - + &Room &Sala - + &Leave room &Abandonar a sala - + You are flooding the chat. Please wait a couple of seconds. Estás a inundar o chat .Por favor aguarde alguns segundos. @@ -3041,188 +3089,198 @@ Introduza 0 para um banimento indefinido. WndDeckEditor - + &Search... &Procurar... - + &Clear search &Limpar pesquisa - + &Search for: &Procurar por: - + Deck &name: &Nome do deck: - + &Comments: &Comentários: - + + &Update prices + + + + + Ctrl+U + Ctrl+U + + + Deck editor [*] Editor de decks [*] - + &New deck &Novo deck - + &Load deck... &Carregar deck... - + &Save deck &Guardar deck - + Save deck &as... G&uardar deck como... - + Load deck from cl&ipboard... Carregar dec&k da memória... - + Save deck to clip&board Guardar deck na &memória - + &Print deck... &Imprimir deck... - + &Close &Fechar - + Ctrl+Q Ctrl+Q - + &Edit sets... &Editar expansões... - + &Deck &Deck - + &Card database &Base de dados das cartas - + Add card to &maindeck Adicionar carta ao &maindeck - + Return Return - + Enter Enter - + Add card to &sideboard Adicionar carta ao &sideboard - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove row &Remover linha - + Del Del - + &Increment number &Aumentar o número - + + + - + &Decrement number &Diminuir o número - + - - - + Are you sure? Tem a certeza? - + The decklist has been modified. Do you want to save the changes? A lista foi modificada. Gostaria de guardar as alterações? - + Load deck Carregar deck - - + + Error Erro - - + + The deck could not be saved. Please check that the directory is writable and try again. O deck não pode ser guardado. Por favor confirme se é possível escrever do directório e tente de novo. - + Save deck Guardar deck diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 0f21ddfd0..2bb0a7a4d 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -152,22 +152,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: Название: - + Mana cost: Манакост: - + Card type: Тип: - + P / T: Сила/Защита: @@ -557,18 +577,36 @@ сайд %1-го игрока + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + Основные + + DeckListModel - + Number Номер - + Card Название + + + Price + + DeckViewContainer @@ -894,54 +932,59 @@ DlgSettings - - - + + + Error Ошибка - + Your card database is invalid. Would you like to go back and set the correct path? База карт не найдена. Вернуться и задать правильный путь? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Ваши колоды отсутствуют в указанной папке. Вернуться и задать правильный путь? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Изображения карт не найдены. Вернуться и задать правильный путь? - + Settings Настройки - + General Основные - + Appearance Внешний вид - + User interface Интерфейс - + + Deck editor + + + + Messages Сообщения - + &Close &Закрыть @@ -949,83 +992,83 @@ GameSelector - + Error Ошибка - + Wrong password. Неверный пароль. - + Spectators are not allowed in this game. В эту игру не пускают зрителей. - + The game is already full. Все места заняты! =Ь - + The game does not exist any more. Эта игра была удалена. - + This game is only open to registered users. Доступно только для зарегистрированных. - + This game is only open to its creator's buddies. Доступно только для друзей. - + You are being ignored by the creator of this game. Вы добавлены в игнор-лист данного игрока. - + Join game Присоединиться - + Password: Пароль: - + Games Игры - + Show &full games Показывать &текущие - + C&reate С&оздать - + &Join &Присоединиться - + J&oin as spectator П&рисоединиться как зритель @@ -1253,128 +1296,133 @@ Reason: %1 Русский: - - + + Czech: + + + + - - - + + + + Error Ошибка - + Server timeout Временная ошибка - + Invalid login data. Неверный логин/пароль. - + There is already an active session using this user name. Please close that session first and re-login. Пользователь с таким именем уже подключен. Пожалуйста, закройте это подключение и войдите заново. - + Socket error: %1 Ошибка сокета: %1 - + 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. Вы пытаетесь подключиться к несуществующему серверу. Пожалуйста, обновите Cockatrice или выберите другой сервер. Локальная версия %1, удаленная версия %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Ваш клиент Cockatrice устарел. Пожалуйста, обновите Cockatrice. Локальная версия %1, удаленная версия %2. - + Connecting to %1... Подключение к %1... - + Disconnected Подключение прервано - + Logged in at %1 Подключено к %1 - + &Connect... &Подключение... - + &Disconnect П&рервать подключение - + Start &local game... &Начать локальную игру... - + &Deck editor Редактор &колод - + &Full screen П&олный экран - + Ctrl+F - + &Settings... Н&астройки - + &Exit &Выход - + &Cockatrice - + &About Cockatrice О про&грамме - + &Help &Справка - + Are you sure? Вы уверены? - + There are still open games. Are you sure you want to quit? Вы подключены к игре. Выйти? @@ -1903,22 +1951,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Add message Добавить сообщение - + Message: Сообщение: - + &Add &Добавить - + &Remove &Удалить @@ -2377,17 +2425,17 @@ Local version is %1, remote version is %2. Сайд - + Cockatrice decks (*.cod) Cockatrice-деклисты (*.cod) - + Plain text decks (*.dec *.mwDeck) Текстовые деклисты (*.dec *.mwDeck) - + All files (*.*) Все файлы (*.*) @@ -2736,27 +2784,27 @@ Please enter a name: TabRoom - + &Say: &Сказать: - + Chat Чат - + &Room &Комната - + &Leave room &Покинуть комнату - + You are flooding the chat. Please wait a couple of seconds. Кажется, Вы нафлудили. Пожалуйста, подождите пару секунд. @@ -2931,188 +2979,198 @@ Enter 0 for an indefinite ban. WndDeckEditor - + &Search... &Поиск... - + &Clear search &Очистить строку поиска - + &Search for: &Искать: - + Deck &name: &Название колоды: - + &Comments: Ко&мментарии: - + + &Update prices + + + + + Ctrl+U + + + + Deck editor [*] Редактор колод [*] - + &New deck Новая коло&да - + &Load deck... &Загрузить колоду... - + &Save deck Со&хранить колоду - + Save deck &as... Сохранить колоду к&ак... - + Load deck from cl&ipboard... Взять колоду из &буфера... - + Save deck to clip&board Копировать колоду в бу&фер - + &Print deck... Пе&чать колоды... - + &Close &Закрыть - + Ctrl+Q - + &Edit sets... Редактировать издани&я... - + &Deck Ко&лода - + &Card database База кар&т - + Add card to &maindeck Добавить ме&йном - + Return - + Enter - + Add card to &sideboard Добавить в са&йд - + Ctrl+Return - + Ctrl+Enter - + &Remove row &Удалить строку - + Del - + &Increment number У&величить количество - + + - + &Decrement number У&меньшить количество - + - - + Are you sure? Вы уверены? - + The decklist has been modified. Do you want to save the changes? Деклист был отредактирован. Сохранить изменения? - + Load deck Загрузить колоду - - + + Error Ошибка - - + + The deck could not be saved. Please check that the directory is writable and try again. Колода не может быть сохранена. Убедитесь, что директория указана верно,а затем повторите попытку. - + Save deck Сохранить колоду From 009000d13055fe2de37059687549368eec2c01c8 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 18 Jun 2011 12:47:24 +0200 Subject: [PATCH 52/87] fixed cz -> cs language code, added slovak translation stub --- cockatrice/cockatrice.pro | 5 +- cockatrice/cockatrice.qrc | 3 +- cockatrice/src/window_main.cpp | 1 + cockatrice/translations/cockatrice_de.ts | 259 +- cockatrice/translations/cockatrice_en.ts | 259 +- cockatrice/translations/cockatrice_es.ts | 259 +- cockatrice/translations/cockatrice_fr.ts | 259 +- cockatrice/translations/cockatrice_ja.ts | 259 +- cockatrice/translations/cockatrice_pl.ts | 763 +++-- cockatrice/translations/cockatrice_pt-br.ts | 259 +- cockatrice/translations/cockatrice_pt.ts | 259 +- cockatrice/translations/cockatrice_ru.ts | 259 +- cockatrice/translations/cockatrice_sk.ts | 3161 +++++++++++++++++++ 13 files changed, 4653 insertions(+), 1352 deletions(-) create mode 100644 cockatrice/translations/cockatrice_sk.ts diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index fc02842b9..045994096 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -182,8 +182,9 @@ TRANSLATIONS += \ translations/cockatrice_fr.ts \ translations/cockatrice_ja.ts \ translations/cockatrice_ru.ts \ - translations/cockatrice_cz.ts \ - translations/cockatrice_pl.ts + translations/cockatrice_cs.ts \ + translations/cockatrice_pl.ts \ + translations/cockatrice_sk.ts win32 { RC_FILE = cockatrice.rc diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 1f04c4050..abeeeeab2 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -46,8 +46,9 @@ translations/cockatrice_fr.qm translations/cockatrice_ja.qm translations/cockatrice_ru.qm - translations/cockatrice_cz.qm + translations/cockatrice_cs.qm translations/cockatrice_pl.qm + translations/cockatrice_sk.qm resources/countries/at.svg resources/countries/au.svg diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index fed1e75a9..595e8b8e0 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -179,6 +179,7 @@ void MainWindow::actAbout() + tr("Japanese:") + " Nagase Task
" + tr("Russian:") + " Alexander Davidov
" + tr("Czech:") + " Ondřej Trhoň
" + + tr("Slovak:") + " Ganjalf Rendy
" )); } diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 8dc03b81b..6dff3bbc7 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -1897,46 +1897,51 @@ Grund: %1 Tschechisch: - - + + Slovak: + + + + - - - + + + + Error Fehler - + Server timeout Server Zeitüberschreitung - + Invalid login data. Ungültige Anmeldedaten. - + There is already an active session using this user name. Please close that session first and re-login. Es gibt bereits eine aktive Verbindung mit diesem Benutzernamen. Bitte schließen Sie diese Verbindung zuerst und versuchen Sie es dann erneut. - + Socket error: %1 Netzwerkfehler: %1 - + 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. Sie versuchen sich an einem veralteten Server anzumelden. Bitte verwenden Sie eine ältere Cockatrice-Version oder melden Sie sich an einem aktuellen Server an. Lokale Version ist %1, Serverversion ist %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Ihr Cockatrice-Client ist veraltet. Bitte laden Sie sich die neueste Version herunter. @@ -1947,52 +1952,52 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversionen stimmen nicht überein. Lokale Version: %1, Serverversion: %2. - + Connecting to %1... Verbinde zu %1... - + Disconnected nicht verbunden - + Logged in at %1 Angemeldet bei %1 - + &Connect... &Verbinden... - + &Disconnect Verbindung &trennen - + Start &local game... &Lokales Spiel starten... - + &About Cockatrice &Über Cockatrice - + &Help &Hilfe - + Are you sure? Sind Sie sicher? - + There are still open games. Are you sure you want to quit? Es gibt noch offene Spiele. Wollen Sie das Programm wirklich beenden? @@ -2009,27 +2014,27 @@ Lokale Version ist %1, Serverversion ist %2. Spiel ver&lassen - + &Deck editor &Deck-Editor - + &Full screen &Vollbild - + Ctrl+F Ctrl+F - + &Settings... &Einstellungen... - + &Exit &Beenden @@ -2042,7 +2047,7 @@ Lokale Version ist %1, Serverversion ist %2. Esc - + &Cockatrice &Cockatrice @@ -2070,22 +2075,22 @@ Lokale Version ist %1, Serverversion ist %2. MessageLogWidget - + Connecting to %1... Verbinde zu %1... - + Connected. Verbunden. - + Disconnected from server. Verbindung zum Server getrennt. - + Invalid password. Ungültiges Passwort. @@ -2126,8 +2131,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten - - + + a card eine Karte @@ -2184,12 +2189,12 @@ Lokale Version ist %1, Serverversion ist %2. %1s Sideboard - + The game has started. Das Spiel hat begonnen. - + %1 shuffles his library. %1 mischt seine Bibliothek. @@ -2206,72 +2211,72 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversion stimmt nicht überein. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. Protokollfehler. - + You have joined game #%1. Sie sind dem Spiel %1 beigetreten. - + %1 has joined the game. %1 ist dem Spiel beigetreten. - + %1 has left the game. %1 hat das Spiel verlassen. - + The game has been closed. Das Spiel wurde geschlossen. - + %1 is now watching the game. %1 schaut nun dem Spiel zu. - + %1 is not watching the game any more. %1 schaut dem Spiel nicht mehr zu. - + %1 has loaded a local deck. %1 hat ein lokales Deck geladen. - + %1 has loaded deck #%2. %1 hat das Deck Nr. %2 geladen. - + %1 is ready to start the game. %1 ist bereit, das Spiel zu starten. - + %1 is not ready to start the game any more. %1 ist nicht mehr bereit, das Spiel zu starten. - + %1 has conceded the game. %1 hat das Spiel aufgegeben. - + %1 rolls a %2 with a %3-sided die. %1 würfelt eine %2 mit einem %3-seitigen Würfel. @@ -2284,7 +2289,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten. - + %1 draws %n card(s). %1 zieht eine Karte. @@ -2292,132 +2297,132 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 undoes his last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes his last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + from the bottom of his library , die unterste Karte seiner Bibliothek, - + the top card of his library die oberste Karte seiner Bibliothek - + from the top of his library , die oberste Karte seiner Bibliothek, - + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + from the stack vom Stapel - + %1 gives %2 control over %3. %1 überlässt %2 die Kontrolle über %3. - + %1 puts %2 into play tapped%3. %1 bringt %2 getappt%3 ins Spiel. - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 plays %2%3. %1 spielt %2%3 aus. - + %1 takes a mulligan to %n. %1 nimmt einen Mulligan auf %n. @@ -2425,47 +2430,47 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 draws his initial hand. %1 zieht seine Starthand. - + %1 flips %2 face-down. %1 wendet %2 auf die Rückseite. - + %1 flips %2 face-up. %1 wendet %2 auf die Vorderseite. - + %1 destroys %2. %1 zerstört %2. - + %1 attaches %2 to %3's %4. %1 legt %2 an %3s %4 an. - + %1 unattaches %2. %1 löst %2 ab. - + %1 creates token: %2%3. %1 erstellt Token: %2%3. - + %1 points from %2's %3 to %4. %1 zeigt von %2s %3 auf %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 legt eine %2 Marke auf %3 (jetzt %4). @@ -2473,7 +2478,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 entfernt eine %2 Marke von %3 (jetzt %4). @@ -2481,22 +2486,22 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 randomly reveals %2%3 to %4. %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3. %1 zeigt zufällig %2%3 offen vor. - + %1 reveals %2%3 to %4. %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3. %1 zeigt %2%3 offen vor. @@ -2505,7 +2510,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 erstellt einen Spielstein: %2 (%3). - + %1 points from %2's %3 to %4's %5. %1 zeigt von %2s %3 auf %4s %5. @@ -2524,7 +2529,7 @@ Lokale Version ist %1, Serverversion ist %2. - + red rote @@ -2532,7 +2537,7 @@ Lokale Version ist %1, Serverversion ist %2. - + yellow gelbe @@ -2540,7 +2545,7 @@ Lokale Version ist %1, Serverversion ist %2. - + green grüne @@ -2548,22 +2553,22 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 sets counter %2 to %3 (%4%5). %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets PT of %2 to %3. %1 setzt Kampfwerte von %2 auf %3. - + %1 sets annotation of %2 to %3. %1 versieht %2 mit dem Hinweis %3. - + %1 is looking at the top %2 cards %3. %1 sieht sich die obersten %2 Karten %3 an. @@ -2660,7 +2665,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4). - + %1 %2 %3. %1 %2 %3. @@ -2673,22 +2678,22 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. %1 sieht sich %2 an. - + %1 stops looking at %2. %1 sieht sich %2 nicht mehr an. - + %1 reveals %2 to %3. %1 zeigt %3 %2. - + %1 reveals %2. %1 zeigt %2 offen vor. @@ -2709,7 +2714,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zeigt %2 aus %3 offen vor. - + ending phase die Zugendphase @@ -2738,57 +2743,57 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich %2s %3 nicht mehr an - + It is now %1's turn. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -2797,7 +2802,7 @@ Lokale Version ist %1, Serverversion ist %2. das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -2806,12 +2811,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 bewegt %2 %3 nach %4 - + taps tappt - + untaps enttappt @@ -2836,7 +2841,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4) - + his permanents seine bleibenden Karten @@ -2849,12 +2854,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 setzt Zähler "%2" auf %3 (%4%5) - + %1 sets %2 to not untap normally. %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. %1 setzt %2 auf normales Enttappen. @@ -3369,7 +3374,7 @@ Lokale Version ist %1, Serverversion ist %2. - + Number: Anzahl: @@ -3384,27 +3389,27 @@ Lokale Version ist %1, Serverversion ist %2. Oberste Karten ins Exil schicken - + Set power/toughness Kampfwerte setzen - + Please enter the new PT: Bitte die neuen Kampfwerte eingeben: - + Set annotation Hinweis setzen - + Please enter the new annotation: Bitte den Hinweis eingeben: - + Set counters Setze Zählmarken diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 901534114..233563803 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -1296,125 +1296,130 @@ Reason: %1 - - + + Slovak: + + + + - - - + + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -1422,52 +1427,52 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). %1 draws a card. @@ -1475,158 +1480,158 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes his last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + from the bottom of his library - + the top card of his library - + from the top of his library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 into his library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1645,7 +1650,7 @@ Local version is %1, remote version is %2. - + red @@ -1653,7 +1658,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1661,7 +1666,7 @@ Local version is %1, remote version is %2. - + green @@ -1669,77 +1674,77 @@ Local version is %1, remote version is %2. - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. - + %1 takes a mulligan to %n. @@ -1747,27 +1752,27 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 places a %2 counter on %3 (now %4). @@ -1775,7 +1780,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 removes a %2 counter from %3 (now %4). @@ -1783,142 +1788,142 @@ Local version is %1, remote version is %2. - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 shuffles his library. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2277,7 +2282,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2302,27 +2307,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 582079f11..6fe34f61e 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -1512,46 +1512,51 @@ Motivo: %1 - - + + Slovak: + + + + - - - + + + + Error Error - + Server timeout Tiempo de espera del servidor agotado - + Invalid login data. Datos de conexión invalidos. - + There is already an active session using this user name. Please close that session first and re-login. Ya existe una sesión activa usando ese nombre de usuario. Por favor, cierra esa sesión primero y reintentalo. - + Socket error: %1 Error del Socket: %1 - + 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. Estás intentando conectar a un servidor obsoleto. Por favor, usa una versión anterior de Cockatrice o conecta a un servidor apropiado. La versión local es %1, la versión remota es %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Tu cliente de Cockatrice esta obsoleto. Por favor, actualiza tu versión de Cockatrice. @@ -1562,82 +1567,82 @@ La versión local es %1, la versión remota es %2. La versión del protocolo es diferente. Version local: %1, version remota: %2. - + Connecting to %1... Conectando a %1... - + Disconnected Desconectado - + Logged in at %1 Conectado en %1 - + &Connect... &Conectar... - + &Disconnect &Desconectar - + Start &local game... Empezar partida &local... - + &Deck editor Editor de &mazos - + &Full screen &Pantalla completa - + Ctrl+F CTRL+F - + &Settings... &Preferencias... - + &Exit &Salir - + &Cockatrice &Cockatrice - + &About Cockatrice &Acerca de Cockatrice - + &Help A&yuda - + Are you sure? ¿Estás seguro? - + There are still open games. Are you sure you want to quit? Todavía hay partidas abiertas. ¿Estás seguro que quieres salir? @@ -1645,52 +1650,52 @@ La versión local es %1, la versión remota es %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado del servidor. - + Invalid password. Contraseña incorrecta. - + Protocol error. Error del protocolo. - + The game has been closed. La partida ha sido cerrada. - + %1 is now watching the game. %1 está ahora observando la partida. - + %1 is not watching the game any more. %1 ya no está observado más la partida. - + %1 is not ready to start the game any more. %1 ya no está listo para empezar el juego. - + %1 rolls a %2 with a %3-sided die. %1 sacó un %2 con un dado de %3 caras. - + %1 draws %n card(s). %1 roba %n carta. @@ -1698,158 +1703,158 @@ La versión local es %1, la versión remota es %2. - + %1 undoes his last draw. %1 deshace su último robo. - + %1 undoes his last draw (%2). %1 deshace su último robo (%2). - + from table de la mesa - + from graveyard del cementerio - + from exile del exilio - + from hand de la mano - + the bottom card of his library el fondo de la biblioteca - + from the bottom of his library del fondo de la biblioteca - + the top card of his library la parte superior de la biblioteca - + from the top of his library de la parte superior de la biblioteca - + from library de la biblioteca - + from sideboard de la reserva - + from the stack de la pila - + %1 gives %2 control over %3. %1 entrega a %2 el control sobre %3. - + %1 puts %2 into play tapped%3. %1 pone %2 en juego%3 girado. - + %1 puts %2 into play%3. %1 pone %2 en juego%3. - + %1 puts %2%3 into graveyard. %1 pone %2%3 en el cementerio. - + %1 exiles %2%3. %1 exilia %2%3. - + %1 moves %2%3 to hand. %1 mueve %2%3 a la mano. - + %1 puts %2%3 into his library. %1 pone %2%3 en la biblioteca. - + %1 puts %2%3 on bottom of his library. %1 pone %2%3 en la parte inferior de su biblioteca. - + %1 puts %2%3 on top of his library. %1 pone %2%3 en la parte superior de su biblioteca. - + %1 puts %2%3 into his library at position %4. %1 pone %2%3 en su biblioteca en la posición %4. - + %1 moves %2%3 to sideboard. %1 mueve %2%3 a la reserva. - + %1 plays %2%3. %1 juega %2%3. - - + + a card una carta - + %1 flips %2 face-down. %1 voltea %2 boca abajo. - + %1 flips %2 face-up. %1 voltea %2 boca arriba. - + %1 attaches %2 to %3's %4. %1 anexa %2 a el %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 apunta desde el %3 de %2 al %5 de %4. @@ -1868,7 +1873,7 @@ La versión local es %1, la versión remota es %2. - + red rojo @@ -1876,7 +1881,7 @@ La versión local es %1, la versión remota es %2. - + yellow amarillo @@ -1884,7 +1889,7 @@ La versión local es %1, la versión remota es %2. - + green verde @@ -1892,72 +1897,72 @@ La versión local es %1, la versión remota es %2. - + %1 sets counter %2 to %3 (%4%5). %1 establece los contadores de %2 a %3 (%4%5). - + %1 sets PT of %2 to %3. %1 establece F/R de %2 a %3. - + %1 sets annotation of %2 to %3. %1 establece la anotación de %2 a %3. - + %1 is looking at the top %2 cards %3. %1 esta mirando las primeras %2 cartas de %3. - + The game has started. La partida ha comenzado. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 La versión del protocolo es diferente. Cliente: %1, Servidor: %2 - + You have joined game #%1. Te has unido a la partida #%1. - + %1 has joined the game. %1 se ha unido a la partida. - + %1 has left the game. %1 ha dejado la partida. - + %1 has loaded a local deck. %1 ha cargado un mazo local. - + %1 has loaded deck #%2. %1 ha cargado el mazo #%2. - + %1 is ready to start the game. %1 está preparado para empezar la partida. - + %1 has conceded the game. %1 ha concedido la partida. @@ -1970,22 +1975,22 @@ La versión local es %1, la versión remota es %2. %1 roba %2 cartas. - + %1 destroys %2. %1 destruye %2. - + %1 creates token: %2%3. %1 crea una ficha: %2%3. - + %1 points from %2's %3 to %4. %1 apunta desde el %3 de %2 a %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 pone %n %2 contador en %3 (ahora %4). @@ -1993,7 +1998,7 @@ La versión local es %1, la versión remota es %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remueve %n %2 contador en %3 (ahora %4). @@ -2001,47 +2006,47 @@ La versión local es %1, la versión remota es %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está mirando: %2. - + %1 stops looking at %2. %1 termina de mirar: %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase de fin de turno - + It is now %1's turn. Es el turno de %1. - + %1 shuffles his library. %1 baraja su biblioteca. - + %1 takes a mulligan to %n. @@ -2049,107 +2054,107 @@ La versión local es %1, la versión remota es %2. - + %1 draws his initial hand. - + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3 a %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step paso de enderezar - + upkeep step paso de mantenimiento - + draw step paso de robar - + first main phase primera fase principal - + beginning of combat step paso de inicio de combate - + declare attackers step paso de declarar atacantes - + declare blockers step paso de declarar bloqueadores - + combat damage step paso de daño de combate - + end of combat step paso de fin de combate - + second main phase segunda fase principal - + It is now the %1. Ahora es el %1. - + taps gira - + untaps endereza - + %1 sets %2 to not untap normally. %1 establece que %2 no se endereze normalmente. - + %1 sets %2 to untap normally. %1 establece que %2 se endereze normalmente. - + his permanents sus permanentes @@ -2516,7 +2521,7 @@ La versión local es %1, la versión remota es %2. - + Number: Número: @@ -2541,27 +2546,27 @@ La versión local es %1, la versión remota es %2. Número de caras: - + Set power/toughness Establecer fuerza/resistencia - + Please enter the new PT: Por favor, introduzca la nueva F/R: - + Set annotation Escribir anotación - + Please enter the new annotation: Por favor, introduza la nueva anotación: - + Set counters Establecer contadores diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 7b65d7f3d..242d66bb6 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -1330,27 +1330,27 @@ Japonais: - - + - - - + + + + Error Erreur - + Server timeout Délai de la demande dépassé - + Invalid login data. Information de connexion érronée. - + Socket error: %1 Erreur de socket: %1 @@ -1397,104 +1397,109 @@ Raison: %1 - + + Slovak: + + + + There is already an active session using this user name. Please close that session first and re-login. Il y a déjà une session ouvert avec le même pseudo. Fermez cette session puis re-connectez-vous. - + 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. Vous tentez de vous connecter à un serveur obsolète. Chargez la nouvelle version de Cockatrice ou connectez-vous à un serveur approprié. La version la plus récente est %1, l'ancienne version est %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Votre client Cockatrice est obsolète. Veuillez charger la nouvelle version. La version la plus récente est %1, l'ancienne version est %2. - + Connecting to %1... Connexion à %1... - + Disconnected Déconnecté - + Logged in at %1 Connecté à %1 - + &Connect... à verifier &Connecter... - + &Disconnect &Déconnecter - + Start &local game... Démarrer une partie &locale... - + &Deck editor Éditeur de &deck - + &Full screen &Plein écran - + Ctrl+F Ctrl+F - + &Settings... &Paramètres... - + &Exit &Quitter - + &Cockatrice &Cockatrice - + &About Cockatrice À propos de Cock&atrice - + &Help A&ide - + Are you sure? Êtes-vous sûr? - + There are still open games. Are you sure you want to quit? Il y a encore des parties en cours. Êtes-vous sûr de vouloir quitter? @@ -1502,103 +1507,103 @@ La version la plus récente est %1, l'ancienne version est %2. MessageLogWidget - + Connecting to %1... Connexion à %1... - + Connected. Connecté. - + Disconnected from server. Déconnecté du serveur. - + Invalid password. Mot de passe invalide. - + Protocol version mismatch. Client: %1, Server: %2 Version de protocole différente. Version locale: %1 ,version distante: %2 - + Protocol error. Erreur de protocole. - + You have joined game #%1. Vous avez rejoint la partie #%1. - + %1 has joined the game. %1 a rejoint la partie. - + %1 has left the game. %1 a quitté la partie. - + The game has been closed. La partie a été fermée. - + %1 is now watching the game. %1 est maintenant spectateur. - + %1 is not watching the game any more. %1 n'est plus spectateur. - + %1 has loaded a local deck. %1 a chargé un deck local. - + %1 has loaded deck #%2. %1 a chargé le deck #%2. - + %1 is ready to start the game. %1 est prêt à démarrer la partie. - + %1 is not ready to start the game any more. %1 n'est plus prêt à démarrer la partie. - + %1 has conceded the game. partie ou jeu %1 a concédé la partie. - + The game has started. La partie commence. - + %1 shuffles his library. %1 mélange sa bibliothèque. - + %1 rolls a %2 with a %3-sided die. is it always a dice? %1 lance un %2 à %3 faces. @@ -1612,124 +1617,124 @@ La version la plus récente est %1, l'ancienne version est %2.%1 pioche %2 cartes. - + from table depuis le champ de bataille - + from graveyard depuis son cimetière - + from exile depuis la zone exil - + from hand depuis sa main - + the bottom card of his library la carte du dessous de sa bibliothèque - + from the bottom of his library du dessous de sa bibliothèque - + the top card of his library le carte du dessus de sa bibliothèque - + from the top of his library du dessus de sa bibliothèque - + from library depuis sa bibliothèque - + from sideboard depuis sa réserve - + from the stack depuis la pile - + %1 puts %2 into play tapped%3. %1 met %2 en jeu engagé%3. - + %1 puts %2 into play%3. what is %3? plz exemple (resp. by Ranma : XX met island en jeu -depuis sa main-.) %1 met %2 en jeu %3. - + %1 puts %2%3 into graveyard. %1 met %2%3 dans son cimetière. - + %1 exiles %2%3. %1 exile %2%3. - + %1 moves %2%3 to hand. %1 met %2%3 dans sa main. - + %1 puts %2%3 into his library. %1 met %2%3 dans sa bibliothèque. - + %1 puts %2%3 on bottom of his library. %1 met %2%3 en-dessous de sa bibliothèque. - + %1 puts %2%3 on top of his library. %1 met %2%3 au-dessus de sa bibliothèque. - + %1 puts %2%3 into his library at position %4. %1 met %2%3 dans sa bibliothèque à la position n°%4. - + %1 moves %2%3 to sideboard. %1 met %2%3 à sa réserve. - + %1 plays %2%3. %1 joue %2%3. - - + + a card une carte - + %1 draws %n card(s). %1 pioche %n carte. @@ -1737,22 +1742,22 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 undoes his last draw. %1 annule sa dernière pioche. - + %1 undoes his last draw (%2). %1 annule sa dernière pioche (%2). - + %1 gives %2 control over %3. %1 donne le contrôle de %2 à %3. - + %1 takes a mulligan to %n. @@ -1760,49 +1765,49 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 draws his initial hand. - + %1 flips %2 face-down. %1 retourne %2 face cachée. - + %1 flips %2 face-up. %1 retourne %2 face visible. - + %1 destroys %2. %1 détruit %2. - + %1 attaches %2 to %3's %4. need exemple (Resp'.by Ranma: JoueurA attache Adventuring Gear sur -Plated Geopede- de -JoueurB-.) %1 attache %2 sur %4 de %3. - + %1 unattaches %2. %1 détache %2. - + %1 creates token: %2%3. %1 crée un jeton %2%3. - + %1 points from %2's %3 to %4. need exemple %1 désigne le %3 de %2 à %4. - + %1 points from %2's %3 to %4's %5. need exemple %1 désigne le %3 de %2 à %5 de %4. @@ -1824,7 +1829,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 places %n %2 counter(s) on %3 (now %4). %1 met %n %2 marqueur sur %3 (maintenant %4). @@ -1832,7 +1837,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 retire %n %2 marqueur de %3 (maintenant %4). @@ -1840,7 +1845,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + red rouge @@ -1848,7 +1853,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + yellow jaune @@ -1856,7 +1861,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + green vert @@ -1864,164 +1869,164 @@ La version la plus récente est %1, l'ancienne version est %2. - + his permanents ses permanents - + %1 %2 %3. wtf ? %1 %2 %3. - + taps engage - + untaps dégage - + %1 sets counter %2 to %3 (%4%5). need exemple %1 met les marqueurs %2 à %3 (%4%5). - + %1 sets %2 to not untap normally. need exemple %2 de %1 ne se dégagera pas lors de l'étape de dégagement. - + %1 sets %2 to untap normally. %2 de %1 se dégagera lors de l'étape de dégagement. - + %1 sets PT of %2 to %3. exemple plz %1 change la F/E de %2 à %3. - + %1 sets annotation of %2 to %3. %1 met l'annotation %3 à %2. - + %1 is looking at the top %2 cards %3. exemple plz %1 regarde les %2 cartes du dessus %3. - + %1 is looking at %2. exemple plz %1 regarde %2. - + %1 stops looking at %2. need exemple to be sure %1 arrête de regarder %2. - + %1 reveals %2 to %3. %1 révèle %2 à %3. - + %1 reveals %2. %1 révèle %2. - + %1 randomly reveals %2%3 to %4. %1 révèle au hasard %2%3 à %4. - + %1 randomly reveals %2%3. %1 révèle au hasard %2%3. - + %1 reveals %2%3 to %4. %1 révèle %2%3 à %4. - + %1 reveals %2%3. %1 révèle %2%3. - + It is now %1's turn. C'est maintenant le tour de %1. - + untap step étape de dégagement - + upkeep step étape d'entretien - + draw step étape de pioche - + first main phase première phase principale - + beginning of combat step étape de début du combat - + declare attackers step étape de déclaration des attaquants - + declare blockers step étape de déclaration des bloqueurs - + combat damage step étape de répartition et de résolution des blessures - + end of combat step étape de fin de combat - + second main phase seconde phase principale - + ending phase phase de fin de tour - + It is now the %1. need exemple C'est maintenant %1. @@ -2381,7 +2386,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + Number: Nombre: @@ -2406,28 +2411,28 @@ La version la plus récente est %1, l'ancienne version est %2.Nombre de faces: - + Set power/toughness Fixer force/endurance - + Please enter the new PT: maybe better with / Entrer la nouvelle F/E: - + Set annotation Mettre une note - + Please enter the new annotation: Entrez la nouvelle note: - + Set counters Mettre des marqueurs diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index ae2fddf75..61e5c43bc 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -1350,128 +1350,133 @@ Reason: %1 - - + + Slovak: + + + + - - - + + + + Error エラー - + Server timeout サーバータイムアウト - + Invalid login data. 無効なログインデータです. - + There is already an active session using this user name. Please close that session first and re-login. これはすでにこのユーザー名で使われているアクティブなセッションです. まずこのセッションを閉じてログインしなおしてください. - + Socket error: %1 ソケットエラー: %1 - + 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. あなたは古いVerのサーバーに接続しようとしています.CockatriceのVerをダウングレードするか適正なサーバーに接続してください. ローカルVer %1,リモートVer %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. あなたのCockatriceのVerが古いです.Cockatriceをアップデートしてください. ローカルVer %1,リモートVer %2. - + Connecting to %1... %1へ接続しています... - + Disconnected 切断されました - + Logged in at %1 %1にログイン中 - + &Connect... 接続... - + &Disconnect 切断 - + Start &local game... ローカルゲームを開始... - + &Deck editor デッキエディター - + &Full screen フルスクリーン - + Ctrl+F - + &Settings... 設定... - + &Exit 終了 - + &Cockatrice - + &About Cockatrice - + &Help ヘルプ - + Are you sure? よろしいですか? - + There are still open games. Are you sure you want to quit? ゲームがまだ開いています.本当に退出しますか? @@ -1479,210 +1484,210 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). - + %1 undoes his last draw. - + %1 undoes his last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + from the bottom of his library - + the top card of his library - + from the top of his library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 into his library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1699,274 +1704,274 @@ Local version is %1, remote version is %2. - + red - + yellow - + green - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. - + %1 takes a mulligan to %n. - + %1 draws his initial hand. - + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). - + %1 removes %n %2 counter(s) from %3 (now %4). - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 shuffles his library. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2325,7 +2330,7 @@ Local version is %1, remote version is %2. - + Number: 枚数 @@ -2350,27 +2355,27 @@ Local version is %1, remote version is %2. 面の数: - + Set power/toughness パワーとタフネスを設定する - + Please enter the new PT: 新しいP/Tを入力してください - + Set annotation 補足を付ける - + Please enter the new annotation: 新しい補足を付けてください - + Set counters カウンターを設定する diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 8f843f821..7660e1032 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -152,22 +152,42 @@ CardInfoWidget - + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + Name: - + Mana cost: - + Card type: - + P / T: @@ -553,38 +573,56 @@ + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + + + DeckListModel - + Number - + Card + + + Price + + DeckViewContainer - + Load &local deck - + Load d&eck from server - + Ready to s&tart - + Load deck @@ -890,54 +928,59 @@ DlgSettings - - - + + + Error - + Your card database is invalid. Would you like to go back and set the correct path? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User interface - + + Deck editor + + + + Messages - + &Close @@ -945,83 +988,83 @@ GameSelector - - + + Error - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + C&reate - + &Join - + J&oin as spectator @@ -1248,125 +1291,135 @@ Reason: %1 - - - - - + + Czech: + + + + + Slovak: + + + + + + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -1409,72 +1462,72 @@ Local version is %1, remote version is %2. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - + %1 shuffles his library. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1483,178 +1536,192 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes his last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + from the bottom of his library - + the top card of his library - + from the top of his library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 into his library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. + + + %1 takes a mulligan to %n. + + + + + + - + + %1 draws his initial hand. + + + + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1663,7 +1730,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -1672,7 +1739,7 @@ Local version is %1, remote version is %2. - + red @@ -1681,7 +1748,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1690,7 +1757,7 @@ Local version is %1, remote version is %2. - + green @@ -1699,157 +1766,157 @@ Local version is %1, remote version is %2. - + his permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -1857,22 +1924,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Add message - + Message: - + &Add - + &Remove @@ -1938,322 +2005,322 @@ Local version is %1, remote version is %2. Player - + &View graveyard - + &View exile - + Player "%1" - + &Graveyard - + &Exile - - - + + + Move to &top of library - - - + + + Move to &bottom of library - - + + Move to &graveyard - - + + Move to &exile - - + + Move to &hand - + &View library - + View &top cards of library... - + Reveal &library to - + Reveal t&op card to - + &View sideboard - + &Draw card - + D&raw cards... - + &Undo last draw - + Take &mulligan - + &Shuffle - + Move top cards to &graveyard... - + Move top cards to &exile... - + Put top card on &bottom - + &Hand - + &Reveal to - + Reveal r&andom card to - + &Sideboard - + &Library - + &Counters - + &Untap all permanents - + R&oll die... - + &Create token... - + C&reate another token - + S&ay - + C&ard - + &All players - + Ctrl+F3 - + F3 - + Ctrl+W - + F4 - + Ctrl+D - + Ctrl+E - + Ctrl+Shift+D - + Ctrl+M - + Ctrl+S - + Ctrl+U - + Ctrl+I - + Ctrl+T - + Ctrl+G - + View top cards of library - + Number of cards: - + Draw cards - - - - + + + + Number: - + Move top cards to grave - + Move top cards to exile - + Roll die - + Number of sides: - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -2319,17 +2386,17 @@ Local version is %1, remote version is %2. - + Cockatrice decks (*.cod) - + Plain text decks (*.dec *.mwDeck) - + All files (*.*) @@ -2506,132 +2573,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases - + &Game - + Next &phase - + Ctrl+Space - + Next &turn - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows - + Ctrl+R - + &Concede - + F2 - + &Leave game - + + Ctrl+Q + + + + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + Kicked - + You have been kicked out of the game. - + Game %1: %2 @@ -2649,22 +2721,22 @@ Please enter a name: - + This user is ignoring you. - + %1 has left the server. - + %1 has joined the server. - + Talking to %1 @@ -2672,27 +2744,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -2759,25 +2831,40 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + &Double-click cards to play them (instead of single-click) - + Animation settings - + &Tap/untap animation + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + + UserList @@ -2851,186 +2938,196 @@ Enter 0 for an indefinite ban. WndDeckEditor - + &Search... - + &Clear search - + &Search for: - + Deck &name: - + &Comments: - - Deck editor [*] + + &Update prices - - &New deck - - - - - &Load deck... - - - - - &Save deck - - - - - Save deck &as... - - - - - Load deck from cl&ipboard... - - - - - Save deck to clip&board - - - - - &Print deck... - - - - - &Close + + Ctrl+U + Deck editor [*] + + + + + &New deck + + + + + &Load deck... + + + + + &Save deck + + + + + Save deck &as... + + + + + Load deck from cl&ipboard... + + + + + Save deck to clip&board + + + + + &Print deck... + + + + + &Close + + + + Ctrl+Q - + &Edit sets... - + &Deck - + &Card database - + Add card to &maindeck - + Return - + Enter - + Add card to &sideboard - + Ctrl+Return - + Ctrl+Enter - + &Remove row - + Del - + &Increment number - + + - + &Decrement number - + - - + Are you sure? - + The decklist has been modified. Do you want to save the changes? - + Load deck - + Error - + The deck could not be saved. Please check that the directory is writable and try again. - + Save deck diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index f3efd5608..b172d9a84 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -1338,27 +1338,27 @@ Russo: - - + - - - + + + + Error Erro - + Server timeout Tempo esgotado do servidor - + Invalid login data. Informações de login inválidas. - + Socket error: %1 Erro de ligação:%1 @@ -1399,103 +1399,108 @@ Razão: %1 - + + Slovak: + + + + There is already an active session using this user name. Please close that session first and re-login. Já existe uma sessão ativa usando este nome de usuário. Por favor, feche a sessão primeiro e logue novamente. - + 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. Você está tentando conectar a um servidor obsoleto. Por favor, faça um downgrade na versão do seu Cockatrice ou conecte-se ao servidor correto. A versão local é %1 e a versão remota é %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. A versão do seu Cockatrice é obsoleta. Por favor, atualize a sua versão. A versão local é %1 e a versão remota é %2. - + Connecting to %1... Conectando a %1... - + Disconnected Desconectado - + Logged in at %1 Logado em %1 - + &Connect... &Conectar... - + &Disconnect &Desconectar - + Start &local game... Iniciar jogo &local... - + &Deck editor Editor de &decks - + &Full screen Tela &cheia - + Ctrl+F Ctrl+F - + &Settings... &Configurações... - + &Exit &Sair - + &Cockatrice &Cockatrice - + &About Cockatrice So&bre o Cockatrice - + &Help &Ajuda - + Are you sure? Você tem certeza? - + There are still open games. Are you sure you want to quit? Ainda existem jogos abertos. Você tem certeza que deseja sair? @@ -1503,52 +1508,52 @@ A versão local é %1 e a versão remota é %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado do servidor. - + Invalid password. Senha incorreta. - + Protocol error. Erro de protocolo. - + The game has been closed. O jogo foi fechado. - + %1 is now watching the game. %1 está assistindo o jogo agora. - + %1 is not watching the game any more. %1 não está mais assistindo o jogo. - + %1 is not ready to start the game any more. %1 não está mais pronto para começar o jogo. - + %1 rolls a %2 with a %3-sided die. %1 tirou um %2 com um dado de %3 lados. - + %1 draws %n card(s). %1 compra %n card. @@ -1556,158 +1561,158 @@ A versão local é %1 e a versão remota é %2. - + %1 undoes his last draw. %1 desfaz sua última compra. - + %1 undoes his last draw (%2). %1 desfaz sua última compra (%2). - + from table vindo do campo de batalha - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library o card do fundo do seu grimório - + from the bottom of his library vindo do fundo do seu grimório - + the top card of his library o card do topo do seu grimório - + from the top of his library vindo do topo do seu grimório - + from library vindo do grimório - + from sideboard vindo do sideboard - + from the stack vindo da pilha - + %1 gives %2 control over %3. %1 dá controle para %2 sobre %3. - + %1 puts %2 into play tapped%3. %1 põe %2 em jogo virado%3. - + %1 puts %2 into play%3. %1 põe %2 no campo de batalha %3. - + %1 puts %2%3 into graveyard. %1 põe %2 no cemitério%3. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2 para a mão%3. - + %1 puts %2%3 into his library. %1 põe %2 no seu grimório%3. - + %1 puts %2%3 on bottom of his library. %1 põe %2 no fundo do seu grimório%3. - + %1 puts %2%3 on top of his library. %1 põe %2 no topo do seu grimório%3. - + %1 puts %2%3 into his library at position %4. %1 põe %2 no seu grimório na posição %4%3. - + %1 moves %2%3 to sideboard. %1 move %2 para o sideboard%3. - + %1 plays %2%3. %1 põe %2 na pilha%3. - - + + a card um card - + %1 flips %2 face-down. %1 vira %2 para baixo. - + %1 flips %2 face-up. %1 vira %2 para cima. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 aponta para %5 de %4 com %3 de %2. @@ -1726,7 +1731,7 @@ A versão local é %1 e a versão remota é %2. - + red vermelho @@ -1734,7 +1739,7 @@ A versão local é %1 e a versão remota é %2. - + yellow amarelo @@ -1742,7 +1747,7 @@ A versão local é %1 e a versão remota é %2. - + green verde @@ -1750,72 +1755,72 @@ A versão local é %1 e a versão remota é %2. - + %1 sets counter %2 to %3 (%4%5). %1 altera o marcador %2 para %3 (%4%5). - + %1 sets PT of %2 to %3. %1 altera o P/R de %2 para %3. - + %1 sets annotation of %2 to %3. %1 altera a nota de %2 para%3. - + %1 is looking at the top %2 cards %3. %1 está olhando para os %2 cards do topo %3. - + The game has started. O jogo começou. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + You have joined game #%1. Você entrou no jogo nº %1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 saiu do jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck nº %2. - + %1 is ready to start the game. %1 está pronto para começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. @@ -1828,22 +1833,22 @@ A versão local é %1 e a versão remota é %2. %1 compra %2 cards. - + %1 destroys %2. %1 destrói %2. - + %1 creates token: %2%3. %1 cria a ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta para %4 com %3 de %2 . - + %1 places %n %2 counter(s) on %3 (now %4). %1 põe %n marcador %2 em %3 (agora %4). @@ -1851,7 +1856,7 @@ A versão local é %1 e a versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 tira %n marcador %2 em %3 (agora %4). @@ -1859,47 +1864,47 @@ A versão local é %1 e a versão remota é %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está olhando para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 para %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase final - + It is now %1's turn. Agora é o turno de %1. - + %1 shuffles his library. %1 embaralha o seu grimório. - + %1 takes a mulligan to %n. @@ -1907,107 +1912,107 @@ A versão local é %1 e a versão remota é %2. - + %1 draws his initial hand. - + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3. para %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 para %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step etapa de desvirar - + upkeep step etapa de manutenção - + draw step etapa de compra - + first main phase primeira fase principal - + beginning of combat step etapa de início de combate - + declare attackers step etapa de declaracão de atacantes - + declare blockers step etapa de declaração de bloqueadores - + combat damage step etapa de dano de combate - + end of combat step etapa de fim de combate - + second main phase segunda fase principal - + It is now the %1. Agora é a %1. - + taps vira - + untaps desvira - + %1 sets %2 to not untap normally. %1 define que %2 não desvira normalmente. - + %1 sets %2 to untap normally. %1 define que %2 desvira normalmente. - + his permanents as suas permanentes @@ -2366,7 +2371,7 @@ A versão local é %1 e a versão remota é %2. - + Number: Número: @@ -2391,27 +2396,27 @@ A versão local é %1 e a versão remota é %2. Número de lados: - + Set power/toughness Alterar poder/resistência - + Please enter the new PT: Por favor, entre com o novo P/R: - + Set annotation Alterar nota - + Please enter the new annotation: Por favor, entre com a nova nota: - + Set counters Alterar marcadores diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 99b8005fd..503dea8cf 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -1342,27 +1342,27 @@ Russo: - - + - - - + + + + Error Erro - + Server timeout Tempo do servidor esgotado - + Invalid login data. Informação de login incorrecta. - + Socket error: %1 Erro de ligação:%1 @@ -1403,103 +1403,108 @@ Motivo: %1 - + + Slovak: + + + + There is already an active session using this user name. Please close that session first and re-login. Já existe uma sessão activa com este nome de utilizador. Por favor termine essa sessão e volte a ligar-se. - + 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. Está a tentar ligar-se a um servidor obsoleto. Por favor faça downgrade à sua versão do Cockatrice ou ligue-se a servidor adequado. Versão local é %1, versão remota é %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. A sua versão do Cockatrice é obsoleta. Por favor actualize-a. Versão local é %1, versão remota é %2. - + Connecting to %1... Ligando a %1... - + Disconnected Desligado - + Logged in at %1 Logado em %1 - + &Connect... &Ligar... - + &Disconnect &Desligar - + Start &local game... Começar &jogo local... - + &Deck editor &Editor de decks - + &Full screen Ecrã &inteiro - + Ctrl+F Ctrl+F - + &Settings... &Configurações... - + &Exit &Sair - + &Cockatrice &Cockatrice - + &About Cockatrice S&obre o Cockatrice - + &Help &Ajuda - + Are you sure? Tens a certeza? - + There are still open games. Are you sure you want to quit? Ainda há jogos abertos. Tem a certeza que deseja sair? @@ -1507,102 +1512,102 @@ Versão local é %1, versão remota é %2. MessageLogWidget - + Connecting to %1... Ligando a %1... - + Connected. Ligado. - + Disconnected from server. Desligado do servidor. - + Invalid password. Password incorrecto. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + Protocol error. Erro de protocolo. - + You have joined game #%1. Você entrou no jogo #%1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 abandonou o jogo. - + The game has been closed. Este jogo foi encerrado. - + %1 is now watching the game. %1 está agora a ver o jogo. - + %1 is not watching the game any more. %1 já não está a ver o jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck #%2. - + %1 is ready to start the game. %1 está pronto a começar o jogo. - + %1 is not ready to start the game any more. %1 já não está pronto a começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. - + The game has started. O jogo começou. - + %1 shuffles his library. %1 baralha o grimório. - + %1 rolls a %2 with a %3-sided die. %1 obteve %2 com um dado de %3 faces. @@ -1615,117 +1620,117 @@ Versão local é %1, versão remota é %2. %1 compra %2 cartas. - + from table vindo da mesa - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library a carta do fundo do seu grimório - + from the bottom of his library do fundo do seu grimório - + the top card of his library a carta do topo do seu grimório - + from the top of his library do topo do seu grimório - + from library do grimório - + from sideboard do sideboard - + from the stack da pilha - + %1 puts %2 into play tapped%3. %1 coloca %2 em jogo virado(a)%3. - + %1 puts %2 into play%3. %1 coloca %2 em jogo %3. - + %1 puts %2%3 into graveyard. %1 coloca %2%3 no cemitério. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2%3 para a mão. - + %1 puts %2%3 into his library. %1 coloca %2%3 no seu grimório. - + %1 puts %2%3 on bottom of his library. %1 coloca %2%3 no fundo do seu grimório. - + %1 puts %2%3 on top of his library. %1 coloca %2%3 no topo do seu grimório. - + %1 puts %2%3 into his library at position %4. %1 coloca %2%3 no seu grimório na posição %4. - + %1 moves %2%3 to sideboard. %1 move %2%3 para o sideboard. - + %1 plays %2%3. %1 joga %2%3. - + %1 takes a mulligan to %n. @@ -1733,12 +1738,12 @@ Versão local é %1, versão remota é %2. - + %1 draws his initial hand. - + %1 places %n %2 counter(s) on %3 (now %4). %1 coloca %n %2 marcador em %3 (agora com %4). @@ -1746,7 +1751,7 @@ Versão local é %1, versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remove %n %2 marcador de %3 (agora com %4). @@ -1754,13 +1759,13 @@ Versão local é %1, versão remota é %2. - - + + a card uma carta - + %1 draws %n card(s). %1 compra %n carta. @@ -1768,57 +1773,57 @@ Versão local é %1, versão remota é %2. - + %1 undoes his last draw. %1 desfaz a sua última compra. - + %1 undoes his last draw (%2). %1 desfaz a sua última compra (%2). - + %1 gives %2 control over %3. %1 dá controlo sobre %3 a %2. - + %1 flips %2 face-down. %1 volta a face de %2 para baixo. - + %1 flips %2 face-up. %1 volta a face de %2 para cima. - + %1 destroys %2. %1 destrói %2. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 creates token: %2%3. %1 cria ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta de %3 de %2 para %4. - + %1 points from %2's %3 to %4's %5. %1 aponta de %3 de %2 para %5 de %4. @@ -1837,7 +1842,7 @@ Versão local é %1, versão remota é %2. - + red vermelho @@ -1845,7 +1850,7 @@ Versão local é %1, versão remota é %2. - + yellow amarelo @@ -1853,7 +1858,7 @@ Versão local é %1, versão remota é %2. - + green verde @@ -1861,157 +1866,157 @@ Versão local é %1, versão remota é %2. - + his permanents as suas permanentes - + %1 %2 %3. %1 %2 %3. - + taps vira - + untaps desvira - + %1 sets counter %2 to %3 (%4%5). %1 altera o número de marcadores %2 para %3(%4%5). - + %1 sets %2 to not untap normally. %1 define %2 para não desvirar normalmente. - + %1 sets %2 to untap normally. %1 define %2 para desvirar normalmente. - + %1 sets PT of %2 to %3. %1 define o P/R de %2 como %3. - + %1 sets annotation of %2 to %3. %1 coloca uma nota de %2 em%3. - + %1 is looking at the top %2 cards %3. %1 está a olhar para as %2 cartas do topo %3. - + %1 is looking at %2. %1 está a olhar para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + %1 randomly reveals %2%3 to %4. %1 revela aleatoreamente %2%3. a %4. - + %1 randomly reveals %2%3. %1 revela aleatoreamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + It is now %1's turn. É agora o turno de %1. - + untap step Etapa de Desvirar - + upkeep step Etapa de Manutenção - + draw step Etapa de Compra - + first main phase 1ª Fase Principal (pré-combate) - + beginning of combat step Etapa de Início de Combate - + declare attackers step Etapa de Declaração de Atacantes - + declare blockers step Etapa de Declaração de Bloqueadores - + combat damage step Etapa de Dano de Combate - + end of combat step Etapa de Fim de Combate - + second main phase 2ª Fase Principal (pós-combate) - + ending phase Fase Final - + It is now the %1. É agora a %1. @@ -2370,7 +2375,7 @@ Versão local é %1, versão remota é %2. - + Number: Número: @@ -2395,27 +2400,27 @@ Versão local é %1, versão remota é %2. Número de faces: - + Set power/toughness Definir poder/resistência - + Please enter the new PT: Por favor introduza o novo P/R: - + Set annotation Colocar nota - + Please enter the new annotation: Por favor introduza a nova nota: - + Set counters Definir marcadores diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 2bb0a7a4d..c1a992642 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -1301,128 +1301,133 @@ Reason: %1 - - + + Slovak: + + + + - - - + + + + Error Ошибка - + Server timeout Временная ошибка - + Invalid login data. Неверный логин/пароль. - + There is already an active session using this user name. Please close that session first and re-login. Пользователь с таким именем уже подключен. Пожалуйста, закройте это подключение и войдите заново. - + Socket error: %1 Ошибка сокета: %1 - + 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. Вы пытаетесь подключиться к несуществующему серверу. Пожалуйста, обновите Cockatrice или выберите другой сервер. Локальная версия %1, удаленная версия %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Ваш клиент Cockatrice устарел. Пожалуйста, обновите Cockatrice. Локальная версия %1, удаленная версия %2. - + Connecting to %1... Подключение к %1... - + Disconnected Подключение прервано - + Logged in at %1 Подключено к %1 - + &Connect... &Подключение... - + &Disconnect П&рервать подключение - + Start &local game... &Начать локальную игру... - + &Deck editor Редактор &колод - + &Full screen П&олный экран - + Ctrl+F - + &Settings... Н&астройки - + &Exit &Выход - + &Cockatrice - + &About Cockatrice О про&грамме - + &Help &Справка - + Are you sure? Вы уверены? - + There are still open games. Are you sure you want to quit? Вы подключены к игре. Выйти? @@ -1430,102 +1435,102 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... Подключение к %1... - + Connected. Подключено. - + Disconnected from server. Нет соединения с сервером. - + Invalid password. Неверный пароль. - + Protocol version mismatch. Client: %1, Server: %2 Несовпадение версий. Клиент: %1, Сервер: %2 - + Protocol error. Ошибка протокола. - + You have joined game #%1. Вы присоединились к игре #%1. - + %1 has joined the game. %1 присоединился к игре. - + %1 has left the game. %1 покиул игру. - + The game has been closed. Игра закрыта. - + %1 is now watching the game. %1 вошел как зритель. - + %1 is not watching the game any more. %1 покинул зрительскую ложу. - + %1 has loaded a local deck. %1 загрузил колоду с диска. - + %1 has loaded deck #%2. %1 загрузил колоду #%2. - + %1 is ready to start the game. %1 готов начать игру. - + %1 is not ready to start the game any more. %1 все еще не готов. - + %1 has conceded the game. %1 решил сдаться. - + The game has started. Игра началась. - + %1 shuffles his library. %1 размешивает библиотеку. - + %1 rolls a %2 with a %3-sided die. %1 выкинул %2 / %3. @@ -1538,168 +1543,168 @@ Local version is %1, remote version is %2. %1 взял %2 карт. - + %1 undoes his last draw. %1 отменил последнее взятие. - + %1 undoes his last draw (%2). %1 отменил %2 последних взятий. - + from table с поля битвы - + from graveyard из кладбища - + from exile из изгнания - + from hand из руки - + the bottom card of his library нижнюю карту своей библиотеки - + from the bottom of his library со дна своей библиотеки - + the top card of his library верхнюю карту своей библиотеки - + from the top of his library с верха своей библиотеки - + from library из библиотеки - + from sideboard из сайда - + from the stack из стека - - + + a card карту - + %1 gives %2 control over %3. %1 передает %2 контроль над %3. - + %1 puts %2 into play%3. %1 поместил %2 на поле битвы %3. - + %1 puts %2%3 into graveyard. %1 поместил %2%3 на кладбище. - + %1 exiles %2%3. %1 изгоняет %2%3. - + %1 moves %2%3 to hand. %1 поместил %2%3 в руку. - + %1 puts %2%3 into his library. %1 поместил %2%3 в свою библиотеку. - + %1 puts %2%3 on bottom of his library. %1 поместил %2%3 на дно своей библиотеки. - + %1 puts %2%3 on top of his library. %1 поместил %2%3 на верх своей библиотеки. - + %1 puts %2%3 into his library at position %4. %1 поместил %2%3 в свою библиотеку %4 сверху. - + %1 moves %2%3 to sideboard. %1 поместил %2%3 в сайд. - + %1 plays %2%3. %1 разыгрывает %2%3. - + %1 flips %2 face-down. %1 перевернул %2 лицом вниз. - + %1 flips %2 face-up. %1 перевернул %2 лицом вверх. - + %1 destroys %2. %1 уничтожил %2. - + %1 attaches %2 to %3's %4. %1 присоединил %2 к %4 игрока %3. - + %1 unattaches %2. %1 отсоединил %2. - + %1 creates token: %2%3. %1 создал фишку: %2%3. - + %1 points from %2's %3 to %4. %1 указывает с %3 контролируемого %2 на %4. - + %1 points from %2's %3 to %4's %5. %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. @@ -1720,7 +1725,7 @@ Local version is %1, remote version is %2. - + %1 draws %n card(s). %1 взял %n карту. @@ -1729,12 +1734,12 @@ Local version is %1, remote version is %2. - + %1 puts %2 into play tapped%3. %1 положил %2 повернутым на поле битвы%3. - + %1 takes a mulligan to %n. @@ -1743,12 +1748,12 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 places %n %2 counter(s) on %3 (now %4). %1 поместил %n %2 жетон на %3 (теперь %4). @@ -1757,7 +1762,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 снял %n %2 жетон с %3 (теперь %4). @@ -1766,7 +1771,7 @@ Local version is %1, remote version is %2. - + red красный @@ -1775,7 +1780,7 @@ Local version is %1, remote version is %2. - + yellow желтый @@ -1784,7 +1789,7 @@ Local version is %1, remote version is %2. - + green зеленый @@ -1793,157 +1798,157 @@ Local version is %1, remote version is %2. - + his permanents свои перманенты - + %1 %2 %3. %1 %2 %3. - + taps повернул - + untaps развернул - + %1 sets counter %2 to %3 (%4%5). %1 установил жетон %2 на %3 (%4%5). - + %1 sets %2 to not untap normally. %2 теперь не разворачивается как обычно (%1). - + %1 sets %2 to untap normally. %2 теперь разворачивается как обычно (%1). - + %1 sets PT of %2 to %3. %1 установил Силу/Защиту %2 %3. - + %1 sets annotation of %2 to %3. %1 сделал пометку на %2 "%3". - + %1 is looking at the top %2 cards %3. %1 смотрит верхние %2 карт библиотеки %3. - + %1 is looking at %2. %1 просматривает %2. - + %1 stops looking at %2. %1 закончил просматривать %2. - + %1 reveals %2 to %3. %1 показывает его %2 %3. - + %1 reveals %2. %1 открыл его %2. - + %1 randomly reveals %2%3 to %4. %1 показывает случайно выбранную%3 карту (%2) %4. - + %1 randomly reveals %2%3. %1 открывает случайно выбранную%3 карту (%2). - + %1 reveals %2%3 to %4. %1 показывает%2%3 %4. - + %1 reveals %2%3. %1 открывает%2%3. - + It is now %1's turn. Ход игрока %1. - + untap step шаг разворота - + upkeep step шаг поддержки - + draw step шаг взятия карты - + first main phase первая главная фаза - + beginning of combat step шаг начала битвы - + declare attackers step шаг назначения атакующих - + declare blockers step шаг назначения блокирующих - + combat damage step шаг нанесения повреждений - + end of combat step шаг завершения битвы - + second main phase вторая главная фаза - + ending phase заключительный шаг - + It is now the %1. Сейчас %1. @@ -2302,7 +2307,7 @@ Local version is %1, remote version is %2. - + Number: Количество: @@ -2327,27 +2332,27 @@ Local version is %1, remote version is %2. Количество граней: - + Set power/toughness Установить Силу/Защиту - + Please enter the new PT: Введите новые Силу/Защиту: - + Set annotation Пометка - + Please enter the new annotation: Введите текст: - + Set counters Установить жетоны diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts new file mode 100644 index 000000000..836c20200 --- /dev/null +++ b/cockatrice/translations/cockatrice_sk.ts @@ -0,0 +1,3161 @@ + + + + + AbstractCounter + + + &Set counter... + + + + + Ctrl+L + + + + + F11 + + + + + F12 + + + + + Set counter + + + + + New value for counter '%1': + + + + + AppearanceSettingsPage + + + Zone background pictures + + + + + Path to hand background: + + + + + Path to stack background: + + + + + Path to table background: + + + + + Path to player info background: + + + + + Path to picture of card back: + + + + + Card rendering + + + + + Display card names on cards having a picture + + + + + Hand layout + + + + + Display hand horizontally (wastes space) + + + + + Table grid layout + + + + + Invert vertical coordinate + + + + + Zone view layout + + + + + Sort by name + + + + + Sort by type + + + + + + + + + Choose path + + + + + CardDatabaseModel + + + Name + + + + + Sets + + + + + Mana cost + + + + + Card type + + + + + P/T + + + + + CardInfoWidget + + + Hide card info + + + + + Show card only + + + + + Show text only + + + + + Show full info + + + + + Name: + + + + + Mana cost: + + + + + Card type: + + + + + P / T: + + + + + CardItem + + + &Play + + + + + &Hide + + + + + &Tap + + + + + &Untap + + + + + Toggle &normal untapping + + + + + &Flip + + + + + &Clone + + + + + Ctrl+H + + + + + &Attach to card... + + + + + Ctrl+A + + + + + Unattac&h + + + + + &Power / toughness + + + + + &Increase power + + + + + Ctrl++ + + + + + &Decrease power + + + + + Ctrl+- + + + + + I&ncrease toughness + + + + + Alt++ + + + + + D&ecrease toughness + + + + + Alt+- + + + + + In&crease power and toughness + + + + + Ctrl+Alt++ + + + + + Dec&rease power and toughness + + + + + Ctrl+Alt+- + + + + + Set &power and toughness... + + + + + Ctrl+P + + + + + &Set annotation... + + + + + red + + + + + yellow + + + + + green + + + + + &Add counter (%1) + + + + + &Remove counter (%1) + + + + + &Set counters (%1)... + + + + + &top of library + + + + + &bottom of library + + + + + &graveyard + + + + + Ctrl+Del + + + + + &exile + + + + + &Move to + + + + + CardZone + + + his hand + nominative + + + + + %1's hand + nominative + + + + + of his hand + genitive + + + + + of %1's hand + genitive + + + + + his hand + accusative + + + + + %1's hand + accusative + + + + + his library + nominative + + + + + %1's library + nominative + + + + + of his library + genitive + + + + + of %1's library + genitive + + + + + his library + accusative + + + + + %1's library + accusative + + + + + his graveyard + nominative + + + + + %1's graveyard + nominative + + + + + of his graveyard + genitive + + + + + of %1's graveyard + genitive + + + + + his graveyard + accusative + + + + + %1's graveyard + accusative + + + + + his exile + nominative + + + + + %1's exile + nominative + + + + + of his exile + genitive + + + + + of %1's exile + genitive + + + + + his exile + accusative + + + + + %1's exile + accusative + + + + + his sideboard + nominative + + + + + %1's sideboard + nominative + + + + + of his sideboard + genitive + + + + + of %1's sideboard + genitive + + + + + his sideboard + accusative + + + + + %1's sideboard + accusative + + + + + DeckEditorSettingsPage + + + Enable &price tag feature (using data from blacklotusproject.com) + + + + + General + + + + + DeckListModel + + + Number + + + + + Card + + + + + Price + + + + + DeckViewContainer + + + Load &local deck + + + + + Load d&eck from server + + + + + Ready to s&tart + + + + + Load deck + + + + + DlgCardSearch + + + Card name: + + + + + Card text: + + + + + Card type (OR): + + + + + Color (OR): + + + + + O&K + + + + + &Cancel + + + + + Card search + + + + + DlgConnect + + + &Host: + + + + + &Port: + + + + + Player &name: + + + + + P&assword: + + + + + &OK + + + + + &Cancel + + + + + Connect to server + + + + + DlgCreateGame + + + &Description: + + + + + P&layers: + + + + + Game type + + + + + &Password: + + + + + Only &buddies can join + + + + + Only &registered users can join + + + + + Joining restrictions + + + + + &Spectators allowed + + + + + Spectators &need a password to join + + + + + Spectators can &chat + + + + + Spectators see &everything + + + + + Spectators + + + + + &OK + + + + + &Cancel + + + + + Create game + + + + + Error + + + + + Server error. + + + + + DlgCreateToken + + + &Name: + + + + + Token + + + + + C&olor: + + + + + white + + + + + blue + + + + + black + + + + + red + + + + + green + + + + + multicolor + + + + + colorless + + + + + &P/T: + + + + + &Annotation: + + + + + &Destroy token when it leaves the table + + + + + &OK + + + + + &Cancel + + + + + Create token + + + + + DlgLoadDeckFromClipboard + + + &Refresh + + + + + &OK + + + + + &Cancel + + + + + Load deck from clipboard + + + + + Error + + + + + Invalid deck list. + + + + + DlgLoadRemoteDeck + + + O&K + + + + + &Cancel + + + + + Load deck + + + + + DlgSettings + + + + + Error + + + + + Your card database is invalid. Would you like to go back and set the correct path? + + + + + The path to your deck directory is invalid. Would you like to go back and set the correct path? + + + + + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? + + + + + Settings + + + + + General + + + + + Appearance + + + + + User interface + + + + + Deck editor + + + + + Messages + + + + + &Close + + + + + GameSelector + + + + + + + + + Error + + + + + Wrong password. + + + + + Spectators are not allowed in this game. + + + + + The game is already full. + + + + + The game does not exist any more. + + + + + This game is only open to registered users. + + + + + This game is only open to its creator's buddies. + + + + + You are being ignored by the creator of this game. + + + + + Join game + + + + + Password: + + + + + Games + + + + + Show &full games + + + + + C&reate + + + + + &Join + + + + + J&oin as spectator + + + + + GameView + + + Esc + + + + + GamesModel + + + yes + + + + + yes, free for spectators + + + + + no + + + + + buddies only + + + + + reg. users only + + + + + not allowed + + + + + Description + + + + + Creator + + + + + Game type + + + + + Password + + + + + Restrictions + + + + + Players + + + + + Spectators + + + + + GeneralSettingsPage + + + + English + + + + + + + Choose path + + + + + Personal settings + + + + + Language: + + + + + Download card pictures on the fly + + + + + Paths + + + + + Decks directory: + + + + + Pictures directory: + + + + + Path to card database: + + + + + MainWindow + + + There are too many concurrent connections from your address. + + + + + Banned by moderator. + + + + + Unknown reason. + + + + + Connection closed + + + + + The server has terminated your connection. +Reason: %1 + + + + + Number of players + + + + + Please enter the number of players. + + + + + + Player %1 + + + + + About Cockatrice + + + + + Version %1 + + + + + Authors: + + + + + Translators: + + + + + Spanish: + + + + + Portugese (Portugal): + + + + + Portugese (Brazil): + + + + + French: + + + + + Japanese: + + + + + Russian: + + + + + Czech: + + + + + Slovak: + + + + + + + + + + Error + + + + + Server timeout + + + + + Invalid login data. + + + + + There is already an active session using this user name. +Please close that session first and re-login. + + + + + Socket error: %1 + + + + + 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. + + + + + Your Cockatrice client is obsolete. Please update your Cockatrice version. +Local version is %1, remote version is %2. + + + + + Connecting to %1... + + + + + Disconnected + + + + + Logged in at %1 + + + + + &Connect... + + + + + &Disconnect + + + + + Start &local game... + + + + + &Deck editor + + + + + &Full screen + + + + + Ctrl+F + + + + + &Settings... + + + + + &Exit + + + + + &Cockatrice + + + + + &About Cockatrice + + + + + &Help + + + + + Are you sure? + + + + + There are still open games. Are you sure you want to quit? + + + + + MessageLogWidget + + + Connecting to %1... + + + + + Connected. + + + + + Disconnected from server. + + + + + Invalid password. + + + + + Protocol version mismatch. Client: %1, Server: %2 + + + + + Protocol error. + + + + + You have joined game #%1. + + + + + %1 has joined the game. + + + + + %1 has left the game. + + + + + The game has been closed. + + + + + %1 is now watching the game. + + + + + %1 is not watching the game any more. + + + + + %1 has loaded a local deck. + + + + + %1 has loaded deck #%2. + + + + + %1 is ready to start the game. + + + + + %1 is not ready to start the game any more. + + + + + %1 has conceded the game. + + + + + The game has started. + + + + + %1 shuffles his library. + + + + + %1 rolls a %2 with a %3-sided die. + + + + + %1 draws %n card(s). + + + + + + + + + %1 undoes his last draw. + + + + + %1 undoes his last draw (%2). + + + + + from table + + + + + from graveyard + + + + + from exile + + + + + from hand + + + + + the bottom card of his library + + + + + from the bottom of his library + + + + + the top card of his library + + + + + from the top of his library + + + + + from library + + + + + from sideboard + + + + + from the stack + + + + + + a card + + + + + %1 gives %2 control over %3. + + + + + %1 puts %2 into play tapped%3. + + + + + %1 puts %2 into play%3. + + + + + %1 puts %2%3 into graveyard. + + + + + %1 exiles %2%3. + + + + + %1 moves %2%3 to hand. + + + + + %1 puts %2%3 into his library. + + + + + %1 puts %2%3 on bottom of his library. + + + + + %1 puts %2%3 on top of his library. + + + + + %1 puts %2%3 into his library at position %4. + + + + + %1 moves %2%3 to sideboard. + + + + + %1 plays %2%3. + + + + + %1 takes a mulligan to %n. + + + + + + + + + %1 draws his initial hand. + + + + + %1 flips %2 face-down. + + + + + %1 flips %2 face-up. + + + + + %1 destroys %2. + + + + + %1 attaches %2 to %3's %4. + + + + + %1 unattaches %2. + + + + + %1 creates token: %2%3. + + + + + %1 points from %2's %3 to %4. + + + + + %1 points from %2's %3 to %4's %5. + + + + + %1 places %n %2 counter(s) on %3 (now %4). + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + + + + + + + + + red + + + + + + + + + yellow + + + + + + + + + green + + + + + + + + + his permanents + + + + + %1 %2 %3. + + + + + taps + + + + + untaps + + + + + %1 sets counter %2 to %3 (%4%5). + + + + + %1 sets %2 to not untap normally. + + + + + %1 sets %2 to untap normally. + + + + + %1 sets PT of %2 to %3. + + + + + %1 sets annotation of %2 to %3. + + + + + %1 is looking at the top %2 cards %3. + + + + + %1 is looking at %2. + + + + + %1 stops looking at %2. + + + + + %1 reveals %2 to %3. + + + + + %1 reveals %2. + + + + + %1 randomly reveals %2%3 to %4. + + + + + %1 randomly reveals %2%3. + + + + + %1 reveals %2%3 to %4. + + + + + %1 reveals %2%3. + + + + + It is now %1's turn. + + + + + untap step + + + + + upkeep step + + + + + draw step + + + + + first main phase + + + + + beginning of combat step + + + + + declare attackers step + + + + + declare blockers step + + + + + combat damage step + + + + + end of combat step + + + + + second main phase + + + + + ending phase + + + + + It is now the %1. + + + + + MessagesSettingsPage + + + Add message + + + + + Message: + + + + + &Add + + + + + &Remove + + + + + PhasesToolbar + + + Untap step + + + + + Upkeep step + + + + + Draw step + + + + + First main phase + + + + + Beginning of combat step + + + + + Declare attackers step + + + + + Declare blockers step + + + + + Combat damage step + + + + + End of combat step + + + + + Second main phase + + + + + End of turn step + + + + + Player + + + &View graveyard + + + + + &View exile + + + + + Player "%1" + + + + + &Graveyard + + + + + &Exile + + + + + + + Move to &top of library + + + + + + + Move to &bottom of library + + + + + + Move to &graveyard + + + + + + Move to &exile + + + + + + Move to &hand + + + + + &View library + + + + + View &top cards of library... + + + + + Reveal &library to + + + + + Reveal t&op card to + + + + + &View sideboard + + + + + &Draw card + + + + + D&raw cards... + + + + + &Undo last draw + + + + + Take &mulligan + + + + + &Shuffle + + + + + Move top cards to &graveyard... + + + + + Move top cards to &exile... + + + + + Put top card on &bottom + + + + + &Hand + + + + + &Reveal to + + + + + Reveal r&andom card to + + + + + &Sideboard + + + + + &Library + + + + + &Counters + + + + + &Untap all permanents + + + + + R&oll die... + + + + + &Create token... + + + + + C&reate another token + + + + + S&ay + + + + + C&ard + + + + + &All players + + + + + Ctrl+F3 + + + + + F3 + + + + + Ctrl+W + + + + + F4 + + + + + Ctrl+D + + + + + Ctrl+E + + + + + Ctrl+Shift+D + + + + + Ctrl+M + + + + + Ctrl+S + + + + + Ctrl+U + + + + + Ctrl+I + + + + + Ctrl+T + + + + + Ctrl+G + + + + + View top cards of library + + + + + Number of cards: + + + + + Draw cards + + + + + + + + Number: + + + + + Move top cards to grave + + + + + Move top cards to exile + + + + + Roll die + + + + + Number of sides: + + + + + Set power/toughness + + + + + Please enter the new PT: + + + + + Set annotation + + + + + Please enter the new annotation: + + + + + Set counters + + + + + PlayerListWidget + + + local deck + + + + + deck #%1 + + + + + User &details + + + + + Direct &chat + + + + + Add to &buddy list + + + + + Remove from &buddy list + + + + + Add to &ignore list + + + + + Remove from &ignore list + + + + + Kick from &game + + + + + QObject + + + Maindeck + + + + + Sideboard + + + + + Cockatrice decks (*.cod) + + + + + Plain text decks (*.dec *.mwDeck) + + + + + All files (*.*) + + + + + RemoteDeckList_TreeModel + + + Name + + + + + ID + + + + + Upload time + + + + + RoomSelector + + + Rooms + + + + + Joi&n + + + + + Room + + + + + Description + + + + + Players + + + + + Games + + + + + SetsModel + + + Short name + + + + + Long name + + + + + TabAdmin + + + Update server &message + + + + + Server administration functions + + + + + &Unlock functions + + + + + &Lock functions + + + + + Unlock administration functions + + + + + Do you really want to unlock the administration functions? + + + + + Administration + + + + + TabDeckStorage + + + Local file system + + + + + Server deck storage + + + + + + Open in deck editor + + + + + Upload deck + + + + + Download deck + + + + + + New folder + + + + + Delete + + + + + Enter deck name + + + + + This decklist does not have a name. +Please enter a name: + + + + + + Unnamed deck + + + + + Name of new folder: + + + + + Deck storage + + + + + TabGame + + + F5 + + + + + F6 + + + + + F7 + + + + + F8 + + + + + F9 + + + + + F10 + + + + + &Phases + + + + + &Game + + + + + Next &phase + + + + + Ctrl+Space + + + + + Next &turn + + + + + Ctrl+Return + + + + + Ctrl+Enter + + + + + &Remove all local arrows + + + + + Ctrl+R + + + + + &Concede + + + + + F2 + + + + + &Leave game + + + + + Ctrl+Q + + + + + &Say: + + + + + Concede + + + + + Are you sure you want to concede this game? + + + + + Leave game + + + + + Are you sure you want to leave this game? + + + + + Kicked + + + + + You have been kicked out of the game. + + + + + Game %1: %2 + + + + + TabMessage + + + Personal &talk + + + + + &Leave + + + + + This user is ignoring you. + + + + + %1 has left the server. + + + + + %1 has joined the server. + + + + + Talking to %1 + + + + + TabRoom + + + &Say: + + + + + Chat + + + + + &Room + + + + + &Leave room + + + + + You are flooding the chat. Please wait a couple of seconds. + + + + + TabServer + + + Server + + + + + TabUserLists + + + User lists + + + + + UserInfoBox + + + User information + + + + + Real name: + + + + + Location: + + + + + User level: + + + + + Administrator + + + + + Judge + + + + + Registered user + + + + + Unregistered user + + + + + UserInterfaceSettingsPage + + + General interface settings + + + + + &Double-click cards to play them (instead of single-click) + + + + + Animation settings + + + + + &Tap/untap animation + + + + + Enable &sounds + + + + + Path to sounds directory: + + + + + Choose path + + + + + UserList + + + Users online: %1 + + + + + Users in this room: %1 + + + + + Buddies online: %1 / %2 + + + + + Ignored users online: %1 / %2 + + + + + User &details + + + + + Direct &chat + + + + + Add to &buddy list + + + + + Remove from &buddy list + + + + + Add to &ignore list + + + + + Remove from &ignore list + + + + + Ban from &server + + + + + Duration + + + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + + + + + WndDeckEditor + + + &Search... + + + + + &Clear search + + + + + &Search for: + + + + + Deck &name: + + + + + &Comments: + + + + + &Update prices + + + + + Ctrl+U + + + + + Deck editor [*] + + + + + &New deck + + + + + &Load deck... + + + + + &Save deck + + + + + Save deck &as... + + + + + Load deck from cl&ipboard... + + + + + Save deck to clip&board + + + + + &Print deck... + + + + + &Close + + + + + Ctrl+Q + + + + + &Edit sets... + + + + + &Deck + + + + + &Card database + + + + + Add card to &maindeck + + + + + Return + + + + + Enter + + + + + Add card to &sideboard + + + + + Ctrl+Return + + + + + Ctrl+Enter + + + + + &Remove row + + + + + Del + + + + + &Increment number + + + + + + + + + + + &Decrement number + + + + + - + + + + + Are you sure? + + + + + The decklist has been modified. +Do you want to save the changes? + + + + + Load deck + + + + + + Error + + + + + + The deck could not be saved. +Please check that the directory is writable and try again. + + + + + Save deck + + + + + WndSets + + + Edit sets + + + + + ZoneViewWidget + + + sort by name + + + + + sort by type + + + + + shuffle when closing + + + + From 8d659b6c39298650cf7cdd55812ea179fd5ed939 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 18 Jun 2011 12:50:08 +0200 Subject: [PATCH 53/87] renamed file --- .../{cockatrice_cz.ts => cockatrice_cs.ts} | 293 ++++++++++-------- 1 file changed, 156 insertions(+), 137 deletions(-) rename cockatrice/translations/{cockatrice_cz.ts => cockatrice_cs.ts} (97%) diff --git a/cockatrice/translations/cockatrice_cz.ts b/cockatrice/translations/cockatrice_cs.ts similarity index 97% rename from cockatrice/translations/cockatrice_cz.ts rename to cockatrice/translations/cockatrice_cs.ts index f3731f0cf..d2acd311a 100644 --- a/cockatrice/translations/cockatrice_cz.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -1296,125 +1296,130 @@ Reason: %1 - - + + Slovak: + + + + - - - + + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -1422,482 +1427,496 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Connected. - + Disconnected from server. - + Invalid password. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - + %1 shuffles his library. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). + + - + %1 undoes his last draw. - + %1 undoes his last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + from the bottom of his library - + the top card of his library - + from the top of his library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 into his library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. + + - + %1 draws his initial hand. - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). + + - + %1 removes %n %2 counter(s) from %3 (now %4). - - - - - red - - - - - - yellow - + red + + + + + + + + + yellow + + + + + + + + green + + - + his permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2256,7 +2275,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2281,27 +2300,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters From 8971a10c80bf4bd749fb08d44ebc593b19c32633 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 18 Jun 2011 13:28:55 +0200 Subject: [PATCH 54/87] added mtg:commander to sets --- oracle/sets.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/oracle/sets.xml b/oracle/sets.xml index 8ebabb9ba..8e7dfda71 100644 --- a/oracle/sets.xml +++ b/oracle/sets.xml @@ -172,6 +172,10 @@ M11 Magic 2011
+ + COM + Magic: The Gathering-Commander + MM Mercadian Masques From 4777d18fe316e53bce40ad5c1b943a072dffdb02 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 22 Jun 2011 16:06:01 +0200 Subject: [PATCH 55/87] added error messages to oracle importer --- oracle/src/oracleimporter.cpp | 20 ++++++++++++-------- oracle/src/oracleimporter.h | 6 +++--- oracle/src/window_main.cpp | 22 ++++++++++++++++++---- oracle/src/window_main.h | 1 + 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 5aa2b99fc..add5e538b 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -15,27 +15,27 @@ OracleImporter::OracleImporter(const QString &_dataDir, QObject *parent) connect(http, SIGNAL(dataReadProgress(int, int)), this, SIGNAL(dataReadProgress(int, int))); } -void OracleImporter::readSetsFromFile(const QString &fileName) +bool OracleImporter::readSetsFromFile(const QString &fileName) { QFile setsFile(fileName); if (!setsFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::critical(0, tr("Error"), tr("Cannot open file '%1'.").arg(fileName)); - return; + return false; } QXmlStreamReader xml(&setsFile); - readSetsFromXml(xml); + return readSetsFromXml(xml); } -void OracleImporter::readSetsFromByteArray(const QByteArray &data) +bool OracleImporter::readSetsFromByteArray(const QByteArray &data) { QXmlStreamReader xml(data); - readSetsFromXml(xml); + return readSetsFromXml(xml); } -void OracleImporter::readSetsFromXml(QXmlStreamReader &xml) +bool OracleImporter::readSetsFromXml(QXmlStreamReader &xml) { - allSets.clear(); + QList newSetList; QString edition; QString editionLong; @@ -56,7 +56,7 @@ void OracleImporter::readSetsFromXml(QXmlStreamReader &xml) else if (xml.name() == "url") editionURL = xml.readElementText(); } - allSets << SetToDownload(edition, editionLong, editionURL, import); + newSetList.append(SetToDownload(edition, editionLong, editionURL, import)); edition = editionLong = editionURL = QString(); } else if (xml.name() == "picture_url") pictureUrl = xml.readElementText(); @@ -67,6 +67,10 @@ void OracleImporter::readSetsFromXml(QXmlStreamReader &xml) else if (xml.name() == "set_url") setUrl = xml.readElementText(); } + if (newSetList.isEmpty()) + return false; + allSets = newSetList; + return true; } CardInfo *OracleImporter::addCard(const QString &setName, QString cardName, int cardId, const QString &cardCost, const QString &cardType, const QString &cardPT, const QStringList &cardText) diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index afee515fa..3f6e4899f 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -34,7 +34,7 @@ private: QString getPictureUrl(QString url, int cardId, QString name, const QString &setName) const; void downloadNextFile(); - void readSetsFromXml(QXmlStreamReader &xml); + bool readSetsFromXml(QXmlStreamReader &xml); CardInfo *addCard(const QString &setName, QString cardName, int cardId, const QString &cardCost, const QString &cardType, const QString &cardPT, const QStringList &cardText); private slots: void httpRequestFinished(int requestId, bool error); @@ -44,8 +44,8 @@ signals: void dataReadProgress(int bytesRead, int totalBytes); public: OracleImporter(const QString &_dataDir, QObject *parent = 0); - void readSetsFromByteArray(const QByteArray &data); - void readSetsFromFile(const QString &fileName); + bool readSetsFromByteArray(const QByteArray &data); + bool readSetsFromFile(const QString &fileName); int startDownload(); int importTextSpoiler(CardSet *set, const QByteArray &data); QList &getSets() { return allSets; } diff --git a/oracle/src/window_main.cpp b/oracle/src/window_main.cpp index 8f8f9aef4..9cf164e8d 100644 --- a/oracle/src/window_main.cpp +++ b/oracle/src/window_main.cpp @@ -94,6 +94,10 @@ WindowMain::WindowMain(QWidget *parent) QStringList args = qApp->arguments(); if (args.contains("-dlsets")) downloadSetsFile(defaultSetsUrl); + + statusLabel = new QLabel; + statusBar()->addWidget(statusLabel); + statusLabel->setText(tr("Sets data not loaded.")); } void WindowMain::updateSetList() @@ -110,6 +114,7 @@ void WindowMain::updateSetList() checkBoxLayout->addWidget(checkBox); checkBoxList << checkBox; } + statusLabel->setText(tr("Ready.")); } void WindowMain::actLoadSetsFile() @@ -121,8 +126,10 @@ void WindowMain::actLoadSetsFile() return; QString fileName = dialog.selectedFiles().at(0); - importer->readSetsFromFile(fileName); - updateSetList(); + if (importer->readSetsFromFile(fileName)) + updateSetList(); + else + QMessageBox::critical(this, tr("Error"), tr("This file does not contain any sets data.")); } void WindowMain::actDownloadSetsFile() @@ -141,9 +148,15 @@ void WindowMain::downloadSetsFile(const QString &url) void WindowMain::setsDownloadFinished() { QNetworkReply *reply = static_cast(sender()); - importer->readSetsFromByteArray(reply->readAll()); + QNetworkReply::NetworkError errorCode = reply->error(); + if (errorCode == QNetworkReply::NoError) { + if (importer->readSetsFromByteArray(reply->readAll())) + updateSetList(); + else + QMessageBox::critical(this, tr("Error"), tr("The file was retrieved successfully, but it does not contain any sets data.")); + } else + QMessageBox::critical(this, tr("Error"), tr("Network error: %1.").arg(reply->errorString())); reply->deleteLater(); - updateSetList(); } void WindowMain::updateTotalProgress(int cardsImported, int setIndex, const QString &nextSetName) @@ -205,6 +218,7 @@ void WindowMain::actStart() checkBoxList[i]->setEnabled(false); startButton->setEnabled(false); totalProgressBar->setMaximum(setsCount); + statusLabel->setText(tr("Downloading card data...")); } void WindowMain::checkBoxChanged(int state) diff --git a/oracle/src/window_main.h b/oracle/src/window_main.h index afcf897db..1fdba235b 100644 --- a/oracle/src/window_main.h +++ b/oracle/src/window_main.h @@ -31,6 +31,7 @@ private: QTextEdit *messageLog; QVBoxLayout *checkBoxLayout; QList checkBoxList; + QLabel *statusLabel; void downloadSetsFile(const QString &url); private slots: From b7ab2d97bd48b36298b2fdd6cc58888084fc98b0 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 22 Jun 2011 17:39:25 +0200 Subject: [PATCH 56/87] support for women --- cockatrice/cockatrice.qrc | 6 +- cockatrice/resources/genders/female.svg | 33 + cockatrice/resources/genders/male.svg | 12 + cockatrice/resources/genders/unknown.svg | 10 + .../userlevels/{judge.svg => moderator.svg} | 0 cockatrice/src/cardzone.cpp | 31 +- cockatrice/src/messagelogwidget.cpp | 35 +- cockatrice/src/messagelogwidget.h | 3 +- cockatrice/src/pixmapgenerator.cpp | 34 +- cockatrice/src/pixmapgenerator.h | 8 + cockatrice/src/player.cpp | 2 +- cockatrice/src/player.h | 2 +- cockatrice/src/userinfobox.cpp | 20 +- cockatrice/src/userinfobox.h | 2 +- cockatrice/translations/cockatrice_cs.ts | 579 +++++++++---- cockatrice/translations/cockatrice_de.ts | 737 +++++++++++++---- cockatrice/translations/cockatrice_en.ts | 583 +++++++++---- cockatrice/translations/cockatrice_es.ts | 737 +++++++++++++---- cockatrice/translations/cockatrice_fr.ts | 763 +++++++++++++----- cockatrice/translations/cockatrice_ja.ts | 633 ++++++++++----- cockatrice/translations/cockatrice_pl.ts | 579 +++++++++---- cockatrice/translations/cockatrice_pt-br.ts | 759 +++++++++++++---- cockatrice/translations/cockatrice_pt.ts | 761 +++++++++++++---- cockatrice/translations/cockatrice_ru.ts | 761 +++++++++++++---- cockatrice/translations/cockatrice_sk.ts | 579 +++++++++---- common/protocol_datastructures.cpp | 4 +- common/protocol_datastructures.h | 10 +- servatrice/servatrice.sql | 1 + servatrice/src/servatrice.cpp | 24 +- 29 files changed, 5743 insertions(+), 1965 deletions(-) create mode 100644 cockatrice/resources/genders/female.svg create mode 100644 cockatrice/resources/genders/male.svg create mode 100644 cockatrice/resources/genders/unknown.svg rename cockatrice/resources/userlevels/{judge.svg => moderator.svg} (100%) diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index abeeeeab2..563ee21d2 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -38,6 +38,10 @@ resources/icon_player.svg resources/icon_spectator.svg + resources/genders/male.svg + resources/genders/female.svg + resources/genders/unknown.svg + translations/cockatrice_de.qm translations/cockatrice_en.qm translations/cockatrice_es.qm @@ -103,7 +107,7 @@ resources/userlevels/normal.svg resources/userlevels/registered.svg - resources/userlevels/judge.svg + resources/userlevels/moderator.svg resources/userlevels/admin.svg resources/news/exclamation_mark.svg diff --git a/cockatrice/resources/genders/female.svg b/cockatrice/resources/genders/female.svg new file mode 100644 index 000000000..b0fbb1306 --- /dev/null +++ b/cockatrice/resources/genders/female.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/cockatrice/resources/genders/male.svg b/cockatrice/resources/genders/male.svg new file mode 100644 index 000000000..8c58a40fc --- /dev/null +++ b/cockatrice/resources/genders/male.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/cockatrice/resources/genders/unknown.svg b/cockatrice/resources/genders/unknown.svg new file mode 100644 index 000000000..99f681f9c --- /dev/null +++ b/cockatrice/resources/genders/unknown.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/cockatrice/resources/userlevels/judge.svg b/cockatrice/resources/userlevels/moderator.svg similarity index 100% rename from cockatrice/resources/userlevels/judge.svg rename to cockatrice/resources/userlevels/moderator.svg diff --git a/cockatrice/src/cardzone.cpp b/cockatrice/src/cardzone.cpp index 3c3606ee2..ceaf08523 100644 --- a/cockatrice/src/cardzone.cpp +++ b/cockatrice/src/cardzone.cpp @@ -46,35 +46,36 @@ void CardZone::clearContents() QString CardZone::getTranslatedName(bool hisOwn, GrammaticalCase gc) const { QString ownerName = player->getName(); + bool female = player->getUserInfo()->getGender() == ServerInfo_User::Female; if (name == "hand") switch (gc) { - case CaseNominative: return hisOwn ? tr("his hand", "nominative") : tr("%1's hand", "nominative").arg(ownerName); - case CaseGenitive: return hisOwn ? tr("of his hand", "genitive") : tr("of %1's hand", "genitive").arg(ownerName); - case CaseAccusative: return hisOwn ? tr("his hand", "accusative") : tr("%1's hand", "accusative").arg(ownerName); + case CaseNominative: return female ? (hisOwn ? tr("her hand", "nominative, female owner") : tr("%1's hand", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his hand", "nominative, male owner") : tr("%1's hand", "nominative, male owner").arg(ownerName)); + case CaseGenitive: return female ? (hisOwn ? tr("of her hand", "genitive, female owner") : tr("of %1's hand", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his hand", "genitive, male owner") : tr("of %1's hand", "genitive, male owner").arg(ownerName)); + case CaseAccusative: return female ? (hisOwn ? tr("her hand", "accusative, female owner") : tr("%1's hand", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his hand", "accusative, male owner") : tr("%1's hand", "accusative, male owner").arg(ownerName)); } else if (name == "deck") switch (gc) { - case CaseNominative: return hisOwn ? tr("his library", "nominative") : tr("%1's library", "nominative").arg(ownerName); - case CaseGenitive: return hisOwn ? tr("of his library", "genitive") : tr("of %1's library", "genitive").arg(ownerName); - case CaseAccusative: return hisOwn ? tr("his library", "accusative") : tr("%1's library", "accusative").arg(ownerName); + case CaseNominative: return female ? (hisOwn ? tr("her library", "nominative, female owner") : tr("%1's library", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his library", "nominative, male owner") : tr("%1's library", "nominative, male owner").arg(ownerName)); + case CaseGenitive: return female ? (hisOwn ? tr("of her library", "genitive, female owner") : tr("of %1's library", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his library", "genitive, male owner") : tr("of %1's library", "genitive, male owner").arg(ownerName)); + case CaseAccusative: return female ? (hisOwn ? tr("her library", "accusative, female owner") : tr("%1's library", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his library", "accusative, male owner") : tr("%1's library", "accusative, male owner").arg(ownerName)); } else if (name == "grave") switch (gc) { - case CaseNominative: return hisOwn ? tr("his graveyard", "nominative") : tr("%1's graveyard", "nominative").arg(ownerName); - case CaseGenitive: return hisOwn ? tr("of his graveyard", "genitive") : tr("of %1's graveyard", "genitive").arg(ownerName); - case CaseAccusative: return hisOwn ? tr("his graveyard", "accusative") : tr("%1's graveyard", "accusative").arg(ownerName); + case CaseNominative: return female ? (hisOwn ? tr("her graveyard", "nominative, female owner") : tr("%1's graveyard", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his graveyard", "nominative, male owner") : tr("%1's graveyard", "nominative, male owner").arg(ownerName)); + case CaseGenitive: return female ? (hisOwn ? tr("of her graveyard", "genitive, female owner") : tr("of %1's graveyard", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his graveyard", "genitive, male owner") : tr("of %1's graveyard", "genitive, male owner").arg(ownerName)); + case CaseAccusative: return female ? (hisOwn ? tr("her graveyard", "accusative, female owner") : tr("%1's graveyard", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his graveyard", "accusative, male owner") : tr("%1's graveyard", "accusative, male owner").arg(ownerName)); } else if (name == "rfg") switch (gc) { - case CaseNominative: return hisOwn ? tr("his exile", "nominative") : tr("%1's exile", "nominative").arg(ownerName); - case CaseGenitive: return hisOwn ? tr("of his exile", "genitive") : tr("of %1's exile", "genitive").arg(ownerName); - case CaseAccusative: return hisOwn ? tr("his exile", "accusative") : tr("%1's exile", "accusative").arg(ownerName); + case CaseNominative: return female ? (hisOwn ? tr("her exile", "nominative, female owner") : tr("%1's exile", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his exile", "nominative, male owner") : tr("%1's exile", "nominative, male owner").arg(ownerName)); + case CaseGenitive: return female ? (hisOwn ? tr("of her exile", "genitive, female owner") : tr("of %1's exile", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his exile", "genitive, male owner") : tr("of %1's exile", "genitive, male owner").arg(ownerName)); + case CaseAccusative: return female ? (hisOwn ? tr("her exile", "accusative, female owner") : tr("%1's exile", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his exile", "accusative, male owner") : tr("%1's exile", "accusative, male owner").arg(ownerName)); } else if (name == "sb") switch (gc) { - case CaseNominative: return hisOwn ? tr("his sideboard", "nominative") : tr("%1's sideboard", "nominative").arg(ownerName); - case CaseGenitive: return hisOwn ? tr("of his sideboard", "genitive") : tr("of %1's sideboard", "genitive").arg(ownerName); - case CaseAccusative: return hisOwn ? tr("his sideboard", "accusative") : tr("%1's sideboard", "accusative").arg(ownerName); + case CaseNominative: return female ? (hisOwn ? tr("her sideboard", "nominative, female owner") : tr("%1's sideboard", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his sideboard", "nominative, male owner") : tr("%1's sideboard", "nominative, male owner").arg(ownerName)); + case CaseGenitive: return female ? (hisOwn ? tr("of her sideboard", "genitive, female owner") : tr("of %1's sideboard", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his sideboard", "genitive, male owner") : tr("of %1's sideboard", "genitive, male owner").arg(ownerName)); + case CaseAccusative: return female ? (hisOwn ? tr("her sideboard", "accusative, female owner") : tr("%1's sideboard", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his sideboard", "accusative, male owner") : tr("%1's sideboard", "accusative, male owner").arg(ownerName)); } return QString(); } diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 18cf52b8e..be218d6bc 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -15,6 +15,11 @@ QString MessageLogWidget::sanitizeHtml(QString dirty) const .replace(">", ">"); } +bool MessageLogWidget::isFemale(Player *player) const +{ + return player->getUserInfo()->getGender() == ServerInfo_User::Female; +} + void MessageLogWidget::logConnecting(QString hostname) { append(tr("Connecting to %1...").arg(sanitizeHtml(hostname))); @@ -122,11 +127,11 @@ void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) append(QString("%1: %2").arg(sanitizeHtml(spectatorName)).arg(sanitizeHtml(message))); } -void MessageLogWidget::logShuffle(Player *player) +void MessageLogWidget::logShuffle(Player *player, CardZone *zone) { soundEngine->shuffle(); if (currentContext != MessageContext_Mulligan) - append(tr("%1 shuffles his library.").arg(sanitizeHtml(player->getName()))); + append(tr("%1 shuffles %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); } void MessageLogWidget::logRollDie(Player *player, int sides, int roll) @@ -147,9 +152,9 @@ void MessageLogWidget::logDrawCards(Player *player, int number) void MessageLogWidget::logUndoDraw(Player *player, QString cardName) { if (cardName.isEmpty()) - append(tr("%1 undoes his last draw.").arg(sanitizeHtml(player->getName()))); + append((isFemale(player) ? tr("%1 undoes her last draw.") : tr("%1 undoes his last draw.")).arg(sanitizeHtml(player->getName()))); else - append(tr("%1 undoes his last draw (%2).").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + append((isFemale(player) ? tr("%1 undoes her last draw (%2).") : tr("%1 undoes his last draw (%2).")).arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } QPair MessageLogWidget::getFromStr(CardZone *zone, QString cardName, int position) const @@ -169,16 +174,16 @@ QPair MessageLogWidget::getFromStr(CardZone *zone, QString car else if (startName == "deck") { if (position == zone->getCards().size() - 1) { if (cardName.isEmpty()) { - cardName = tr("the bottom card of his library"); + cardName = isFemale(zone->getPlayer()) ? tr("the bottom card of her library") : tr("the bottom card of his library"); cardNameContainsStartZone = true; } else - fromStr = tr(" from the bottom of his library"); + fromStr = isFemale(zone->getPlayer()) ? tr(" from the bottom of her library") : tr(" from the bottom of his library"); } else if (position == 0) { if (cardName.isEmpty()) { - cardName = tr("the top card of his library"); + cardName = isFemale(zone->getPlayer()) ? tr("the top card of her library") : tr("the top card of his library"); cardNameContainsStartZone = true; } else - fromStr = tr(" from the top of his library"); + fromStr = isFemale(zone->getPlayer()) ? tr(" from the top of her library") : tr(" from the top of his library"); } else fromStr = tr(" from library"); } else if (startName == "sb") @@ -233,13 +238,13 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes) finalStr = tr("%1 moves %2%3 to hand."); else if (targetName == "deck") { if (attributes.newX == -1) - finalStr = tr("%1 puts %2%3 into his library."); + finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 into her library.") : tr("%1 puts %2%3 into his library."); else if (attributes.newX == attributes.targetZone->getCards().size() - 1) - finalStr = tr("%1 puts %2%3 on bottom of his library."); + finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 on bottom of her library.") : tr("%1 puts %2%3 on bottom of his library."); else if (attributes.newX == 0) - finalStr = tr("%1 puts %2%3 on top of his library."); + finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 on top of her library.") : tr("%1 puts %2%3 on top of his library."); else - finalStr = tr("%1 puts %2%3 into his library at position %4."); + finalStr = isFemale(attributes.targetZone->getPlayer()) ? tr("%1 puts %2%3 into her library at position %4.") : tr("%1 puts %2%3 into his library at position %4."); } else if (targetName == "sb") finalStr = tr("%1 moves %2%3 to sideboard."); else if (targetName == "stack") { @@ -269,7 +274,7 @@ void MessageLogWidget::logMulligan(Player *player, int number) if (number > -1) append(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); else - append(tr("%1 draws his initial hand.").arg(sanitizeHtml(player->getName()))); + append((isFemale(player) ? tr("%1 draws her initial hand.") : tr("%1 draws his initial hand.")).arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown) @@ -351,7 +356,7 @@ void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) else { QString cardStr; if (!card) - cardStr = tr("his permanents"); + cardStr = isFemale(player) ? tr("her permanents") : tr("his permanents"); else cardStr = QString("%1").arg(sanitizeHtml(card->getName())); append(tr("%1 %2 %3.").arg(sanitizeHtml(player->getName())).arg(tapped ? tr("taps") : tr("untaps")).arg(cardStr)); @@ -495,7 +500,7 @@ void MessageLogWidget::containerProcessingDone() void MessageLogWidget::connectToPlayer(Player *player) { connect(player, SIGNAL(logSay(Player *, QString)), this, SLOT(logSay(Player *, QString))); - connect(player, SIGNAL(logShuffle(Player *)), this, SLOT(logShuffle(Player *))); + connect(player, SIGNAL(logShuffle(Player *, CardZone *)), this, SLOT(logShuffle(Player *, CardZone *))); connect(player, SIGNAL(logRollDie(Player *, int, int)), this, SLOT(logRollDie(Player *, int, int))); connect(player, SIGNAL(logCreateArrow(Player *, Player *, QString, Player *, QString, bool)), this, SLOT(logCreateArrow(Player *, Player *, QString, Player *, QString, bool))); connect(player, SIGNAL(logCreateToken(Player *, QString, QString)), this, SLOT(logCreateToken(Player *, QString, QString))); diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 1a42a3261..fe548547b 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -31,6 +31,7 @@ private: CardInfoWidget *infoWidget; QString sanitizeHtml(QString dirty) const; + bool isFemale(Player *player) const; QPair getFromStr(CardZone *zone, QString cardName, int position) const; QString getCardNameUnderMouse(const QPoint &pos) const; MessageContext currentContext; @@ -66,7 +67,7 @@ public slots: void logGameStart(); void logSay(Player *player, QString message); void logSpectatorSay(QString spectatorName, QString message); - void logShuffle(Player *player); + void logShuffle(Player *player, CardZone *zone); void logRollDie(Player *player, int sides, int roll); void logDrawCards(Player *player, int number); void logUndoDraw(Player *player, QString cardName); diff --git a/cockatrice/src/pixmapgenerator.cpp b/cockatrice/src/pixmapgenerator.cpp index a27b081da..1c04e9226 100644 --- a/cockatrice/src/pixmapgenerator.cpp +++ b/cockatrice/src/pixmapgenerator.cpp @@ -78,6 +78,36 @@ QPixmap PingPixmapGenerator::generatePixmap(int size, int value, int max) QMap PingPixmapGenerator::pmCache; +QPixmap GenderPixmapGenerator::generatePixmap(int height, int _gender) +{ + ServerInfo_User::Gender gender = static_cast(_gender); + if ((gender != ServerInfo_User::Male) && (gender != ServerInfo_User::Female)) + gender = ServerInfo_User::GenderUnknown; + + int key = gender * 100000 + height; + if (pmCache.contains(key)) + return pmCache.value(key); + + QString genderStr; + switch (gender) { + case ServerInfo_User::Male: genderStr = "male"; break; + case ServerInfo_User::Female: genderStr = "female"; break; + default: genderStr = "unknown"; + }; + + QSvgRenderer svg(QString(":/resources/genders/" + genderStr + ".svg")); + int width = (int) round(height * (double) svg.defaultSize().width() / (double) svg.defaultSize().height()); + QPixmap pixmap(width, height); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + svg.render(&painter, QRectF(0, 0, width, height)); + + pmCache.insert(key, pixmap); + return pixmap; +} + +QMap GenderPixmapGenerator::pmCache; + QPixmap CountryPixmapGenerator::generatePixmap(int height, const QString &countryCode) { if (countryCode.size() != 2) @@ -110,8 +140,8 @@ QPixmap UserLevelPixmapGenerator::generatePixmap(int height, int userLevel) QString levelString; if (userLevel & ServerInfo_User::IsAdmin) levelString = "admin"; - else if (userLevel & ServerInfo_User::IsJudge) - levelString = "judge"; + else if (userLevel & ServerInfo_User::IsModerator) + levelString = "moderator"; else if (userLevel &ServerInfo_User::IsRegistered) levelString = "registered"; else diff --git a/cockatrice/src/pixmapgenerator.h b/cockatrice/src/pixmapgenerator.h index 7f69c26dd..25fa00c96 100644 --- a/cockatrice/src/pixmapgenerator.h +++ b/cockatrice/src/pixmapgenerator.h @@ -28,6 +28,14 @@ public: static void clear() { pmCache.clear(); } }; +class GenderPixmapGenerator { +private: + static QMap pmCache; +public: + static QPixmap generatePixmap(int height, int gender); + static void clear() { pmCache.clear(); } +}; + class CountryPixmapGenerator { private: static QMap pmCache; diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index d6a349788..7ebf9cdfe 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -713,7 +713,7 @@ void Player::eventSay(Event_Say *event) void Player::eventShuffle(Event_Shuffle * /*event*/) { - emit logShuffle(this); + emit logShuffle(this, zones.value("deck")); } void Player::eventRollDie(Event_RollDie *event) diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 4096c1e98..8645d70f0 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -70,7 +70,7 @@ signals: void newCardAdded(AbstractCardItem *card); // Log events void logSay(Player *player, QString message); - void logShuffle(Player *player); + void logShuffle(Player *player, CardZone *zone); void logRollDie(Player *player, int sides, int roll); void logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard, bool _playerTarget); void logCreateToken(Player *player, QString cardName, QString pt); diff --git a/cockatrice/src/userinfobox.cpp b/cockatrice/src/userinfobox.cpp index 40b4b0126..53b319c09 100644 --- a/cockatrice/src/userinfobox.cpp +++ b/cockatrice/src/userinfobox.cpp @@ -17,6 +17,8 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *paren nameLabel->setFont(nameFont); realNameLabel1 = new QLabel; realNameLabel2 = new QLabel; + genderLabel1 = new QLabel; + genderLabel2 = new QLabel; countryLabel1 = new QLabel; countryLabel2 = new QLabel; userLevelLabel1 = new QLabel; @@ -28,11 +30,13 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *paren mainLayout->addWidget(nameLabel, 1, 0, 1, 3); mainLayout->addWidget(realNameLabel1, 2, 0, 1, 1); mainLayout->addWidget(realNameLabel2, 2, 1, 1, 2); - mainLayout->addWidget(countryLabel1, 3, 0, 1, 1); - mainLayout->addWidget(countryLabel2, 3, 1, 1, 2); - mainLayout->addWidget(userLevelLabel1, 4, 0, 1, 1); - mainLayout->addWidget(userLevelLabel2, 4, 1, 1, 1); - mainLayout->addWidget(userLevelLabel3, 4, 2, 1, 1); + mainLayout->addWidget(genderLabel1, 3, 0, 1, 1); + mainLayout->addWidget(genderLabel2, 3, 1, 1, 2); + mainLayout->addWidget(countryLabel1, 4, 0, 1, 1); + mainLayout->addWidget(countryLabel2, 4, 1, 1, 2); + mainLayout->addWidget(userLevelLabel1, 5, 0, 1, 1); + mainLayout->addWidget(userLevelLabel2, 5, 1, 1, 1); + mainLayout->addWidget(userLevelLabel3, 5, 2, 1, 1); mainLayout->setColumnStretch(2, 10); setWindowTitle(tr("User information")); @@ -43,6 +47,7 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _fullInfo, QWidget *paren void UserInfoBox::retranslateUi() { realNameLabel1->setText(tr("Real name:")); + genderLabel1->setText(tr("Gender:")); countryLabel1->setText(tr("Location:")); userLevelLabel1->setText(tr("User level:")); } @@ -58,13 +63,14 @@ void UserInfoBox::updateInfo(ServerInfo_User *user) nameLabel->setText(user->getName()); realNameLabel2->setText(user->getRealName()); + genderLabel2->setPixmap(GenderPixmapGenerator::generatePixmap(15, user->getGender())); countryLabel2->setPixmap(CountryPixmapGenerator::generatePixmap(15, user->getCountry())); userLevelLabel2->setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel)); QString userLevelText; if (userLevel & ServerInfo_User::IsAdmin) userLevelText = tr("Administrator"); - else if (userLevel & ServerInfo_User::IsJudge) - userLevelText = tr("Judge"); + else if (userLevel & ServerInfo_User::IsModerator) + userLevelText = tr("Moderator"); else if (userLevel & ServerInfo_User::IsRegistered) userLevelText = tr("Registered user"); else diff --git a/cockatrice/src/userinfobox.h b/cockatrice/src/userinfobox.h index adf5f832c..ee4fd6043 100644 --- a/cockatrice/src/userinfobox.h +++ b/cockatrice/src/userinfobox.h @@ -13,7 +13,7 @@ class UserInfoBox : public QWidget { private: AbstractClient *client; bool fullInfo; - QLabel *avatarLabel, *nameLabel, *realNameLabel1, *realNameLabel2, *countryLabel1, *countryLabel2, *userLevelLabel1, *userLevelLabel2, *userLevelLabel3; + QLabel *avatarLabel, *nameLabel, *realNameLabel1, *realNameLabel2, *genderLabel1, *genderLabel2, *countryLabel1, *countryLabel2, *userLevelLabel1, *userLevelLabel2, *userLevelLabel3; public: UserInfoBox(AbstractClient *_client, bool fullInfo, QWidget *parent = 0, Qt::WindowFlags flags = 0); void retranslateUi(); diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index d2acd311a..1ce8de4b1 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -393,183 +393,363 @@ CardZone - - his hand - nominative + + her hand + nominative, female owner - + %1's hand - nominative + nominative, female owner - of his hand - genitive + his hand + nominative, male owner + %1's hand + nominative, male owner + + + + + of her hand + genitive, female owner + + + + of %1's hand - genitive + genitive, female owner - his hand - accusative + of his hand + genitive, male owner + of %1's hand + genitive, male owner + + + + + her hand + accusative, female owner + + + + %1's hand - accusative + accusative, female owner - - his library - nominative + + his hand + accusative, male owner - + + %1's hand + accusative, male owner + + + + + her library + nominative, female owner + + + + %1's library - nominative + nominative, female owner - of his library - genitive + his library + nominative, male owner + %1's library + nominative, male owner + + + + + of her library + genitive, female owner + + + + of %1's library - genitive + genitive, female owner - his library - accusative + of his library + genitive, male owner + of %1's library + genitive, male owner + + + + + her library + accusative, female owner + + + + %1's library - accusative + accusative, female owner - - his graveyard - nominative + + his library + accusative, male owner - + + %1's library + accusative, male owner + + + + + her graveyard + nominative, female owner + + + + %1's graveyard - nominative + nominative, female owner - of his graveyard - genitive + his graveyard + nominative, male owner + %1's graveyard + nominative, male owner + + + + + of her graveyard + genitive, female owner + + + + of %1's graveyard - genitive + genitive, female owner - his graveyard - accusative + of his graveyard + genitive, male owner + of %1's graveyard + genitive, male owner + + + + + her graveyard + accusative, female owner + + + + %1's graveyard - accusative + accusative, female owner - - his exile - nominative + + his graveyard + accusative, male owner - + + %1's graveyard + accusative, male owner + + + + + her exile + nominative, female owner + + + + %1's exile - nominative + nominative, female owner - of his exile - genitive + his exile + nominative, male owner + %1's exile + nominative, male owner + + + + + of her exile + genitive, female owner + + + + of %1's exile - genitive + genitive, female owner - his exile - accusative + of his exile + genitive, male owner + of %1's exile + genitive, male owner + + + + + her exile + accusative, female owner + + + + %1's exile - accusative + accusative, female owner - - his sideboard - nominative + + his exile + accusative, male owner - + + %1's exile + accusative, male owner + + + + + her sideboard + nominative, female owner + + + + %1's sideboard - nominative + nominative, female owner - of his sideboard - genitive + his sideboard + nominative, male owner + %1's sideboard + nominative, male owner + + + + + of her sideboard + genitive, female owner + + + + of %1's sideboard - genitive + genitive, female owner - his sideboard - accusative + of his sideboard + genitive, male owner + of %1's sideboard + genitive, male owner + + + + + her sideboard + accusative, female owner + + + + %1's sideboard - accusative + accusative, female owner + + + + + his sideboard + accusative, male owner + + + + + %1's sideboard + accusative, male owner @@ -1427,107 +1607,107 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Connected. - + Disconnected from server. - + Invalid password. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - - %1 shuffles his library. + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1536,138 +1716,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). - + + %1 undoes her last draw (%2). + + + + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + + the bottom card of her library + + + + from the bottom of his library - - the top card of his library - - - - - from the top of his library + + from the bottom of her library + the top card of his library + + + + + the top card of her library + + + + + from the top of his library + + + + + from the top of her library + + + + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. - - %1 puts %2%3 into his library at position %4. - - - - - %1 moves %2%3 to sideboard. + + %1 puts %2%3 on top of her library. + %1 puts %2%3 into his library at position %4. + + + + + %1 puts %2%3 into her library at position %4. + + + + + %1 moves %2%3 to sideboard. + + + + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1676,52 +1906,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1730,7 +1965,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -1739,7 +1974,7 @@ Local version is %1, remote version is %2. - + red @@ -1748,7 +1983,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1757,7 +1992,7 @@ Local version is %1, remote version is %2. - + green @@ -1766,157 +2001,162 @@ Local version is %1, remote version is %2. - + his permanents - + + her permanents + + + + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2788,42 +3028,47 @@ Please enter a name: UserInfoBox - + User information - + Real name: - + + Gender: + + + + Location: - + User level: - + Administrator - - Judge + + Moderator - + Registered user - + Unregistered user diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 6dff3bbc7..85e2d47ba 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -520,40 +520,34 @@ von %1s Sideboard - his hand nominative - seine Hand + seine Hand - %1's hand nominative - %1s Hand + %1s Hand - of his hand genitive - seiner Hand + seiner Hand - of %1's hand genitive - von %1s Hand + von %1s Hand - his hand accusative - seine Hand + seine Hand - %1's hand accusative - %1s Hand + %1s Hand his hand @@ -566,40 +560,34 @@ %1s Hand - his library nominative - seine Bibliothek + seine Bibliothek - %1's library nominative - %1s Bibliothek + %1s Bibliothek - of his library genitive - seiner Bibliothek + seiner Bibliothek - of %1's library genitive - von %1s Bibliothek + von %1s Bibliothek - his library accusative - seine Bibliothek + seine Bibliothek - %1's library accusative - %1s Bibliothek + %1s Bibliothek his library @@ -612,40 +600,394 @@ %1s Bibliothek - - his graveyard - nominative - sein Friedhof + + her hand + nominative, female owner + ihre Hand - + + %1's hand + nominative, female owner + %1s Hand + + + + his hand + nominative, male owner + seine Hand + + + + %1's hand + nominative, male owner + %1s Hand + + + + of her hand + genitive, female owner + ihrer Hand + + + + of %1's hand + genitive, female owner + von %1s Hand + + + + of his hand + genitive, male owner + seiner Hand + + + + of %1's hand + genitive, male owner + von %1s Hand + + + + her hand + accusative, female owner + ihre Hand + + + + %1's hand + accusative, female owner + %1s Hand + + + + his hand + accusative, male owner + seine Hand + + + + %1's hand + accusative, male owner + %1s Hand + + + + her library + nominative, female owner + ihre Bibliothek + + + + %1's library + nominative, female owner + %1s Bibliothek + + + + his library + nominative, male owner + seine Bibliothek + + + + %1's library + nominative, male owner + %1s Bibliothek + + + + of her library + genitive, female owner + ihrer Bibliothek + + + + of %1's library + genitive, female owner + von %1s Bibliothek + + + + of his library + genitive, male owner + seiner Bibliothek + + + + of %1's library + genitive, male owner + von %1s Bibliothek + + + + her library + accusative, female owner + ihre Bibliothek + + + + %1's library + accusative, female owner + %1s Bibliothek + + + + his library + accusative, male owner + seine Bibliothek + + + + %1's library + accusative, male owner + %1s Bibliothek + + + + her graveyard + nominative, female owner + ihr Friedhof + + + %1's graveyard - nominative + nominative, female owner %1s Friedhof - of his graveyard - genitive - seines Friedhofs + his graveyard + nominative, male owner + sein Friedhof + %1's graveyard + nominative, male owner + %1s Friedhof + + + + of her graveyard + genitive, female owner + ihres Friedhofs + + + of %1's graveyard - genitive + genitive, female owner von %1s Friedhof - his graveyard - accusative - sein Friedhof + of his graveyard + genitive, male owner + seines Friedhofs + of %1's graveyard + genitive, male owner + von %1s Friedhof + + + + her graveyard + accusative, female owner + ihren Friedhof + + + + %1's graveyard + accusative, female owner + %1s Friedhof + + + + his graveyard + accusative, male owner + seinen Friedhof + + + + %1's graveyard + accusative, male owner + %1s Friedhof + + + + her exile + nominative, female owner + ihr Exil + + + + %1's exile + nominative, female owner + %1s Exil + + + + his exile + nominative, male owner + sein Exil + + + + %1's exile + nominative, male owner + %1s Exil + + + + of her exile + genitive, female owner + ihres Exils + + + + of %1's exile + genitive, female owner + von %1s Exil + + + + of his exile + genitive, male owner + seines Exils + + + + of %1's exile + genitive, male owner + von %1s Exil + + + + her exile + accusative, female owner + ihr Exil + + + + %1's exile + accusative, female owner + %1s Exil + + + + his exile + accusative, male owner + sein Exil + + + + %1's exile + accusative, male owner + %1s Exil + + + + her sideboard + nominative, female owner + ihr Sideboard + + + + %1's sideboard + nominative, female owner + %1s Sideboard + + + + his sideboard + nominative, male owner + sein Sideboard + + + + %1's sideboard + nominative, male owner + %1s Sideboard + + + + of her sideboard + genitive, female owner + ihres Sideboards + + + + of %1's sideboard + genitive, female owner + von %1s Sideboard + + + + of his sideboard + genitive, male owner + seines Sideboards + + + + of %1's sideboard + genitive, male owner + von %1s Sideboard + + + + her sideboard + accusative, female owner + ihr Sideboard + + + + %1's sideboard + accusative, female owner + %1s Sideboard + + + + his sideboard + accusative, male owner + sein Sideboard + + + + %1's sideboard + accusative, male owner + %1s Sideboard + + + his graveyard + nominative + sein Friedhof + + + %1's graveyard + nominative + %1s Friedhof + + + of his graveyard + genitive + seines Friedhofs + + + of %1's graveyard + genitive + von %1s Friedhof + + + his graveyard + accusative + sein Friedhof + + %1's graveyard accusative - %1s Friedhof + %1s Friedhof his graveyard @@ -658,40 +1000,34 @@ %1s Friedhof - his exile nominative - sein Exil + sein Exil - %1's exile nominative - %1s Exil + %1s Exil - of his exile genitive - seines Exils + seines Exils - of %1's exile genitive - von %1s Exil + von %1s Exil - his exile accusative - sein Exil + sein Exil - %1's exile accusative - %1s Exil + %1s Exil his exile @@ -704,40 +1040,34 @@ %1s Exil - his sideboard nominative - sein Sideboard + sein Sideboard - %1's sideboard nominative - %1s Sideboard + %1s Sideboard - of his sideboard genitive - seines Sideboards + seines Sideboards - of %1's sideboard genitive - von %1s Sideboard + von %1s Sideboard - his sideboard accusative - sein Sideboard + sein Sideboard - %1's sideboard accusative - %1s Sideboard + %1s Sideboard his sideboard @@ -1899,7 +2229,7 @@ Grund: %1 Slovak: - + Slowakisch: @@ -2075,22 +2405,22 @@ Lokale Version ist %1, Serverversion ist %2. MessageLogWidget - + Connecting to %1... Verbinde zu %1... - + Connected. Verbunden. - + Disconnected from server. Verbindung zum Server getrennt. - + Invalid password. Ungültiges Passwort. @@ -2131,8 +2461,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten - - + + a card eine Karte @@ -2189,14 +2519,13 @@ Lokale Version ist %1, Serverversion ist %2. %1s Sideboard - + The game has started. Das Spiel hat begonnen. - %1 shuffles his library. - %1 mischt seine Bibliothek. + %1 mischt seine Bibliothek. %1 rolls a %2 with a %3-sided dice. @@ -2211,72 +2540,77 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversion stimmt nicht überein. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. Protokollfehler. - + You have joined game #%1. Sie sind dem Spiel %1 beigetreten. - + %1 has joined the game. %1 ist dem Spiel beigetreten. - + %1 has left the game. %1 hat das Spiel verlassen. - + The game has been closed. Das Spiel wurde geschlossen. - + %1 is now watching the game. %1 schaut nun dem Spiel zu. - + %1 is not watching the game any more. %1 schaut dem Spiel nicht mehr zu. - + %1 has loaded a local deck. %1 hat ein lokales Deck geladen. - + %1 has loaded deck #%2. %1 hat das Deck Nr. %2 geladen. - + %1 is ready to start the game. %1 ist bereit, das Spiel zu starten. - + %1 is not ready to start the game any more. %1 ist nicht mehr bereit, das Spiel zu starten. - + %1 has conceded the game. %1 hat das Spiel aufgegeben. + %1 shuffles %2. + %1 mischt %2. + + + %1 rolls a %2 with a %3-sided die. %1 würfelt eine %2 mit einem %3-seitigen Würfel. @@ -2289,7 +2623,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten. - + %1 draws %n card(s). %1 zieht eine Karte. @@ -2297,132 +2631,182 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 undoes his last draw. %1 legt die zuletzt gezogene Karte zurück. - + + %1 undoes her last draw. + %1 legt die zuletzt gezogene Karte zurück. + + + %1 undoes his last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + + %1 undoes her last draw (%2). + %1 legt die zuletzt gezogene Karte zurück (%2). + + + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + + the bottom card of her library + die unterste Karte ihrer Bibliothek + + + from the bottom of his library , die unterste Karte seiner Bibliothek, - + + from the bottom of her library + , die unterste Karte ihrer Bibliothek, + + + the top card of his library die oberste Karte seiner Bibliothek - + + the top card of her library + die oberste Karte ihrer Bibliothek + + + from the top of his library , die oberste Karte seiner Bibliothek, - + + from the top of her library + , die oberste Karte ihrer Bibliothek, + + + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + from the stack vom Stapel - + %1 gives %2 control over %3. %1 überlässt %2 die Kontrolle über %3. - + %1 puts %2 into play tapped%3. %1 bringt %2 getappt%3 ins Spiel. - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + + %1 puts %2%3 into her library. + %1 legt %2%3 in ihre Bibliothek. + + + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + + %1 puts %2%3 on bottom of her library. + %1 legt %2%3 unter ihre Bibliothek. + + + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + + %1 puts %2%3 on top of her library. + %1 legt %2%3 auf die Bibliothek. + + + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + + %1 puts %2%3 into her library at position %4. + %1 legt %2%3 in ihre Bibliothek an %4. Stelle. + + + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 plays %2%3. %1 spielt %2%3 aus. - + %1 takes a mulligan to %n. %1 nimmt einen Mulligan auf %n. @@ -2430,47 +2814,52 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 draws his initial hand. %1 zieht seine Starthand. - + + %1 draws her initial hand. + %1 zieht ihre Starthand. + + + %1 flips %2 face-down. %1 wendet %2 auf die Rückseite. - + %1 flips %2 face-up. %1 wendet %2 auf die Vorderseite. - + %1 destroys %2. %1 zerstört %2. - + %1 attaches %2 to %3's %4. %1 legt %2 an %3s %4 an. - + %1 unattaches %2. %1 löst %2 ab. - + %1 creates token: %2%3. %1 erstellt Token: %2%3. - + %1 points from %2's %3 to %4. %1 zeigt von %2s %3 auf %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 legt eine %2 Marke auf %3 (jetzt %4). @@ -2478,7 +2867,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 entfernt eine %2 Marke von %3 (jetzt %4). @@ -2486,22 +2875,27 @@ Lokale Version ist %1, Serverversion ist %2. - + + her permanents + ihre bleibenden Karten + + + %1 randomly reveals %2%3 to %4. %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3. %1 zeigt zufällig %2%3 offen vor. - + %1 reveals %2%3 to %4. %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3. %1 zeigt %2%3 offen vor. @@ -2510,7 +2904,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 erstellt einen Spielstein: %2 (%3). - + %1 points from %2's %3 to %4's %5. %1 zeigt von %2s %3 auf %4s %5. @@ -2529,7 +2923,7 @@ Lokale Version ist %1, Serverversion ist %2. - + red rote @@ -2537,7 +2931,7 @@ Lokale Version ist %1, Serverversion ist %2. - + yellow gelbe @@ -2545,7 +2939,7 @@ Lokale Version ist %1, Serverversion ist %2. - + green grüne @@ -2553,22 +2947,22 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 sets counter %2 to %3 (%4%5). %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets PT of %2 to %3. %1 setzt Kampfwerte von %2 auf %3. - + %1 sets annotation of %2 to %3. %1 versieht %2 mit dem Hinweis %3. - + %1 is looking at the top %2 cards %3. %1 sieht sich die obersten %2 Karten %3 an. @@ -2665,7 +3059,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4). - + %1 %2 %3. %1 %2 %3. @@ -2678,22 +3072,22 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. %1 sieht sich %2 an. - + %1 stops looking at %2. %1 sieht sich %2 nicht mehr an. - + %1 reveals %2 to %3. %1 zeigt %3 %2. - + %1 reveals %2. %1 zeigt %2 offen vor. @@ -2714,7 +3108,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zeigt %2 aus %3 offen vor. - + ending phase die Zugendphase @@ -2743,57 +3137,57 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich %2s %3 nicht mehr an - + It is now %1's turn. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -2802,7 +3196,7 @@ Lokale Version ist %1, Serverversion ist %2. das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -2811,12 +3205,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 bewegt %2 %3 nach %4 - + taps tappt - + untaps enttappt @@ -2841,7 +3235,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4) - + his permanents seine bleibenden Karten @@ -2854,12 +3248,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 setzt Zähler "%2" auf %3 (%4%5) - + %1 sets %2 to not untap normally. %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. %1 setzt %2 auf normales Enttappen. @@ -4021,42 +4415,51 @@ Bitte geben Sie einen Namen ein: UserInfoBox - + User information Benutzerinformationen - + Real name: Richtiger Name: - + + Gender: + Geschlecht: + + + Location: Ort: - + User level: Nutzerstatus: - + Administrator Administrator - - Judge - Schiedsrichter + + Moderator + Moderator - + Judge + Schiedsrichter + + + Registered user Registrierter Benutzer - + Unregistered user Unregistrierter Benutzer diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 233563803..415aa3fd0 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -393,183 +393,363 @@ CardZone - - his hand - nominative + + her hand + nominative, female owner - + %1's hand - nominative + nominative, female owner - of his hand - genitive + his hand + nominative, male owner + %1's hand + nominative, male owner + + + + + of her hand + genitive, female owner + + + + of %1's hand - genitive + genitive, female owner - his hand - accusative + of his hand + genitive, male owner + of %1's hand + genitive, male owner + + + + + her hand + accusative, female owner + + + + %1's hand - accusative + accusative, female owner - - his library - nominative + + his hand + accusative, male owner - + + %1's hand + accusative, male owner + + + + + her library + nominative, female owner + + + + %1's library - nominative + nominative, female owner - of his library - genitive + his library + nominative, male owner + %1's library + nominative, male owner + + + + + of her library + genitive, female owner + + + + of %1's library - genitive + genitive, female owner - his library - accusative + of his library + genitive, male owner + of %1's library + genitive, male owner + + + + + her library + accusative, female owner + + + + %1's library - accusative + accusative, female owner - - his graveyard - nominative + + his library + accusative, male owner - + + %1's library + accusative, male owner + + + + + her graveyard + nominative, female owner + + + + %1's graveyard - nominative + nominative, female owner - of his graveyard - genitive + his graveyard + nominative, male owner + %1's graveyard + nominative, male owner + + + + + of her graveyard + genitive, female owner + + + + of %1's graveyard - genitive + genitive, female owner - his graveyard - accusative + of his graveyard + genitive, male owner + of %1's graveyard + genitive, male owner + + + + + her graveyard + accusative, female owner + + + + %1's graveyard - accusative + accusative, female owner - - his exile - nominative + + his graveyard + accusative, male owner - + + %1's graveyard + accusative, male owner + + + + + her exile + nominative, female owner + + + + %1's exile - nominative + nominative, female owner - of his exile - genitive + his exile + nominative, male owner + %1's exile + nominative, male owner + + + + + of her exile + genitive, female owner + + + + of %1's exile - genitive + genitive, female owner - his exile - accusative + of his exile + genitive, male owner + of %1's exile + genitive, male owner + + + + + her exile + accusative, female owner + + + + %1's exile - accusative + accusative, female owner - - his sideboard - nominative + + his exile + accusative, male owner - + + %1's exile + accusative, male owner + + + + + her sideboard + nominative, female owner + + + + %1's sideboard - nominative + nominative, female owner - of his sideboard - genitive + his sideboard + nominative, male owner + %1's sideboard + nominative, male owner + + + + + of her sideboard + genitive, female owner + + + + of %1's sideboard - genitive + genitive, female owner - his sideboard - accusative + of his sideboard + genitive, male owner + of %1's sideboard + genitive, male owner + + + + + her sideboard + accusative, female owner + + + + %1's sideboard - accusative + accusative, female owner + + + + + his sideboard + accusative, male owner + + + + + %1's sideboard + accusative, male owner @@ -1427,52 +1607,57 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. + %1 shuffles %2. + + + + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). %1 draws a card. @@ -1480,158 +1665,208 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). - + + %1 undoes her last draw (%2). + + + + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + + the bottom card of her library + + + + from the bottom of his library - - the top card of his library - - - - - from the top of his library + + from the bottom of her library + the top card of his library + + + + + the top card of her library + + + + + from the top of his library + + + + + from the top of her library + + + + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. - - %1 puts %2%3 into his library at position %4. - - - - - %1 moves %2%3 to sideboard. + + %1 puts %2%3 on top of her library. + %1 puts %2%3 into his library at position %4. + + + + + %1 puts %2%3 into her library at position %4. + + + + + %1 moves %2%3 to sideboard. + + + + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1650,7 +1885,7 @@ Local version is %1, remote version is %2. - + red @@ -1658,7 +1893,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1666,7 +1901,7 @@ Local version is %1, remote version is %2. - + green @@ -1674,77 +1909,77 @@ Local version is %1, remote version is %2. - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. - + %1 takes a mulligan to %n. @@ -1752,27 +1987,32 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 places a %2 counter on %3 (now %4). @@ -1780,7 +2020,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 removes a %2 counter from %3 (now %4). @@ -1788,142 +2028,142 @@ Local version is %1, remote version is %2. - + + her permanents + + + + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - - %1 shuffles his library. - - - - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2795,42 +3035,47 @@ Please enter a name: UserInfoBox - + User information - + Real name: - + + Gender: + + + + Location: - + User level: - + Administrator - - Judge + + Moderator - + Registered user - + Unregistered user diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 6fe34f61e..116265d52 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -485,40 +485,34 @@ de la reserva &de %1 - his hand nominative - su mano + su mano - %1's hand nominative - mano de %1 + mano de %1 - of his hand genitive - de su mano + de su mano - of %1's hand genitive - de la mano de %1 + de la mano de %1 - his hand accusative - su mano + su mano - %1's hand accusative - mano de %1 + mano de %1 his hand @@ -531,40 +525,34 @@ mano &de %1 - his library nominative - su biblioteca + su biblioteca - %1's library nominative - biblioteca de %1 + biblioteca de %1 - of his library genitive - de su biblioteca + de su biblioteca - of %1's library genitive - de la biblioteca de %1 + de la biblioteca de %1 - his library accusative - su biblioteca + su biblioteca - %1's library accusative - biblioteca de %1 + biblioteca de %1 his library @@ -577,40 +565,394 @@ biblioteca &de %1 - - his graveyard - nominative - su cementerio + + her hand + nominative, female owner + - - %1's graveyard - nominative - cementerio de %1 + + %1's hand + nominative, female owner + + + + + his hand + nominative, male owner + su mano + + + + %1's hand + nominative, male owner + + + + + of her hand + genitive, female owner + + + + + of %1's hand + genitive, female owner + + + + + of his hand + genitive, male owner + de su mano + + + + of %1's hand + genitive, male owner + + + + + her hand + accusative, female owner + + + + + %1's hand + accusative, female owner + + + + + his hand + accusative, male owner + su mano + + + + %1's hand + accusative, male owner + + + + + her library + nominative, female owner + + + + + %1's library + nominative, female owner + + + + + his library + nominative, male owner + su biblioteca + + + + %1's library + nominative, male owner + + + + + of her library + genitive, female owner + + + + + of %1's library + genitive, female owner + + + + + of his library + genitive, male owner + de su biblioteca + + + + of %1's library + genitive, male owner + + + + + her library + accusative, female owner + + + + + %1's library + accusative, female owner + + + + + his library + accusative, male owner + su biblioteca + + + + %1's library + accusative, male owner + + her graveyard + nominative, female owner + + + + + %1's graveyard + nominative, female owner + + + + + his graveyard + nominative, male owner + su cementerio + + + + %1's graveyard + nominative, male owner + + + + + of her graveyard + genitive, female owner + + + + + of %1's graveyard + genitive, female owner + + + + + of his graveyard + genitive, male owner + de su cementerio + + + + of %1's graveyard + genitive, male owner + + + + + her graveyard + accusative, female owner + + + + + %1's graveyard + accusative, female owner + + + + + his graveyard + accusative, male owner + su cementerio + + + + %1's graveyard + accusative, male owner + + + + + her exile + nominative, female owner + + + + + %1's exile + nominative, female owner + el exilio de %1 + + + + his exile + nominative, male owner + su exilio + + + + %1's exile + nominative, male owner + el exilio de %1 + + + + of her exile + genitive, female owner + + + + + of %1's exile + genitive, female owner + del exilio de %1 + + + + of his exile + genitive, male owner + de su exilio + + + + of %1's exile + genitive, male owner + del exilio de %1 + + + + her exile + accusative, female owner + + + + + %1's exile + accusative, female owner + el exilio de %1 + + + + his exile + accusative, male owner + su exilio + + + + %1's exile + accusative, male owner + el exilio de %1 + + + + her sideboard + nominative, female owner + + + + + %1's sideboard + nominative, female owner + la reserva de %1 + + + + his sideboard + nominative, male owner + su reserva + + + + %1's sideboard + nominative, male owner + la reserva de %1 + + + + of her sideboard + genitive, female owner + + + + + of %1's sideboard + genitive, female owner + + + + + of his sideboard + genitive, male owner + de su reserva + + + + of %1's sideboard + genitive, male owner + + + + + her sideboard + accusative, female owner + + + + + %1's sideboard + accusative, female owner + la reserva de %1 + + + + his sideboard + accusative, male owner + su reserva + + + + %1's sideboard + accusative, male owner + la reserva de %1 + + + his graveyard + nominative + su cementerio + + + %1's graveyard + nominative + cementerio de %1 + + of his graveyard genitive - de su cementerio + de su cementerio - of %1's graveyard genitive - del cementerio de %1 + del cementerio de %1 - his graveyard accusative - su cementerio + su cementerio - %1's graveyard accusative - cementerio de %1 + cementerio de %1 his graveyard @@ -623,40 +965,34 @@ cementerio &de %1 - his exile nominative - su exilio + su exilio - %1's exile nominative - el exilio de %1 + el exilio de %1 - of his exile genitive - de su exilio + de su exilio - of %1's exile genitive - del exilio de %1 + del exilio de %1 - his exile accusative - su exilio + su exilio - %1's exile accusative - el exilio de %1 + el exilio de %1 his exile @@ -669,40 +1005,34 @@ el exilio de %1 - his sideboard nominative - su reserva + su reserva - %1's sideboard nominative - la reserva de %1 + la reserva de %1 - of his sideboard genitive - de su reserva + de su reserva - of %1's sideboard genitive - de la reserva de %1 + de la reserva de %1 - his sideboard accusative - su reserva + su reserva - %1's sideboard accusative - la reserva de %1 + la reserva de %1 his sideboard @@ -1650,52 +1980,57 @@ La versión local es %1, la versión remota es %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado del servidor. - + Invalid password. Contraseña incorrecta. - + Protocol error. Error del protocolo. - + The game has been closed. La partida ha sido cerrada. - + %1 is now watching the game. %1 está ahora observando la partida. - + %1 is not watching the game any more. %1 ya no está observado más la partida. - + %1 is not ready to start the game any more. %1 ya no está listo para empezar el juego. + %1 shuffles %2. + + + + %1 rolls a %2 with a %3-sided die. %1 sacó un %2 con un dado de %3 caras. - + %1 draws %n card(s). %1 roba %n carta. @@ -1703,158 +2038,208 @@ La versión local es %1, la versión remota es %2. - + %1 undoes his last draw. %1 deshace su último robo. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). %1 deshace su último robo (%2). - + + %1 undoes her last draw (%2). + + + + from table de la mesa - + from graveyard del cementerio - + from exile del exilio - + from hand de la mano - + the bottom card of his library el fondo de la biblioteca - + + the bottom card of her library + + + + from the bottom of his library del fondo de la biblioteca - + + from the bottom of her library + + + + the top card of his library la parte superior de la biblioteca - + + the top card of her library + + + + from the top of his library de la parte superior de la biblioteca - + + from the top of her library + + + + from library de la biblioteca - + from sideboard de la reserva - + from the stack de la pila - + %1 gives %2 control over %3. %1 entrega a %2 el control sobre %3. - + %1 puts %2 into play tapped%3. %1 pone %2 en juego%3 girado. - + %1 puts %2 into play%3. %1 pone %2 en juego%3. - + %1 puts %2%3 into graveyard. %1 pone %2%3 en el cementerio. - + %1 exiles %2%3. %1 exilia %2%3. - + %1 moves %2%3 to hand. %1 mueve %2%3 a la mano. - + %1 puts %2%3 into his library. %1 pone %2%3 en la biblioteca. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. %1 pone %2%3 en la parte inferior de su biblioteca. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. %1 pone %2%3 en la parte superior de su biblioteca. - + + %1 puts %2%3 on top of her library. + + + + %1 puts %2%3 into his library at position %4. %1 pone %2%3 en su biblioteca en la posición %4. - + + %1 puts %2%3 into her library at position %4. + + + + %1 moves %2%3 to sideboard. %1 mueve %2%3 a la reserva. - + %1 plays %2%3. %1 juega %2%3. - - + + a card una carta - + %1 flips %2 face-down. %1 voltea %2 boca abajo. - + %1 flips %2 face-up. %1 voltea %2 boca arriba. - + %1 attaches %2 to %3's %4. %1 anexa %2 a el %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 apunta desde el %3 de %2 al %5 de %4. @@ -1873,7 +2258,7 @@ La versión local es %1, la versión remota es %2. - + red rojo @@ -1881,7 +2266,7 @@ La versión local es %1, la versión remota es %2. - + yellow amarillo @@ -1889,7 +2274,7 @@ La versión local es %1, la versión remota es %2. - + green verde @@ -1897,72 +2282,72 @@ La versión local es %1, la versión remota es %2. - + %1 sets counter %2 to %3 (%4%5). %1 establece los contadores de %2 a %3 (%4%5). - + %1 sets PT of %2 to %3. %1 establece F/R de %2 a %3. - + %1 sets annotation of %2 to %3. %1 establece la anotación de %2 a %3. - + %1 is looking at the top %2 cards %3. %1 esta mirando las primeras %2 cartas de %3. - + The game has started. La partida ha comenzado. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 La versión del protocolo es diferente. Cliente: %1, Servidor: %2 - + You have joined game #%1. Te has unido a la partida #%1. - + %1 has joined the game. %1 se ha unido a la partida. - + %1 has left the game. %1 ha dejado la partida. - + %1 has loaded a local deck. %1 ha cargado un mazo local. - + %1 has loaded deck #%2. %1 ha cargado el mazo #%2. - + %1 is ready to start the game. %1 está preparado para empezar la partida. - + %1 has conceded the game. %1 ha concedido la partida. @@ -1975,22 +2360,22 @@ La versión local es %1, la versión remota es %2. %1 roba %2 cartas. - + %1 destroys %2. %1 destruye %2. - + %1 creates token: %2%3. %1 crea una ficha: %2%3. - + %1 points from %2's %3 to %4. %1 apunta desde el %3 de %2 a %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 pone %n %2 contador en %3 (ahora %4). @@ -1998,7 +2383,7 @@ La versión local es %1, la versión remota es %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remueve %n %2 contador en %3 (ahora %4). @@ -2006,47 +2391,46 @@ La versión local es %1, la versión remota es %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está mirando: %2. - + %1 stops looking at %2. %1 termina de mirar: %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase de fin de turno - + It is now %1's turn. Es el turno de %1. - %1 shuffles his library. - %1 baraja su biblioteca. + %1 baraja su biblioteca. - + %1 takes a mulligan to %n. @@ -2054,107 +2438,117 @@ La versión local es %1, la versión remota es %2. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + + her permanents + + + + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3 a %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step paso de enderezar - + upkeep step paso de mantenimiento - + draw step paso de robar - + first main phase primera fase principal - + beginning of combat step paso de inicio de combate - + declare attackers step paso de declarar atacantes - + declare blockers step paso de declarar bloqueadores - + combat damage step paso de daño de combate - + end of combat step paso de fin de combate - + second main phase segunda fase principal - + It is now the %1. Ahora es el %1. - + taps gira - + untaps endereza - + %1 sets %2 to not untap normally. %1 establece que %2 no se endereze normalmente. - + %1 sets %2 to untap normally. %1 establece que %2 se endereze normalmente. - + his permanents sus permanentes @@ -3097,42 +3491,51 @@ Por favor, introduzca un nombre: UserInfoBox - + User information Información del usuario - + Real name: Nombre real: - + + Gender: + + + + Location: Localización: - + User level: Nivel de usuario: - + Administrator Administrador - - Judge - Juez + + Moderator + - + Judge + Juez + + + Registered user Usuario registrado - + Unregistered user Usuario no registrado diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 242d66bb6..de17833e4 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -397,184 +397,514 @@ CardZone - his hand nominative - sa main + sa main - %1's hand nominative - main de %1 + main de %1 - of his hand genitive - de sa main + de sa main + + + of %1's hand + genitive + de la main de %1 + + + his hand + accusative + sa main + + + %1's hand + accusative + main de %1 + + + his library + nominative + sa bibliothèque + + + %1's library + nominative + bibliothèque de %1 + + + of his library + genitive + de sa bibliothèque + + + of %1's library + genitive + de la bibliothèque de %1 + + + his library + accusative + sa bibliothèque + + + %1's library + accusative + bibliothèque de %1 - of %1's hand - genitive - de la main de %1 + her hand + nominative, female owner + - - his hand - accusative - sa main - - - + %1's hand - accusative - main de %1 + nominative, female owner + main de %1 - - his library - nominative - sa bibliothèque + + his hand + nominative, male owner + sa main - + + %1's hand + nominative, male owner + main de %1 + + + + of her hand + genitive, female owner + + + + + of %1's hand + genitive, female owner + de la main de %1 + + + + of his hand + genitive, male owner + de sa main + + + + of %1's hand + genitive, male owner + de la main de %1 + + + + her hand + accusative, female owner + + + + + %1's hand + accusative, female owner + main de %1 + + + + his hand + accusative, male owner + sa main + + + + %1's hand + accusative, male owner + main de %1 + + + + her library + nominative, female owner + + + + %1's library - nominative - bibliothèque de %1 + nominative, female owner + bibliothèque de %1 - of his library - genitive - de sa bibliothèque + his library + nominative, male owner + sa bibliothèque + %1's library + nominative, male owner + bibliothèque de %1 + + + + of her library + genitive, female owner + + + + of %1's library - genitive - de la bibliothèque de %1 + genitive, female owner + de la bibliothèque de %1 - his library - accusative - sa bibliothèque + of his library + genitive, male owner + de sa bibliothèque + of %1's library + genitive, male owner + de la bibliothèque de %1 + + + + her library + accusative, female owner + + + + %1's library - accusative - bibliothèque de %1 + accusative, female owner + bibliothèque de %1 - - his graveyard - nominative - son cimetière + + his library + accusative, male owner + sa bibliothèque - - %1's graveyard - nominative - le cimetière de %1 + + %1's library + accusative, male owner + bibliothèque de %1 + her graveyard + nominative, female owner + + + + + %1's graveyard + nominative, female owner + le cimetière de %1 + + + + his graveyard + nominative, male owner + son cimetière + + + + %1's graveyard + nominative, male owner + le cimetière de %1 + + + + of her graveyard + genitive, female owner + + + + + of %1's graveyard + genitive, female owner + du cimetière de %1 + + + + of his graveyard + genitive, male owner + de son cimetière + + + + of %1's graveyard + genitive, male owner + du cimetière de %1 + + + + her graveyard + accusative, female owner + + + + + %1's graveyard + accusative, female owner + le cimetière de %1 + + + + his graveyard + accusative, male owner + son cimetière + + + + %1's graveyard + accusative, male owner + le cimetière de %1 + + + + her exile + nominative, female owner + + + + + %1's exile + nominative, female owner + la zone exil de %1 + + + + his exile + nominative, male owner + sa zone exil + + + + %1's exile + nominative, male owner + la zone exil de %1 + + + + of her exile + genitive, female owner + + + + + of %1's exile + genitive, female owner + de la zone exil de %1 + + + + of his exile + genitive, male owner + de sa zone exil + + + + of %1's exile + genitive, male owner + de la zone exil de %1 + + + + her exile + accusative, female owner + + + + + %1's exile + accusative, female owner + la zone exil de %1 + + + + his exile + accusative, male owner + sa zone exil + + + + %1's exile + accusative, male owner + la zone exil de %1 + + + + her sideboard + nominative, female owner + + + + + %1's sideboard + nominative, female owner + la réserve de %1 + + + + his sideboard + nominative, male owner + sa réserve + + + + %1's sideboard + nominative, male owner + la réserve de %1 + + + + of her sideboard + genitive, female owner + + + + + of %1's sideboard + genitive, female owner + de la réserve de %1 + + + + of his sideboard + genitive, male owner + de sa réserve + + + + of %1's sideboard + genitive, male owner + de la réserve de %1 + + + + her sideboard + accusative, female owner + + + + + %1's sideboard + accusative, female owner + la réserve de %1 + + + + his sideboard + accusative, male owner + sa réserve + + + + %1's sideboard + accusative, male owner + la réserve de %1 + + + his graveyard + nominative + son cimetière + + + %1's graveyard + nominative + le cimetière de %1 + + of his graveyard genitive - de son cimetière + de son cimetière - of %1's graveyard genitive - du cimetière de %1 + du cimetière de %1 - his graveyard accusative - son cimetière + son cimetière - %1's graveyard accusative - le cimetière de %1 + le cimetière de %1 - his exile nominative - sa zone exil + sa zone exil - %1's exile nominative - la zone exil de %1 + la zone exil de %1 - of his exile genitive - de sa zone exil + de sa zone exil - of %1's exile genitive - de la zone exil de %1 + de la zone exil de %1 - his exile accusative - sa zone exil + sa zone exil - %1's exile accusative - la zone exil de %1 + la zone exil de %1 - his sideboard nominative - sa réserve + sa réserve - %1's sideboard nominative - la réserve de %1 + la réserve de %1 - of his sideboard genitive - de sa réserve + de sa réserve - of %1's sideboard genitive - de la réserve de %1 + de la réserve de %1 - his sideboard accusative - sa réserve + sa réserve - %1's sideboard accusative - la réserve de %1 + la réserve de %1 @@ -1507,103 +1837,102 @@ La version la plus récente est %1, l'ancienne version est %2. MessageLogWidget - + Connecting to %1... Connexion à %1... - + Connected. Connecté. - + Disconnected from server. Déconnecté du serveur. - + Invalid password. Mot de passe invalide. - + Protocol version mismatch. Client: %1, Server: %2 Version de protocole différente. Version locale: %1 ,version distante: %2 - + Protocol error. Erreur de protocole. - + You have joined game #%1. Vous avez rejoint la partie #%1. - + %1 has joined the game. %1 a rejoint la partie. - + %1 has left the game. %1 a quitté la partie. - + The game has been closed. La partie a été fermée. - + %1 is now watching the game. %1 est maintenant spectateur. - + %1 is not watching the game any more. %1 n'est plus spectateur. - + %1 has loaded a local deck. %1 a chargé un deck local. - + %1 has loaded deck #%2. %1 a chargé le deck #%2. - + %1 is ready to start the game. %1 est prêt à démarrer la partie. - + %1 is not ready to start the game any more. %1 n'est plus prêt à démarrer la partie. - + %1 has conceded the game. partie ou jeu %1 a concédé la partie. - + The game has started. La partie commence. - %1 shuffles his library. - %1 mélange sa bibliothèque. + %1 mélange sa bibliothèque. - + %1 rolls a %2 with a %3-sided die. is it always a dice? %1 lance un %2 à %3 faces. @@ -1617,124 +1946,169 @@ La version la plus récente est %1, l'ancienne version est %2.%1 pioche %2 cartes. - + from table depuis le champ de bataille - + from graveyard depuis son cimetière - + from exile depuis la zone exil - + from hand depuis sa main - + the bottom card of his library la carte du dessous de sa bibliothèque - + + the bottom card of her library + + + + from the bottom of his library du dessous de sa bibliothèque - + + from the bottom of her library + + + + the top card of his library le carte du dessus de sa bibliothèque - + + the top card of her library + + + + from the top of his library du dessus de sa bibliothèque - + + from the top of her library + + + + from library depuis sa bibliothèque - + from sideboard depuis sa réserve - + from the stack depuis la pile - + %1 puts %2 into play tapped%3. %1 met %2 en jeu engagé%3. - + %1 puts %2 into play%3. what is %3? plz exemple (resp. by Ranma : XX met island en jeu -depuis sa main-.) %1 met %2 en jeu %3. - + %1 puts %2%3 into graveyard. %1 met %2%3 dans son cimetière. - + %1 exiles %2%3. %1 exile %2%3. - + %1 moves %2%3 to hand. %1 met %2%3 dans sa main. - + %1 puts %2%3 into his library. %1 met %2%3 dans sa bibliothèque. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. %1 met %2%3 en-dessous de sa bibliothèque. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. %1 met %2%3 au-dessus de sa bibliothèque. - + + %1 puts %2%3 on top of her library. + + + + %1 puts %2%3 into his library at position %4. %1 met %2%3 dans sa bibliothèque à la position n°%4. - + + %1 puts %2%3 into her library at position %4. + + + + %1 moves %2%3 to sideboard. %1 met %2%3 à sa réserve. - + %1 plays %2%3. %1 joue %2%3. - - + + a card une carte + + + %1 shuffles %2. + + - + %1 draws %n card(s). %1 pioche %n carte. @@ -1742,22 +2116,32 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 undoes his last draw. %1 annule sa dernière pioche. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). %1 annule sa dernière pioche (%2). - + + %1 undoes her last draw (%2). + + + + %1 gives %2 control over %3. %1 donne le contrôle de %2 à %3. - + %1 takes a mulligan to %n. @@ -1765,49 +2149,54 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + %1 flips %2 face-down. %1 retourne %2 face cachée. - + %1 flips %2 face-up. %1 retourne %2 face visible. - + %1 destroys %2. %1 détruit %2. - + %1 attaches %2 to %3's %4. need exemple (Resp'.by Ranma: JoueurA attache Adventuring Gear sur -Plated Geopede- de -JoueurB-.) %1 attache %2 sur %4 de %3. - + %1 unattaches %2. %1 détache %2. - + %1 creates token: %2%3. %1 crée un jeton %2%3. - + %1 points from %2's %3 to %4. need exemple %1 désigne le %3 de %2 à %4. - + %1 points from %2's %3 to %4's %5. need exemple %1 désigne le %3 de %2 à %5 de %4. @@ -1829,7 +2218,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 places %n %2 counter(s) on %3 (now %4). %1 met %n %2 marqueur sur %3 (maintenant %4). @@ -1837,7 +2226,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 retire %n %2 marqueur de %3 (maintenant %4). @@ -1845,7 +2234,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + red rouge @@ -1853,7 +2242,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + yellow jaune @@ -1861,7 +2250,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + green vert @@ -1869,164 +2258,169 @@ La version la plus récente est %1, l'ancienne version est %2. - + his permanents ses permanents - + + her permanents + + + + %1 %2 %3. wtf ? %1 %2 %3. - + taps engage - + untaps dégage - + %1 sets counter %2 to %3 (%4%5). need exemple %1 met les marqueurs %2 à %3 (%4%5). - + %1 sets %2 to not untap normally. need exemple %2 de %1 ne se dégagera pas lors de l'étape de dégagement. - + %1 sets %2 to untap normally. %2 de %1 se dégagera lors de l'étape de dégagement. - + %1 sets PT of %2 to %3. exemple plz %1 change la F/E de %2 à %3. - + %1 sets annotation of %2 to %3. %1 met l'annotation %3 à %2. - + %1 is looking at the top %2 cards %3. exemple plz %1 regarde les %2 cartes du dessus %3. - + %1 is looking at %2. exemple plz %1 regarde %2. - + %1 stops looking at %2. need exemple to be sure %1 arrête de regarder %2. - + %1 reveals %2 to %3. %1 révèle %2 à %3. - + %1 reveals %2. %1 révèle %2. - + %1 randomly reveals %2%3 to %4. %1 révèle au hasard %2%3 à %4. - + %1 randomly reveals %2%3. %1 révèle au hasard %2%3. - + %1 reveals %2%3 to %4. %1 révèle %2%3 à %4. - + %1 reveals %2%3. %1 révèle %2%3. - + It is now %1's turn. C'est maintenant le tour de %1. - + untap step étape de dégagement - + upkeep step étape d'entretien - + draw step étape de pioche - + first main phase première phase principale - + beginning of combat step étape de début du combat - + declare attackers step étape de déclaration des attaquants - + declare blockers step étape de déclaration des bloqueurs - + combat damage step étape de répartition et de résolution des blessures - + end of combat step étape de fin de combat - + second main phase seconde phase principale - + ending phase phase de fin de tour - + It is now the %1. need exemple C'est maintenant %1. @@ -2957,43 +3351,52 @@ Entrez un nom s'il vous plaît: UserInfoBox - + User information Informations utilisateur - + Real name: Vrai nom: - + + Gender: + + + + Location: Localisation: - + User level: Rang utilisateur: - + Administrator Administrateur - - Judge - arbitre ? - Juge + + Moderator + - + Judge + arbitre ? + Juge + + + Registered user Utilisateur enregistré - + Unregistered user Utilisateur non enregistré diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index 61e5c43bc..4ae3575c8 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -403,184 +403,364 @@ CardZone - - his hand - nominative - + + her hand + nominative, female owner + - + %1's hand - nominative - + nominative, female owner + - of his hand - genitive - + his hand + nominative, male owner + + %1's hand + nominative, male owner + + + + + of her hand + genitive, female owner + + + + of %1's hand - genitive - + genitive, female owner + - his hand - accusative - + of his hand + genitive, male owner + + of %1's hand + genitive, male owner + + + + + her hand + accusative, female owner + + + + %1's hand - accusative - + accusative, female owner + - - his library - nominative - + + his hand + accusative, male owner + - + + %1's hand + accusative, male owner + + + + + her library + nominative, female owner + + + + %1's library - nominative - + nominative, female owner + - of his library - genitive - + his library + nominative, male owner + + %1's library + nominative, male owner + + + + + of her library + genitive, female owner + + + + of %1's library - genitive - + genitive, female owner + - his library - accusative - + of his library + genitive, male owner + + of %1's library + genitive, male owner + + + + + her library + accusative, female owner + + + + %1's library - accusative - + accusative, female owner + - - his graveyard - nominative - + + his library + accusative, male owner + - + + %1's library + accusative, male owner + + + + + her graveyard + nominative, female owner + + + + %1's graveyard - nominative - + nominative, female owner + - of his graveyard - genitive - + his graveyard + nominative, male owner + + %1's graveyard + nominative, male owner + + + + + of her graveyard + genitive, female owner + + + + of %1's graveyard - genitive - + genitive, female owner + - his graveyard - accusative - + of his graveyard + genitive, male owner + + of %1's graveyard + genitive, male owner + + + + + her graveyard + accusative, female owner + + + + %1's graveyard - accusative - + accusative, female owner + - - his exile - nominative - + + his graveyard + accusative, male owner + - + + %1's graveyard + accusative, male owner + + + + + her exile + nominative, female owner + + + + %1's exile - nominative - + nominative, female owner + - of his exile - genitive - + his exile + nominative, male owner + + %1's exile + nominative, male owner + + + + + of her exile + genitive, female owner + + + + of %1's exile - genitive - + genitive, female owner + - his exile - accusative - + of his exile + genitive, male owner + + of %1's exile + genitive, male owner + + + + + her exile + accusative, female owner + + + + %1's exile - accusative - + accusative, female owner + - - his sideboard - nominative - + + his exile + accusative, male owner + - + + %1's exile + accusative, male owner + + + + + her sideboard + nominative, female owner + + + + %1's sideboard - nominative - + nominative, female owner + - of his sideboard - genitive - + his sideboard + nominative, male owner + + %1's sideboard + nominative, male owner + + + + + of her sideboard + genitive, female owner + + + + of %1's sideboard - genitive - + genitive, female owner + - his sideboard - accusative - + of his sideboard + genitive, male owner + + of %1's sideboard + genitive, male owner + + + + + her sideboard + accusative, female owner + + + + %1's sideboard - accusative - + accusative, female owner + + + + + his sideboard + accusative, male owner + + + + + %1's sideboard + accusative, male owner + @@ -1484,210 +1664,265 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. + %1 shuffles %2. + + + + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). - + %1 undoes his last draw. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). - + + %1 undoes her last draw (%2). + + + + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + + the bottom card of her library + + + + from the bottom of his library - + + from the bottom of her library + + + + the top card of his library - + + the top card of her library + + + + from the top of his library - + + from the top of her library + + + + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. - + + %1 puts %2%3 on top of her library. + + + + %1 puts %2%3 into his library at position %4. - + + %1 puts %2%3 into her library at position %4. + + + + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1704,274 +1939,279 @@ Local version is %1, remote version is %2. - + red - + yellow - + green - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. - + %1 takes a mulligan to %n. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). - + %1 removes %n %2 counter(s) from %3 (now %4). - + + her permanents + + + + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - - %1 shuffles his library. - - - - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2889,42 +3129,51 @@ Please enter a name: UserInfoBox - + User information ユーザー情報 - + Real name: 本名: - + + Gender: + + + + Location: 現在地: - + User level: ユーザーレベル: - + Administrator 管理者 - - Judge - ジャッジ + + Moderator + - + Judge + ジャッジ + + + Registered user 登録ユーザー - + Unregistered user 未登録ユーザー diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 7660e1032..bdaa82631 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -393,183 +393,363 @@ CardZone - - his hand - nominative + + her hand + nominative, female owner - + %1's hand - nominative + nominative, female owner - of his hand - genitive + his hand + nominative, male owner + %1's hand + nominative, male owner + + + + + of her hand + genitive, female owner + + + + of %1's hand - genitive + genitive, female owner - his hand - accusative + of his hand + genitive, male owner + of %1's hand + genitive, male owner + + + + + her hand + accusative, female owner + + + + %1's hand - accusative + accusative, female owner - - his library - nominative + + his hand + accusative, male owner - + + %1's hand + accusative, male owner + + + + + her library + nominative, female owner + + + + %1's library - nominative + nominative, female owner - of his library - genitive + his library + nominative, male owner + %1's library + nominative, male owner + + + + + of her library + genitive, female owner + + + + of %1's library - genitive + genitive, female owner - his library - accusative + of his library + genitive, male owner + of %1's library + genitive, male owner + + + + + her library + accusative, female owner + + + + %1's library - accusative + accusative, female owner - - his graveyard - nominative + + his library + accusative, male owner - + + %1's library + accusative, male owner + + + + + her graveyard + nominative, female owner + + + + %1's graveyard - nominative + nominative, female owner - of his graveyard - genitive + his graveyard + nominative, male owner + %1's graveyard + nominative, male owner + + + + + of her graveyard + genitive, female owner + + + + of %1's graveyard - genitive + genitive, female owner - his graveyard - accusative + of his graveyard + genitive, male owner + of %1's graveyard + genitive, male owner + + + + + her graveyard + accusative, female owner + + + + %1's graveyard - accusative + accusative, female owner - - his exile - nominative + + his graveyard + accusative, male owner - + + %1's graveyard + accusative, male owner + + + + + her exile + nominative, female owner + + + + %1's exile - nominative + nominative, female owner - of his exile - genitive + his exile + nominative, male owner + %1's exile + nominative, male owner + + + + + of her exile + genitive, female owner + + + + of %1's exile - genitive + genitive, female owner - his exile - accusative + of his exile + genitive, male owner + of %1's exile + genitive, male owner + + + + + her exile + accusative, female owner + + + + %1's exile - accusative + accusative, female owner - - his sideboard - nominative + + his exile + accusative, male owner - + + %1's exile + accusative, male owner + + + + + her sideboard + nominative, female owner + + + + %1's sideboard - nominative + nominative, female owner - of his sideboard - genitive + his sideboard + nominative, male owner + %1's sideboard + nominative, male owner + + + + + of her sideboard + genitive, female owner + + + + of %1's sideboard - genitive + genitive, female owner - his sideboard - accusative + of his sideboard + genitive, male owner + of %1's sideboard + genitive, male owner + + + + + her sideboard + accusative, female owner + + + + %1's sideboard - accusative + accusative, female owner + + + + + his sideboard + accusative, male owner + + + + + %1's sideboard + accusative, male owner @@ -1427,107 +1607,107 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Connected. - + Disconnected from server. - + Invalid password. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - - %1 shuffles his library. + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1536,138 +1716,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). - + + %1 undoes her last draw (%2). + + + + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + + the bottom card of her library + + + + from the bottom of his library - - the top card of his library - - - - - from the top of his library + + from the bottom of her library + the top card of his library + + + + + the top card of her library + + + + + from the top of his library + + + + + from the top of her library + + + + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. - - %1 puts %2%3 into his library at position %4. - - - - - %1 moves %2%3 to sideboard. + + %1 puts %2%3 on top of her library. + %1 puts %2%3 into his library at position %4. + + + + + %1 puts %2%3 into her library at position %4. + + + + + %1 moves %2%3 to sideboard. + + + + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1676,52 +1906,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1730,7 +1965,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -1739,7 +1974,7 @@ Local version is %1, remote version is %2. - + red @@ -1748,7 +1983,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1757,7 +1992,7 @@ Local version is %1, remote version is %2. - + green @@ -1766,157 +2001,162 @@ Local version is %1, remote version is %2. - + his permanents - + + her permanents + + + + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2788,42 +3028,47 @@ Please enter a name: UserInfoBox - + User information - + Real name: - + + Gender: + + + + Location: - + User level: - + Administrator - - Judge + + Moderator - + Registered user - + Unregistered user diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index b172d9a84..c0549f8d1 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -401,184 +401,514 @@ CardZone - his hand nominative - sua mão + sua mão - %1's hand nominative - mão de %1 + mão de %1 - of his hand genitive - da sua mão + da sua mão + + + of %1's hand + genitive + da mão de %1 + + + his hand + accusative + sua mão + + + %1's hand + accusative + mão de %1 + + + his library + nominative + seu grimório + + + %1's library + nominative + grimório de %1 + + + of his library + genitive + do seu grimório + + + of %1's library + genitive + do grimório de %1 + + + his library + accusative + seu grimório + + + %1's library + accusative + grimório de %1 - of %1's hand - genitive - da mão de %1 + her hand + nominative, female owner + - - his hand - accusative - sua mão - - - + %1's hand - accusative - mão de %1 + nominative, female owner + mão de %1 - - his library - nominative - seu grimório + + his hand + nominative, male owner + sua mão - + + %1's hand + nominative, male owner + mão de %1 + + + + of her hand + genitive, female owner + + + + + of %1's hand + genitive, female owner + da mão de %1 + + + + of his hand + genitive, male owner + da sua mão + + + + of %1's hand + genitive, male owner + da mão de %1 + + + + her hand + accusative, female owner + + + + + %1's hand + accusative, female owner + mão de %1 + + + + his hand + accusative, male owner + sua mão + + + + %1's hand + accusative, male owner + mão de %1 + + + + her library + nominative, female owner + + + + %1's library - nominative - grimório de %1 + nominative, female owner + grimório de %1 - of his library - genitive - do seu grimório + his library + nominative, male owner + seu grimório + %1's library + nominative, male owner + grimório de %1 + + + + of her library + genitive, female owner + + + + of %1's library - genitive - do grimório de %1 + genitive, female owner + do grimório de %1 - his library - accusative - seu grimório + of his library + genitive, male owner + do seu grimório + of %1's library + genitive, male owner + do grimório de %1 + + + + her library + accusative, female owner + + + + %1's library - accusative - grimório de %1 + accusative, female owner + grimório de %1 - - his graveyard - nominative - seu cemitério + + his library + accusative, male owner + seu grimório - - %1's graveyard - nominative - cemitério de %1 + + %1's library + accusative, male owner + grimório de %1 + her graveyard + nominative, female owner + + + + + %1's graveyard + nominative, female owner + cemitério de %1 + + + + his graveyard + nominative, male owner + seu cemitério + + + + %1's graveyard + nominative, male owner + cemitério de %1 + + + + of her graveyard + genitive, female owner + + + + + of %1's graveyard + genitive, female owner + do cemitério de %1 + + + + of his graveyard + genitive, male owner + do seu cemitério + + + + of %1's graveyard + genitive, male owner + do cemitério de %1 + + + + her graveyard + accusative, female owner + + + + + %1's graveyard + accusative, female owner + cemitério de %1 + + + + his graveyard + accusative, male owner + seu cemitério + + + + %1's graveyard + accusative, male owner + cemitério de %1 + + + + her exile + nominative, female owner + + + + + %1's exile + nominative, female owner + exílio de %1 + + + + his exile + nominative, male owner + seu exílio + + + + %1's exile + nominative, male owner + exílio de %1 + + + + of her exile + genitive, female owner + + + + + of %1's exile + genitive, female owner + do exílio de %1 + + + + of his exile + genitive, male owner + do seu exílio + + + + of %1's exile + genitive, male owner + do exílio de %1 + + + + her exile + accusative, female owner + + + + + %1's exile + accusative, female owner + exílio de %1 + + + + his exile + accusative, male owner + seu exílio + + + + %1's exile + accusative, male owner + exílio de %1 + + + + her sideboard + nominative, female owner + + + + + %1's sideboard + nominative, female owner + sideboard de %1 + + + + his sideboard + nominative, male owner + seu sideboard + + + + %1's sideboard + nominative, male owner + sideboard de %1 + + + + of her sideboard + genitive, female owner + + + + + of %1's sideboard + genitive, female owner + do sideboard de %1 + + + + of his sideboard + genitive, male owner + do seu sideboard + + + + of %1's sideboard + genitive, male owner + do sideboard de %1 + + + + her sideboard + accusative, female owner + + + + + %1's sideboard + accusative, female owner + sideboard de %1 + + + + his sideboard + accusative, male owner + seu sideboard + + + + %1's sideboard + accusative, male owner + sideboard de %1 + + + his graveyard + nominative + seu cemitério + + + %1's graveyard + nominative + cemitério de %1 + + of his graveyard genitive - do seu cemitério + do seu cemitério - of %1's graveyard genitive - do cemitério de %1 + do cemitério de %1 - his graveyard accusative - seu cemitério + seu cemitério - %1's graveyard accusative - cemitério de %1 + cemitério de %1 - his exile nominative - seu exílio + seu exílio - %1's exile nominative - exílio de %1 + exílio de %1 - of his exile genitive - do seu exílio + do seu exílio - of %1's exile genitive - do exílio de %1 + do exílio de %1 - his exile accusative - seu exílio + seu exílio - %1's exile accusative - exílio de %1 + exílio de %1 - his sideboard nominative - seu sideboard + seu sideboard - %1's sideboard nominative - sideboard de %1 + sideboard de %1 - of his sideboard genitive - do seu sideboard + do seu sideboard - of %1's sideboard genitive - do sideboard de %1 + do sideboard de %1 - his sideboard accusative - seu sideboard + seu sideboard - %1's sideboard accusative - sideboard de %1 + sideboard de %1 @@ -1508,52 +1838,57 @@ A versão local é %1 e a versão remota é %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado do servidor. - + Invalid password. Senha incorreta. - + Protocol error. Erro de protocolo. - + The game has been closed. O jogo foi fechado. - + %1 is now watching the game. %1 está assistindo o jogo agora. - + %1 is not watching the game any more. %1 não está mais assistindo o jogo. - + %1 is not ready to start the game any more. %1 não está mais pronto para começar o jogo. + %1 shuffles %2. + + + + %1 rolls a %2 with a %3-sided die. %1 tirou um %2 com um dado de %3 lados. - + %1 draws %n card(s). %1 compra %n card. @@ -1561,158 +1896,208 @@ A versão local é %1 e a versão remota é %2. - + %1 undoes his last draw. %1 desfaz sua última compra. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). %1 desfaz sua última compra (%2). - + + %1 undoes her last draw (%2). + + + + from table vindo do campo de batalha - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library o card do fundo do seu grimório - + + the bottom card of her library + + + + from the bottom of his library vindo do fundo do seu grimório - + + from the bottom of her library + + + + the top card of his library o card do topo do seu grimório - + + the top card of her library + + + + from the top of his library vindo do topo do seu grimório - + + from the top of her library + + + + from library vindo do grimório - + from sideboard vindo do sideboard - + from the stack vindo da pilha - + %1 gives %2 control over %3. %1 dá controle para %2 sobre %3. - + %1 puts %2 into play tapped%3. %1 põe %2 em jogo virado%3. - + %1 puts %2 into play%3. %1 põe %2 no campo de batalha %3. - + %1 puts %2%3 into graveyard. %1 põe %2 no cemitério%3. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2 para a mão%3. - + %1 puts %2%3 into his library. %1 põe %2 no seu grimório%3. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. %1 põe %2 no fundo do seu grimório%3. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. %1 põe %2 no topo do seu grimório%3. - + + %1 puts %2%3 on top of her library. + + + + %1 puts %2%3 into his library at position %4. %1 põe %2 no seu grimório na posição %4%3. - + + %1 puts %2%3 into her library at position %4. + + + + %1 moves %2%3 to sideboard. %1 move %2 para o sideboard%3. - + %1 plays %2%3. %1 põe %2 na pilha%3. - - + + a card um card - + %1 flips %2 face-down. %1 vira %2 para baixo. - + %1 flips %2 face-up. %1 vira %2 para cima. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 aponta para %5 de %4 com %3 de %2. @@ -1731,7 +2116,7 @@ A versão local é %1 e a versão remota é %2. - + red vermelho @@ -1739,7 +2124,7 @@ A versão local é %1 e a versão remota é %2. - + yellow amarelo @@ -1747,7 +2132,7 @@ A versão local é %1 e a versão remota é %2. - + green verde @@ -1755,72 +2140,72 @@ A versão local é %1 e a versão remota é %2. - + %1 sets counter %2 to %3 (%4%5). %1 altera o marcador %2 para %3 (%4%5). - + %1 sets PT of %2 to %3. %1 altera o P/R de %2 para %3. - + %1 sets annotation of %2 to %3. %1 altera a nota de %2 para%3. - + %1 is looking at the top %2 cards %3. %1 está olhando para os %2 cards do topo %3. - + The game has started. O jogo começou. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + You have joined game #%1. Você entrou no jogo nº %1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 saiu do jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck nº %2. - + %1 is ready to start the game. %1 está pronto para começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. @@ -1833,22 +2218,22 @@ A versão local é %1 e a versão remota é %2. %1 compra %2 cards. - + %1 destroys %2. %1 destrói %2. - + %1 creates token: %2%3. %1 cria a ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta para %4 com %3 de %2 . - + %1 places %n %2 counter(s) on %3 (now %4). %1 põe %n marcador %2 em %3 (agora %4). @@ -1856,7 +2241,7 @@ A versão local é %1 e a versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 tira %n marcador %2 em %3 (agora %4). @@ -1864,47 +2249,46 @@ A versão local é %1 e a versão remota é %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está olhando para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 para %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase final - + It is now %1's turn. Agora é o turno de %1. - %1 shuffles his library. - %1 embaralha o seu grimório. + %1 embaralha o seu grimório. - + %1 takes a mulligan to %n. @@ -1912,107 +2296,117 @@ A versão local é %1 e a versão remota é %2. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + + her permanents + + + + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3. para %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 para %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step etapa de desvirar - + upkeep step etapa de manutenção - + draw step etapa de compra - + first main phase primeira fase principal - + beginning of combat step etapa de início de combate - + declare attackers step etapa de declaracão de atacantes - + declare blockers step etapa de declaração de bloqueadores - + combat damage step etapa de dano de combate - + end of combat step etapa de fim de combate - + second main phase segunda fase principal - + It is now the %1. Agora é a %1. - + taps vira - + untaps desvira - + %1 sets %2 to not untap normally. %1 define que %2 não desvira normalmente. - + %1 sets %2 to untap normally. %1 define que %2 desvira normalmente. - + his permanents as suas permanentes @@ -2939,42 +3333,51 @@ Por favor, entre um nome: UserInfoBox - + User information Informação do usuário - + Real name: Nome real: - + + Gender: + + + + Location: Localização: - + User level: Nível do usuário: - + Administrator Administrador - - Judge - Juiz + + Moderator + - + Judge + Juiz + + + Registered user Usuário registrado - + Unregistered user Usuário não registrado diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 503dea8cf..9b7dac82c 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -401,184 +401,514 @@ CardZone - his hand nominative - sua mão + sua mão - %1's hand nominative - mão de %1 + mão de %1 - of his hand genitive - da sua mão + da sua mão + + + of %1's hand + genitive + da mão de %1 + + + his hand + accusative + sua mão + + + %1's hand + accusative + mão de %1 + + + his library + nominative + seu grimório + + + %1's library + nominative + grimório de %1 + + + of his library + genitive + do seu grimório + + + of %1's library + genitive + do grimório de %1 + + + his library + accusative + seu grimório + + + %1's library + accusative + grimório de %1 - of %1's hand - genitive - da mão de %1 + her hand + nominative, female owner + - - his hand - accusative - sua mão - - - + %1's hand - accusative - mão de %1 + nominative, female owner + mão de %1 - - his library - nominative - seu grimório + + his hand + nominative, male owner + sua mão - + + %1's hand + nominative, male owner + mão de %1 + + + + of her hand + genitive, female owner + + + + + of %1's hand + genitive, female owner + da mão de %1 + + + + of his hand + genitive, male owner + da sua mão + + + + of %1's hand + genitive, male owner + da mão de %1 + + + + her hand + accusative, female owner + + + + + %1's hand + accusative, female owner + mão de %1 + + + + his hand + accusative, male owner + sua mão + + + + %1's hand + accusative, male owner + mão de %1 + + + + her library + nominative, female owner + + + + %1's library - nominative - grimório de %1 + nominative, female owner + grimório de %1 - of his library - genitive - do seu grimório + his library + nominative, male owner + seu grimório + %1's library + nominative, male owner + grimório de %1 + + + + of her library + genitive, female owner + + + + of %1's library - genitive - do grimório de %1 + genitive, female owner + do grimório de %1 - his library - accusative - seu grimório + of his library + genitive, male owner + do seu grimório + of %1's library + genitive, male owner + do grimório de %1 + + + + her library + accusative, female owner + + + + %1's library - accusative - grimório de %1 + accusative, female owner + grimório de %1 - - his graveyard - nominative - seu cemitério + + his library + accusative, male owner + seu grimório - - %1's graveyard - nominative - cemitério de %1 + + %1's library + accusative, male owner + grimório de %1 + her graveyard + nominative, female owner + + + + + %1's graveyard + nominative, female owner + + + + + his graveyard + nominative, male owner + seu cemitério + + + + %1's graveyard + nominative, male owner + + + + + of her graveyard + genitive, female owner + + + + + of %1's graveyard + genitive, female owner + do cemitério de %1 + + + + of his graveyard + genitive, male owner + do seu cemitério + + + + of %1's graveyard + genitive, male owner + do cemitério de %1 + + + + her graveyard + accusative, female owner + + + + + %1's graveyard + accusative, female owner + + + + + his graveyard + accusative, male owner + seu cemitério + + + + %1's graveyard + accusative, male owner + + + + + her exile + nominative, female owner + + + + + %1's exile + nominative, female owner + exílio de %1 + + + + his exile + nominative, male owner + seu exílio + + + + %1's exile + nominative, male owner + exílio de %1 + + + + of her exile + genitive, female owner + + + + + of %1's exile + genitive, female owner + do exílio de %1 + + + + of his exile + genitive, male owner + do seu exílio + + + + of %1's exile + genitive, male owner + do exílio de %1 + + + + her exile + accusative, female owner + + + + + %1's exile + accusative, female owner + exílio de %1 + + + + his exile + accusative, male owner + seu exílio + + + + %1's exile + accusative, male owner + exílio de %1 + + + + her sideboard + nominative, female owner + + + + + %1's sideboard + nominative, female owner + sideboard de %1 + + + + his sideboard + nominative, male owner + seu sideboard + + + + %1's sideboard + nominative, male owner + sideboard de %1 + + + + of her sideboard + genitive, female owner + + + + + of %1's sideboard + genitive, female owner + do sideboard de %1 + + + + of his sideboard + genitive, male owner + do seu sideboard + + + + of %1's sideboard + genitive, male owner + do sideboard de %1 + + + + her sideboard + accusative, female owner + + + + + %1's sideboard + accusative, female owner + sideboard de %1 + + + + his sideboard + accusative, male owner + seu sideboard + + + + %1's sideboard + accusative, male owner + sideboard de %1 + + + his graveyard + nominative + seu cemitério + + + %1's graveyard + nominative + cemitério de %1 + + of his graveyard genitive - do seu cemitério + do seu cemitério - of %1's graveyard genitive - do cemitério de %1 + do cemitério de %1 - his graveyard accusative - seu cemitério + seu cemitério - %1's graveyard accusative - cemitéro de %1 + cemitéro de %1 - his exile nominative - seu exílio + seu exílio - %1's exile nominative - exílio de %1 + exílio de %1 - of his exile genitive - do seu exílio + do seu exílio - of %1's exile genitive - do exílio de %1 + do exílio de %1 - his exile accusative - seu exílio + seu exílio - %1's exile accusative - exílio de %1 + exílio de %1 - his sideboard nominative - seu sideboard + seu sideboard - %1's sideboard nominative - sideboard de %1 + sideboard de %1 - of his sideboard genitive - do seu sideboard + do seu sideboard - of %1's sideboard genitive - do sideboard de %1 + do sideboard de %1 - his sideboard accusative - seu sideboard + seu sideboard - %1's sideboard accusative - sideboard de %1 + sideboard de %1 @@ -1512,102 +1842,101 @@ Versão local é %1, versão remota é %2. MessageLogWidget - + Connecting to %1... Ligando a %1... - + Connected. Ligado. - + Disconnected from server. Desligado do servidor. - + Invalid password. Password incorrecto. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + Protocol error. Erro de protocolo. - + You have joined game #%1. Você entrou no jogo #%1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 abandonou o jogo. - + The game has been closed. Este jogo foi encerrado. - + %1 is now watching the game. %1 está agora a ver o jogo. - + %1 is not watching the game any more. %1 já não está a ver o jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck #%2. - + %1 is ready to start the game. %1 está pronto a começar o jogo. - + %1 is not ready to start the game any more. %1 já não está pronto a começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. - + The game has started. O jogo começou. - %1 shuffles his library. - %1 baralha o grimório. + %1 baralha o grimório. - + %1 rolls a %2 with a %3-sided die. %1 obteve %2 com um dado de %3 faces. @@ -1620,117 +1949,157 @@ Versão local é %1, versão remota é %2. %1 compra %2 cartas. - + from table vindo da mesa - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library a carta do fundo do seu grimório - + + the bottom card of her library + + + + from the bottom of his library do fundo do seu grimório - + + from the bottom of her library + + + + the top card of his library a carta do topo do seu grimório - + + the top card of her library + + + + from the top of his library do topo do seu grimório - + + from the top of her library + + + + from library do grimório - + from sideboard do sideboard - + from the stack da pilha - + %1 puts %2 into play tapped%3. %1 coloca %2 em jogo virado(a)%3. - + %1 puts %2 into play%3. %1 coloca %2 em jogo %3. - + %1 puts %2%3 into graveyard. %1 coloca %2%3 no cemitério. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2%3 para a mão. - + %1 puts %2%3 into his library. %1 coloca %2%3 no seu grimório. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. %1 coloca %2%3 no fundo do seu grimório. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. %1 coloca %2%3 no topo do seu grimório. - + + %1 puts %2%3 on top of her library. + + + + %1 puts %2%3 into his library at position %4. %1 coloca %2%3 no seu grimório na posição %4. - + + %1 puts %2%3 into her library at position %4. + + + + %1 moves %2%3 to sideboard. %1 move %2%3 para o sideboard. - + %1 plays %2%3. %1 joga %2%3. - + %1 takes a mulligan to %n. @@ -1738,12 +2107,17 @@ Versão local é %1, versão remota é %2. - + %1 draws his initial hand. + + + %1 draws her initial hand. + + - + %1 places %n %2 counter(s) on %3 (now %4). %1 coloca %n %2 marcador em %3 (agora com %4). @@ -1751,7 +2125,7 @@ Versão local é %1, versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remove %n %2 marcador de %3 (agora com %4). @@ -1759,13 +2133,18 @@ Versão local é %1, versão remota é %2. - - + + a card uma carta + + + %1 shuffles %2. + + - + %1 draws %n card(s). %1 compra %n carta. @@ -1773,57 +2152,67 @@ Versão local é %1, versão remota é %2. - + %1 undoes his last draw. %1 desfaz a sua última compra. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). %1 desfaz a sua última compra (%2). - + + %1 undoes her last draw (%2). + + + + %1 gives %2 control over %3. %1 dá controlo sobre %3 a %2. - + %1 flips %2 face-down. %1 volta a face de %2 para baixo. - + %1 flips %2 face-up. %1 volta a face de %2 para cima. - + %1 destroys %2. %1 destrói %2. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 creates token: %2%3. %1 cria ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta de %3 de %2 para %4. - + %1 points from %2's %3 to %4's %5. %1 aponta de %3 de %2 para %5 de %4. @@ -1842,7 +2231,7 @@ Versão local é %1, versão remota é %2. - + red vermelho @@ -1850,7 +2239,7 @@ Versão local é %1, versão remota é %2. - + yellow amarelo @@ -1858,7 +2247,7 @@ Versão local é %1, versão remota é %2. - + green verde @@ -1866,157 +2255,162 @@ Versão local é %1, versão remota é %2. - + his permanents as suas permanentes - + + her permanents + + + + %1 %2 %3. %1 %2 %3. - + taps vira - + untaps desvira - + %1 sets counter %2 to %3 (%4%5). %1 altera o número de marcadores %2 para %3(%4%5). - + %1 sets %2 to not untap normally. %1 define %2 para não desvirar normalmente. - + %1 sets %2 to untap normally. %1 define %2 para desvirar normalmente. - + %1 sets PT of %2 to %3. %1 define o P/R de %2 como %3. - + %1 sets annotation of %2 to %3. %1 coloca uma nota de %2 em%3. - + %1 is looking at the top %2 cards %3. %1 está a olhar para as %2 cartas do topo %3. - + %1 is looking at %2. %1 está a olhar para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + %1 randomly reveals %2%3 to %4. %1 revela aleatoreamente %2%3. a %4. - + %1 randomly reveals %2%3. %1 revela aleatoreamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + It is now %1's turn. É agora o turno de %1. - + untap step Etapa de Desvirar - + upkeep step Etapa de Manutenção - + draw step Etapa de Compra - + first main phase 1ª Fase Principal (pré-combate) - + beginning of combat step Etapa de Início de Combate - + declare attackers step Etapa de Declaração de Atacantes - + declare blockers step Etapa de Declaração de Bloqueadores - + combat damage step Etapa de Dano de Combate - + end of combat step Etapa de Fim de Combate - + second main phase 2ª Fase Principal (pós-combate) - + ending phase Fase Final - + It is now the %1. É agora a %1. @@ -2943,42 +3337,51 @@ Por favor introduza um nome: UserInfoBox - + User information Informação do utilizador - + Real name: Nome real: - + + Gender: + + + + Location: Localização: - + User level: Nível de utilizador: - + Administrator Administrador - - Judge - Juiz + + Moderator + - + Judge + Juiz + + + Registered user Utilizador registado - + Unregistered user Utilizador não registado diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index c1a992642..1f5e95e59 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -397,184 +397,514 @@ CardZone - his hand nominative - его рука + его рука - %1's hand nominative - рука %1-го игрока + рука %1-го игрока - of his hand genitive - его руки + его руки + + + of %1's hand + genitive + руки %1-го игрока + + + his hand + accusative + его руку + + + %1's hand + accusative + руку %1-го игрока + + + his library + nominative + его библиотека + + + %1's library + nominative + библиотека %1-го игрока + + + of his library + genitive + его библиотеки + + + of %1's library + genitive + библиотеки %1-го игрока + + + his library + accusative + его библиотеку + + + %1's library + accusative + библиотеку %1-го игрока - of %1's hand - genitive - руки %1-го игрока + her hand + nominative, female owner + - - his hand - accusative - его руку - - - + %1's hand - accusative - руку %1-го игрока + nominative, female owner + - - his library - nominative - его библиотека + + his hand + nominative, male owner + - + + %1's hand + nominative, male owner + + + + + of her hand + genitive, female owner + + + + + of %1's hand + genitive, female owner + руки %1-го игрока + + + + of his hand + genitive, male owner + его руки + + + + of %1's hand + genitive, male owner + руки %1-го игрока + + + + her hand + accusative, female owner + + + + + %1's hand + accusative, female owner + + + + + his hand + accusative, male owner + + + + + %1's hand + accusative, male owner + + + + + her library + nominative, female owner + + + + %1's library - nominative - библиотека %1-го игрока + nominative, female owner + - of his library - genitive - его библиотеки + his library + nominative, male owner + + %1's library + nominative, male owner + + + + + of her library + genitive, female owner + + + + of %1's library - genitive - библиотеки %1-го игрока + genitive, female owner + библиотеки %1-го игрока - his library - accusative - его библиотеку + of his library + genitive, male owner + его библиотеки + of %1's library + genitive, male owner + библиотеки %1-го игрока + + + + her library + accusative, female owner + + + + %1's library - accusative - библиотеку %1-го игрока + accusative, female owner + - - his graveyard - nominative - его кладбище + + his library + accusative, male owner + - - %1's graveyard - nominative - кладбище %1-го игрока + + %1's library + accusative, male owner + + her graveyard + nominative, female owner + + + + + %1's graveyard + nominative, female owner + кладбище %1-го игрока + + + + his graveyard + nominative, male owner + его кладбище + + + + %1's graveyard + nominative, male owner + кладбище %1-го игрока + + + + of her graveyard + genitive, female owner + + + + + of %1's graveyard + genitive, female owner + кладбища %1-го игрока + + + + of his graveyard + genitive, male owner + его кладбища + + + + of %1's graveyard + genitive, male owner + кладбища %1-го игрока + + + + her graveyard + accusative, female owner + + + + + %1's graveyard + accusative, female owner + кладбище %1-го игрока + + + + his graveyard + accusative, male owner + его кладбище + + + + %1's graveyard + accusative, male owner + кладбище %1-го игрока + + + + her exile + nominative, female owner + + + + + %1's exile + nominative, female owner + изгнание %1-го игрока + + + + his exile + nominative, male owner + его изгнание + + + + %1's exile + nominative, male owner + изгнание %1-го игрока + + + + of her exile + genitive, female owner + + + + + of %1's exile + genitive, female owner + изгнания %1-го игрока + + + + of his exile + genitive, male owner + его изгнания + + + + of %1's exile + genitive, male owner + изгнания %1-го игрока + + + + her exile + accusative, female owner + + + + + %1's exile + accusative, female owner + изгнание %1-го игрока + + + + his exile + accusative, male owner + его изгнание + + + + %1's exile + accusative, male owner + изгнание %1-го игрока + + + + her sideboard + nominative, female owner + + + + + %1's sideboard + nominative, female owner + сайд %1-го игрока + + + + his sideboard + nominative, male owner + его сайд + + + + %1's sideboard + nominative, male owner + сайд %1-го игрока + + + + of her sideboard + genitive, female owner + + + + + of %1's sideboard + genitive, female owner + сайда %1-го игрока + + + + of his sideboard + genitive, male owner + его сайда + + + + of %1's sideboard + genitive, male owner + сайда %1-го игрока + + + + her sideboard + accusative, female owner + + + + + %1's sideboard + accusative, female owner + сайд %1-го игрока + + + + his sideboard + accusative, male owner + его сайд + + + + %1's sideboard + accusative, male owner + сайд %1-го игрока + + + his graveyard + nominative + его кладбище + + + %1's graveyard + nominative + кладбище %1-го игрока + + of his graveyard genitive - его кладбища + его кладбища - of %1's graveyard genitive - кладбища %1-го игрока + кладбища %1-го игрока - his graveyard accusative - его кладбище + его кладбище - %1's graveyard accusative - кладбище %1-го игрока + кладбище %1-го игрока - his exile nominative - его изгнание + его изгнание - %1's exile nominative - изгнание %1-го игрока + изгнание %1-го игрока - of his exile genitive - его изгнания + его изгнания - of %1's exile genitive - изгнания %1-го игрока + изгнания %1-го игрока - his exile accusative - его изгнание + его изгнание - %1's exile accusative - изгнание %1-го игрока + изгнание %1-го игрока - his sideboard nominative - его сайд + его сайд - %1's sideboard nominative - сайд %1-го игрока + сайд %1-го игрока - of his sideboard genitive - его сайда + его сайда - of %1's sideboard genitive - сайда %1-го игрока + сайда %1-го игрока - his sideboard accusative - его сайд + его сайд - %1's sideboard accusative - сайд %1-го игрока + сайд %1-го игрока @@ -1435,102 +1765,101 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... Подключение к %1... - + Connected. Подключено. - + Disconnected from server. Нет соединения с сервером. - + Invalid password. Неверный пароль. - + Protocol version mismatch. Client: %1, Server: %2 Несовпадение версий. Клиент: %1, Сервер: %2 - + Protocol error. Ошибка протокола. - + You have joined game #%1. Вы присоединились к игре #%1. - + %1 has joined the game. %1 присоединился к игре. - + %1 has left the game. %1 покиул игру. - + The game has been closed. Игра закрыта. - + %1 is now watching the game. %1 вошел как зритель. - + %1 is not watching the game any more. %1 покинул зрительскую ложу. - + %1 has loaded a local deck. %1 загрузил колоду с диска. - + %1 has loaded deck #%2. %1 загрузил колоду #%2. - + %1 is ready to start the game. %1 готов начать игру. - + %1 is not ready to start the game any more. %1 все еще не готов. - + %1 has conceded the game. %1 решил сдаться. - + The game has started. Игра началась. - %1 shuffles his library. - %1 размешивает библиотеку. + %1 размешивает библиотеку. - + %1 rolls a %2 with a %3-sided die. %1 выкинул %2 / %3. @@ -1543,168 +1872,168 @@ Local version is %1, remote version is %2. %1 взял %2 карт. - + %1 undoes his last draw. %1 отменил последнее взятие. - + %1 undoes his last draw (%2). %1 отменил %2 последних взятий. - + from table с поля битвы - + from graveyard из кладбища - + from exile из изгнания - + from hand из руки - + the bottom card of his library нижнюю карту своей библиотеки - + from the bottom of his library со дна своей библиотеки - + the top card of his library верхнюю карту своей библиотеки - + from the top of his library с верха своей библиотеки - + from library из библиотеки - + from sideboard из сайда - + from the stack из стека - - + + a card карту - + %1 gives %2 control over %3. %1 передает %2 контроль над %3. - + %1 puts %2 into play%3. %1 поместил %2 на поле битвы %3. - + %1 puts %2%3 into graveyard. %1 поместил %2%3 на кладбище. - + %1 exiles %2%3. %1 изгоняет %2%3. - + %1 moves %2%3 to hand. %1 поместил %2%3 в руку. - + %1 puts %2%3 into his library. %1 поместил %2%3 в свою библиотеку. - + %1 puts %2%3 on bottom of his library. %1 поместил %2%3 на дно своей библиотеки. - + %1 puts %2%3 on top of his library. %1 поместил %2%3 на верх своей библиотеки. - + %1 puts %2%3 into his library at position %4. %1 поместил %2%3 в свою библиотеку %4 сверху. - + %1 moves %2%3 to sideboard. %1 поместил %2%3 в сайд. - + %1 plays %2%3. %1 разыгрывает %2%3. - + %1 flips %2 face-down. %1 перевернул %2 лицом вниз. - + %1 flips %2 face-up. %1 перевернул %2 лицом вверх. - + %1 destroys %2. %1 уничтожил %2. - + %1 attaches %2 to %3's %4. %1 присоединил %2 к %4 игрока %3. - + %1 unattaches %2. %1 отсоединил %2. - + %1 creates token: %2%3. %1 создал фишку: %2%3. - + %1 points from %2's %3 to %4. %1 указывает с %3 контролируемого %2 на %4. - + %1 points from %2's %3 to %4's %5. %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. @@ -1724,8 +2053,13 @@ Local version is %1, remote version is %2. %1 удалил %n жетоны (%2) с %3 (теперь %4). + + + %1 shuffles %2. + + - + %1 draws %n card(s). %1 взял %n карту. @@ -1734,12 +2068,62 @@ Local version is %1, remote version is %2. - + + %1 undoes her last draw. + + + + + %1 undoes her last draw (%2). + + + + + the bottom card of her library + + + + + from the bottom of her library + + + + + the top card of her library + + + + + from the top of her library + + + + %1 puts %2 into play tapped%3. %1 положил %2 повернутым на поле битвы%3. + + + %1 puts %2%3 into her library. + + + + + %1 puts %2%3 on bottom of her library. + + + + + %1 puts %2%3 on top of her library. + + + + + %1 puts %2%3 into her library at position %4. + + - + %1 takes a mulligan to %n. @@ -1748,12 +2132,17 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. + + + %1 draws her initial hand. + + - + %1 places %n %2 counter(s) on %3 (now %4). %1 поместил %n %2 жетон на %3 (теперь %4). @@ -1762,7 +2151,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 снял %n %2 жетон с %3 (теперь %4). @@ -1771,7 +2160,7 @@ Local version is %1, remote version is %2. - + red красный @@ -1780,7 +2169,7 @@ Local version is %1, remote version is %2. - + yellow желтый @@ -1789,7 +2178,7 @@ Local version is %1, remote version is %2. - + green зеленый @@ -1798,157 +2187,162 @@ Local version is %1, remote version is %2. - + his permanents свои перманенты - + + her permanents + + + + %1 %2 %3. %1 %2 %3. - + taps повернул - + untaps развернул - + %1 sets counter %2 to %3 (%4%5). %1 установил жетон %2 на %3 (%4%5). - + %1 sets %2 to not untap normally. %2 теперь не разворачивается как обычно (%1). - + %1 sets %2 to untap normally. %2 теперь разворачивается как обычно (%1). - + %1 sets PT of %2 to %3. %1 установил Силу/Защиту %2 %3. - + %1 sets annotation of %2 to %3. %1 сделал пометку на %2 "%3". - + %1 is looking at the top %2 cards %3. %1 смотрит верхние %2 карт библиотеки %3. - + %1 is looking at %2. %1 просматривает %2. - + %1 stops looking at %2. %1 закончил просматривать %2. - + %1 reveals %2 to %3. %1 показывает его %2 %3. - + %1 reveals %2. %1 открыл его %2. - + %1 randomly reveals %2%3 to %4. %1 показывает случайно выбранную%3 карту (%2) %4. - + %1 randomly reveals %2%3. %1 открывает случайно выбранную%3 карту (%2). - + %1 reveals %2%3 to %4. %1 показывает%2%3 %4. - + %1 reveals %2%3. %1 открывает%2%3. - + It is now %1's turn. Ход игрока %1. - + untap step шаг разворота - + upkeep step шаг поддержки - + draw step шаг взятия карты - + first main phase первая главная фаза - + beginning of combat step шаг начала битвы - + declare attackers step шаг назначения атакующих - + declare blockers step шаг назначения блокирующих - + combat damage step шаг нанесения повреждений - + end of combat step шаг завершения битвы - + second main phase вторая главная фаза - + ending phase заключительный шаг - + It is now the %1. Сейчас %1. @@ -2833,42 +3227,51 @@ Please enter a name: UserInfoBox - + User information Информация о пользователе - + Real name: Настоящее имя: - + + Gender: + + + + Location: Местонахождение: - + User level: Уровень: - + Administrator Администратор - - Judge - Судья + + Moderator + - + Judge + Судья + + + Registered user Зарегистрированный пользователь - + Unregistered user Рандом diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 836c20200..30324e939 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -393,183 +393,363 @@ CardZone - - his hand - nominative + + her hand + nominative, female owner - + %1's hand - nominative + nominative, female owner - of his hand - genitive + his hand + nominative, male owner + %1's hand + nominative, male owner + + + + + of her hand + genitive, female owner + + + + of %1's hand - genitive + genitive, female owner - his hand - accusative + of his hand + genitive, male owner + of %1's hand + genitive, male owner + + + + + her hand + accusative, female owner + + + + %1's hand - accusative + accusative, female owner - - his library - nominative + + his hand + accusative, male owner - + + %1's hand + accusative, male owner + + + + + her library + nominative, female owner + + + + %1's library - nominative + nominative, female owner - of his library - genitive + his library + nominative, male owner + %1's library + nominative, male owner + + + + + of her library + genitive, female owner + + + + of %1's library - genitive + genitive, female owner - his library - accusative + of his library + genitive, male owner + of %1's library + genitive, male owner + + + + + her library + accusative, female owner + + + + %1's library - accusative + accusative, female owner - - his graveyard - nominative + + his library + accusative, male owner - + + %1's library + accusative, male owner + + + + + her graveyard + nominative, female owner + + + + %1's graveyard - nominative + nominative, female owner - of his graveyard - genitive + his graveyard + nominative, male owner + %1's graveyard + nominative, male owner + + + + + of her graveyard + genitive, female owner + + + + of %1's graveyard - genitive + genitive, female owner - his graveyard - accusative + of his graveyard + genitive, male owner + of %1's graveyard + genitive, male owner + + + + + her graveyard + accusative, female owner + + + + %1's graveyard - accusative + accusative, female owner - - his exile - nominative + + his graveyard + accusative, male owner - + + %1's graveyard + accusative, male owner + + + + + her exile + nominative, female owner + + + + %1's exile - nominative + nominative, female owner - of his exile - genitive + his exile + nominative, male owner + %1's exile + nominative, male owner + + + + + of her exile + genitive, female owner + + + + of %1's exile - genitive + genitive, female owner - his exile - accusative + of his exile + genitive, male owner + of %1's exile + genitive, male owner + + + + + her exile + accusative, female owner + + + + %1's exile - accusative + accusative, female owner - - his sideboard - nominative + + his exile + accusative, male owner - + + %1's exile + accusative, male owner + + + + + her sideboard + nominative, female owner + + + + %1's sideboard - nominative + nominative, female owner - of his sideboard - genitive + his sideboard + nominative, male owner + %1's sideboard + nominative, male owner + + + + + of her sideboard + genitive, female owner + + + + of %1's sideboard - genitive + genitive, female owner - his sideboard - accusative + of his sideboard + genitive, male owner + of %1's sideboard + genitive, male owner + + + + + her sideboard + accusative, female owner + + + + %1's sideboard - accusative + accusative, female owner + + + + + his sideboard + accusative, male owner + + + + + %1's sideboard + accusative, male owner @@ -1427,107 +1607,107 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Connected. - + Disconnected from server. - + Invalid password. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - - %1 shuffles his library. + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1536,138 +1716,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + + %1 undoes her last draw. + + + + %1 undoes his last draw (%2). - + + %1 undoes her last draw (%2). + + + + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + + the bottom card of her library + + + + from the bottom of his library - - the top card of his library - - - - - from the top of his library + + from the bottom of her library + the top card of his library + + + + + the top card of her library + + + + + from the top of his library + + + + + from the top of her library + + + + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + + %1 puts %2%3 into her library. + + + + %1 puts %2%3 on bottom of his library. - + + %1 puts %2%3 on bottom of her library. + + + + %1 puts %2%3 on top of his library. - - %1 puts %2%3 into his library at position %4. - - - - - %1 moves %2%3 to sideboard. + + %1 puts %2%3 on top of her library. + %1 puts %2%3 into his library at position %4. + + + + + %1 puts %2%3 into her library at position %4. + + + + + %1 moves %2%3 to sideboard. + + + + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1676,52 +1906,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + + %1 draws her initial hand. + + + + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1730,7 +1965,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -1739,7 +1974,7 @@ Local version is %1, remote version is %2. - + red @@ -1748,7 +1983,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1757,7 +1992,7 @@ Local version is %1, remote version is %2. - + green @@ -1766,157 +2001,162 @@ Local version is %1, remote version is %2. - + his permanents - + + her permanents + + + + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2788,42 +3028,47 @@ Please enter a name: UserInfoBox - + User information - + Real name: - + + Gender: + + + + Location: - + User level: - + Administrator - - Judge + + Moderator - + Registered user - + Unregistered user diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index 547c5b937..aaf164674 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -11,12 +11,13 @@ CardToMove::CardToMove(int _cardId, const QString &_pt, bool _tapped) insertItem(new SerializableItem_Bool("tapped", _tapped)); } -ServerInfo_User::ServerInfo_User(const QString &_name, int _userLevel, const QString &_realName, const QString &_country, const QByteArray &_avatarBmp) +ServerInfo_User::ServerInfo_User(const QString &_name, int _userLevel, const QString &_realName, Gender _gender, const QString &_country, const QByteArray &_avatarBmp) : SerializableItem_Map("user") { insertItem(new SerializableItem_String("name", _name)); insertItem(new SerializableItem_Int("userlevel", _userLevel)); insertItem(new SerializableItem_String("real_name", _realName)); + insertItem(new SerializableItem_Int("gender", _gender)); insertItem(new SerializableItem_String("country", _country)); insertItem(new SerializableItem_ByteArray("avatar_bmp", _avatarBmp)); } @@ -27,6 +28,7 @@ ServerInfo_User::ServerInfo_User(const ServerInfo_User *other, bool complete) insertItem(new SerializableItem_String("name", other->getName())); insertItem(new SerializableItem_Int("userlevel", other->getUserLevel())); insertItem(new SerializableItem_String("real_name", other->getRealName())); + insertItem(new SerializableItem_Int("gender", other->getGender())); insertItem(new SerializableItem_String("country", other->getCountry())); insertItem(new SerializableItem_ByteArray("avatar_bmp", complete ? other->getAvatarBmp() : QByteArray())); } diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 066bbc338..02f5336c1 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -41,16 +41,22 @@ public: IsNothing = 0x00, IsUser = 0x01, IsRegistered = 0x02, - IsJudge = 0x04, + IsModerator = 0x04, IsAdmin = 0x08 }; - ServerInfo_User(const QString &_name = QString(), int _userLevel = IsNothing, const QString &_realName = QString(), const QString &_country = QString(), const QByteArray &_avatarBmp = QByteArray()); + enum Gender { + GenderUnknown = -1, + Male = 0, + Female = 1 + }; + ServerInfo_User(const QString &_name = QString(), int _userLevel = IsNothing, const QString &_realName = QString(), Gender _gender = GenderUnknown, const QString &_country = QString(), const QByteArray &_avatarBmp = QByteArray()); ServerInfo_User(const ServerInfo_User *other, bool complete = true); static SerializableItem *newItem() { return new ServerInfo_User; } QString getName() const { return static_cast(itemMap.value("name"))->getData(); } int getUserLevel() const { return static_cast(itemMap.value("userlevel"))->getData(); } void setUserLevel(int _userLevel) { static_cast(itemMap.value("userlevel"))->setData(_userLevel); } QString getRealName() const { return static_cast(itemMap.value("real_name"))->getData(); } + Gender getGender() const { return static_cast(static_cast(itemMap.value("gender"))->getData()); } QString getCountry() const { return static_cast(itemMap.value("country"))->getData(); } QByteArray getAvatarBmp() const { return static_cast(itemMap.value("avatar_bmp"))->getData(); } }; diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index 203941a9a..06effa016 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -104,6 +104,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_users` ( `admin` tinyint(1) NOT NULL, `name` varchar(35) NOT NULL, `realname` varchar(255) NOT NULL, + `gender` char(1) NOT NULL, `password` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, `country` char(2) NOT NULL, diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 505c6fd0f..eaca1de6f 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -217,19 +217,31 @@ ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool co QString name = query.value(0).toString(); bool is_admin = query.value(1).toInt(); QString realName = query.value(2).toString(); - QString country = query.value(3).toString(); + QString genderStr = query.value(3).toString(); + QString country = query.value(4).toString(); QByteArray avatarBmp; if (complete) - avatarBmp = query.value(4).toByteArray(); + avatarBmp = query.value(5).toByteArray(); + + ServerInfo_User::Gender gender; + if (genderStr == "m") + gender = ServerInfo_User::Male; + else if (genderStr == "f") + gender = ServerInfo_User::Female; + else + gender = ServerInfo_User::GenderUnknown; int userLevel = ServerInfo_User::IsUser | ServerInfo_User::IsRegistered; - if (is_admin) + if (is_admin == 1) userLevel |= ServerInfo_User::IsAdmin; + else if (is_admin == 2) + userLevel |= ServerInfo_User::IsModerator; return new ServerInfo_User( name, userLevel, realName, + gender, country, avatarBmp ); @@ -243,7 +255,7 @@ ServerInfo_User *Servatrice::getUserData(const QString &name) checkSql(); QSqlQuery query; - query.prepare("select name, admin, realname, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1"); + query.prepare("select name, admin, realname, gender, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1"); query.bindValue(":name", name); if (!execSqlQuery(query)) return new ServerInfo_User(name, ServerInfo_User::IsUser); @@ -276,7 +288,7 @@ QMap Servatrice::getBuddyList(const QString &name) checkSql(); QSqlQuery query; - query.prepare("select a.name, a.admin, a.realname, a.country from " + dbPrefix + "_users a left join " + dbPrefix + "_buddylist b on a.id = b.id_user2 left join " + dbPrefix + "_users c on b.id_user1 = c.id where c.name = :name"); + query.prepare("select a.name, a.admin, a.realname, a.gender, a.country from " + dbPrefix + "_users a left join " + dbPrefix + "_buddylist b on a.id = b.id_user2 left join " + dbPrefix + "_users c on b.id_user1 = c.id where c.name = :name"); query.bindValue(":name", name); if (!execSqlQuery(query)) return result; @@ -299,7 +311,7 @@ QMap Servatrice::getIgnoreList(const QString &name) checkSql(); QSqlQuery query; - query.prepare("select a.name, a.admin, a.realname, a.country from " + dbPrefix + "_users a left join " + dbPrefix + "_ignorelist b on a.id = b.id_user2 left join " + dbPrefix + "_users c on b.id_user1 = c.id where c.name = :name"); + query.prepare("select a.name, a.admin, a.realname, a.gender, a.country from " + dbPrefix + "_users a left join " + dbPrefix + "_ignorelist b on a.id = b.id_user2 left join " + dbPrefix + "_users c on b.id_user1 = c.id where c.name = :name"); query.bindValue(":name", name); if (!execSqlQuery(query)) return result; From 5e3db65846b38349f9b781c57981d9b55e96dceb Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 22 Jun 2011 18:55:03 +0200 Subject: [PATCH 57/87] added deck editor icon --- cockatrice/cockatrice.qrc | 1 + .../resources/icon_config_deckeditor.svg | 268 ++++++++++++++++++ cockatrice/src/dlg_settings.cpp | 2 +- 3 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 cockatrice/resources/icon_config_deckeditor.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 563ee21d2..553561306 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -7,6 +7,7 @@ resources/icon_config_appearance.svg resources/icon_config_interface.svg resources/icon_config_messages.svg + resources/icon_config_deckeditor.svg resources/phases/icon_phase_untap.svg resources/phases/icon_phase_upkeep.svg resources/phases/icon_phase_draw.svg diff --git a/cockatrice/resources/icon_config_deckeditor.svg b/cockatrice/resources/icon_config_deckeditor.svg new file mode 100644 index 000000000..9e167516c --- /dev/null +++ b/cockatrice/resources/icon_config_deckeditor.svg @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index 0f295af2a..3f1c5a3d4 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -605,7 +605,7 @@ void DlgSettings::createIcons() deckEditorButton = new QListWidgetItem(contentsWidget); deckEditorButton->setTextAlignment(Qt::AlignHCenter); deckEditorButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - deckEditorButton->setIcon(QIcon(":/resources/icon_deckeditor.svg")); + deckEditorButton->setIcon(QIcon(":/resources/icon_config_deckeditor.svg")); messagesButton = new QListWidgetItem(contentsWidget); messagesButton->setTextAlignment(Qt::AlignHCenter); From a4c3d4838961b774f5844804304a276b9728d2a7 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Fri, 24 Jun 2011 18:45:39 +0200 Subject: [PATCH 58/87] server shutdown function --- cockatrice/src/abstractclient.cpp | 19 +-- cockatrice/src/abstractclient.h | 2 + cockatrice/src/localserverinterface.h | 3 +- cockatrice/src/tab_admin.cpp | 71 ++++++++- cockatrice/src/tab_admin.h | 20 ++- cockatrice/src/tab_supervisor.cpp | 4 +- cockatrice/src/window_main.cpp | 8 + cockatrice/src/window_main.h | 1 + cockatrice/translations/cockatrice_cs.ts | 156 +++++++++++++------ cockatrice/translations/cockatrice_de.ts | 163 ++++++++++++++------ cockatrice/translations/cockatrice_en.ts | 155 +++++++++++++------ cockatrice/translations/cockatrice_es.ts | 155 +++++++++++++------ cockatrice/translations/cockatrice_fr.ts | 155 +++++++++++++------ cockatrice/translations/cockatrice_ja.ts | 154 ++++++++++++------ cockatrice/translations/cockatrice_pl.ts | 156 +++++++++++++------ cockatrice/translations/cockatrice_pt-br.ts | 155 +++++++++++++------ cockatrice/translations/cockatrice_pt.ts | 155 +++++++++++++------ cockatrice/translations/cockatrice_ru.ts | 156 +++++++++++++------ cockatrice/translations/cockatrice_sk.ts | 156 +++++++++++++------ common/protocol.h | 9 ++ common/protocol_item_ids.h | 32 ++-- common/protocol_items.cpp | 16 +- common/protocol_items.dat | 4 +- common/protocol_items.h | 20 ++- common/protocol_mc.pl | 7 + common/server.cpp | 1 + common/server_protocolhandler.cpp | 13 +- common/server_protocolhandler.h | 3 +- servatrice/src/main.cpp | 4 + servatrice/src/servatrice.cpp | 39 ++++- servatrice/src/servatrice.h | 6 + servatrice/src/serversocketinterface.cpp | 13 +- servatrice/src/serversocketinterface.h | 3 +- 33 files changed, 1410 insertions(+), 604 deletions(-) diff --git a/cockatrice/src/abstractclient.cpp b/cockatrice/src/abstractclient.cpp index 5fb9b433a..7edb7a2ea 100644 --- a/cockatrice/src/abstractclient.cpp +++ b/cockatrice/src/abstractclient.cpp @@ -32,15 +32,16 @@ void AbstractClient::processProtocolItem(ProtocolItem *item) GenericEvent *genericEvent = qobject_cast(item); if (genericEvent) { switch (genericEvent->getItemId()) { - case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(qobject_cast(item)); break; - case ItemId_Event_AddToList: emit addToListEventReceived(qobject_cast(item)); break; - case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(qobject_cast(item)); break; - case ItemId_Event_UserJoined: emit userJoinedEventReceived(qobject_cast(item)); break; - case ItemId_Event_UserLeft: emit userLeftEventReceived(qobject_cast(item)); break; - case ItemId_Event_ServerMessage: emit serverMessageEventReceived(qobject_cast(item)); break; - case ItemId_Event_ListRooms: emit listRoomsEventReceived(qobject_cast(item)); break; - case ItemId_Event_GameJoined: emit gameJoinedEventReceived(qobject_cast(item)); break; - case ItemId_Event_Message: emit messageEventReceived(qobject_cast(item)); break; + case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(static_cast(item)); break; + case ItemId_Event_ServerShutdown: emit serverShutdownEventReceived(static_cast(item)); break; + case ItemId_Event_AddToList: emit addToListEventReceived(static_cast(item)); break; + case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(static_cast(item)); break; + case ItemId_Event_UserJoined: emit userJoinedEventReceived(static_cast(item)); break; + case ItemId_Event_UserLeft: emit userLeftEventReceived(static_cast(item)); break; + case ItemId_Event_ServerMessage: emit serverMessageEventReceived(static_cast(item)); break; + case ItemId_Event_ListRooms: emit listRoomsEventReceived(static_cast(item)); break; + case ItemId_Event_GameJoined: emit gameJoinedEventReceived(static_cast(item)); break; + case ItemId_Event_Message: emit messageEventReceived(static_cast(item)); break; } if (genericEvent->getReceiverMayDelete()) delete genericEvent; diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index f43131b56..d896a89dc 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -21,6 +21,7 @@ class Event_ListRooms; class Event_GameJoined; class Event_Message; class Event_ConnectionClosed; +class Event_ServerShutdown; enum ClientStatus { StatusDisconnected, @@ -43,6 +44,7 @@ signals: void gameEventContainerReceived(GameEventContainer *event); // Generic events void connectionClosedEventReceived(Event_ConnectionClosed *event); + void serverShutdownEventReceived(Event_ServerShutdown *event); void addToListEventReceived(Event_AddToList *event); void removeFromListEventReceived(Event_RemoveFromList *event); void userJoinedEventReceived(Event_UserJoined *event); diff --git a/cockatrice/src/localserverinterface.h b/cockatrice/src/localserverinterface.h index fc23b1b57..261941476 100644 --- a/cockatrice/src/localserverinterface.h +++ b/cockatrice/src/localserverinterface.h @@ -18,8 +18,9 @@ private: ResponseCode cmdDeckDel(Command_DeckDel * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdDeckUpload(Command_DeckUpload * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdDeckDownload(Command_DeckDownload * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } - ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdBanFromServer(Command_BanFromServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } + ResponseCode cmdShutdownServer(Command_ShutdownServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } + ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } public: LocalServerInterface(LocalServer *_server); ~LocalServerInterface(); diff --git a/cockatrice/src/tab_admin.cpp b/cockatrice/src/tab_admin.cpp index 4ea3a6527..082321384 100644 --- a/cockatrice/src/tab_admin.cpp +++ b/cockatrice/src/tab_admin.cpp @@ -1,19 +1,72 @@ +#include #include +#include #include #include #include +#include +#include +#include #include "tab_admin.h" #include "abstractclient.h" #include "protocol_items.h" -TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent) - : Tab(_tabSupervisor, parent), locked(true), client(_client) +ShutdownDialog::ShutdownDialog(QWidget *parent) + : QDialog(parent) +{ + QLabel *reasonLabel = new QLabel(tr("&Reason for shutdown:")); + reasonEdit = new QLineEdit; + reasonLabel->setBuddy(reasonEdit); + QLabel *minutesLabel = new QLabel(tr("&Time until shutdown (minutes):")); + minutesEdit = new QSpinBox; + minutesLabel->setBuddy(minutesEdit); + minutesEdit->setMinimum(0); + minutesEdit->setValue(5); + + QPushButton *okButton = new QPushButton(tr("&OK")); + okButton->setAutoDefault(true); + okButton->setDefault(true); + connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); + QPushButton *cancelButton = new QPushButton(tr("&Cancel")); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(); + buttonLayout->addWidget(okButton); + buttonLayout->addWidget(cancelButton); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(reasonLabel, 0, 0); + mainLayout->addWidget(reasonEdit, 0, 1); + mainLayout->addWidget(minutesLabel, 1, 0); + mainLayout->addWidget(minutesEdit, 1, 1); + mainLayout->addLayout(buttonLayout, 2, 0, 1, 2); + + setLayout(mainLayout); + setWindowTitle(tr("Shut down server")); +} + +QString ShutdownDialog::getReason() const +{ + return reasonEdit->text(); +} + +int ShutdownDialog::getMinutes() const +{ + return minutesEdit->value(); +} + +TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool _fullAdmin, QWidget *parent) + : Tab(_tabSupervisor, parent), locked(true), client(_client), fullAdmin(_fullAdmin) { updateServerMessageButton = new QPushButton; connect(updateServerMessageButton, SIGNAL(clicked()), this, SLOT(actUpdateServerMessage())); + shutdownServerButton = new QPushButton; + connect(shutdownServerButton, SIGNAL(clicked()), this, SLOT(actShutdownServer())); QVBoxLayout *vbox = new QVBoxLayout; vbox->addWidget(updateServerMessageButton); + vbox->addWidget(shutdownServerButton); vbox->addStretch(); adminGroupBox = new QGroupBox; @@ -38,6 +91,7 @@ TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidg void TabAdmin::retranslateUi() { updateServerMessageButton->setText(tr("Update server &message")); + shutdownServerButton->setText(tr("&Shut down server")); adminGroupBox->setTitle(tr("Server administration functions")); unlockButton->setText(tr("&Unlock functions")); @@ -49,10 +103,18 @@ void TabAdmin::actUpdateServerMessage() client->sendCommand(new Command_UpdateServerMessage()); } +void TabAdmin::actShutdownServer() +{ + ShutdownDialog dlg; + if (dlg.exec()) + client->sendCommand(new Command_ShutdownServer(dlg.getReason(), dlg.getMinutes())); +} + void TabAdmin::actUnlock() { if (QMessageBox::question(this, tr("Unlock administration functions"), tr("Do you really want to unlock the administration functions?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - adminGroupBox->setEnabled(true); + if (fullAdmin) + adminGroupBox->setEnabled(true); lockButton->setEnabled(true); unlockButton->setEnabled(false); locked = false; @@ -61,7 +123,8 @@ void TabAdmin::actUnlock() void TabAdmin::actLock() { - adminGroupBox->setEnabled(false); + if (fullAdmin) + adminGroupBox->setEnabled(false); lockButton->setEnabled(false); unlockButton->setEnabled(true); locked = true; diff --git a/cockatrice/src/tab_admin.h b/cockatrice/src/tab_admin.h index 8450d473b..a4982bbae 100644 --- a/cockatrice/src/tab_admin.h +++ b/cockatrice/src/tab_admin.h @@ -2,27 +2,43 @@ #define TAB_ADMIN_H #include "tab.h" +#include class AbstractClient; class QGroupBox; class QPushButton; +class QSpinBox; +class QLineEdit; + +class ShutdownDialog : public QDialog { + Q_OBJECT +private: + QLineEdit *reasonEdit; + QSpinBox *minutesEdit; +public: + ShutdownDialog(QWidget *parent = 0); + QString getReason() const; + int getMinutes() const; +}; class TabAdmin : public Tab { Q_OBJECT private: bool locked; AbstractClient *client; - QPushButton *updateServerMessageButton; + bool fullAdmin; + QPushButton *updateServerMessageButton, *shutdownServerButton; QGroupBox *adminGroupBox; QPushButton *unlockButton, *lockButton; private slots: void actUpdateServerMessage(); + void actShutdownServer(); void actUnlock(); void actLock(); public: - TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent = 0); + TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool _fullAdmin, QWidget *parent = 0); void retranslateUi(); QString getTabText() const { return tr("Administration"); } bool getLocked() const { return locked; } diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index be7751a08..1dfe7d443 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -135,8 +135,8 @@ void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo) } else tabDeckStorage = 0; - if (userInfo->getUserLevel() & ServerInfo_User::IsAdmin) { - tabAdmin = new TabAdmin(this, client); + if (userInfo->getUserLevel() & ServerInfo_User::IsModerator) { + tabAdmin = new TabAdmin(this, client, (userInfo->getUserLevel() & ServerInfo_User::IsAdmin)); myAddTab(tabAdmin); } else tabAdmin = 0; diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 595e8b8e0..7acbe5510 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -56,11 +56,18 @@ void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event) reasonStr = tr("There are too many concurrent connections from your address."); else if (reason == "banned") reasonStr = tr("Banned by moderator."); + else if (reason == "server_shutdown") + reasonStr = tr("Scheduled server shutdown."); else reasonStr = tr("Unknown reason."); QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr)); } +void MainWindow::processServerShutdownEvent(Event_ServerShutdown *event) +{ + QMessageBox::information(this, tr("Scheduled server shutdown"), tr("The server is going to be restarted in %n minute(s).\nAll running games will be lost.\nReason for shutdown: %1", "", event->getMinutes()).arg(event->getReason())); +} + void MainWindow::statusChanged(ClientStatus _status) { setClientStatusTitle(); @@ -290,6 +297,7 @@ MainWindow::MainWindow(QWidget *parent) client = new RemoteClient(this); connect(client, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed *)), this, SLOT(processConnectionClosedEvent(Event_ConnectionClosed *))); + connect(client, SIGNAL(serverShutdownEventReceived(Event_ServerShutdown *)), this, SLOT(processServerShutdownEvent(Event_ServerShutdown *))); connect(client, SIGNAL(serverError(ResponseCode)), this, SLOT(serverError(ResponseCode))); connect(client, SIGNAL(socketError(const QString &)), this, SLOT(socketError(const QString &))); connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout())); diff --git a/cockatrice/src/window_main.h b/cockatrice/src/window_main.h index 9ca62ba84..4d8b45d60 100644 --- a/cockatrice/src/window_main.h +++ b/cockatrice/src/window_main.h @@ -36,6 +36,7 @@ private slots: void updateTabMenu(QMenu *menu); void statusChanged(ClientStatus _status); void processConnectionClosedEvent(Event_ConnectionClosed *event); + void processServerShutdownEvent(Event_ServerShutdown *event); void serverTimeout(); void serverError(ResponseCode r); void socketError(const QString &errorStr); diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index 1ce8de4b1..bea2660ef 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -1390,216 +1390,237 @@ + Scheduled server shutdown. + + + + Unknown reason. - + Connection closed - + The server has terminated your connection. Reason: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + + Number of players - + Please enter the number of players. - - + + Player %1 - + About Cockatrice - + Version %1 - + Authors: - + Translators: - + Spanish: - + Portugese (Portugal): - + Portugese (Brazil): - + French: - + Japanese: - + Russian: - + Czech: - + Slovak: - - + - - + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -2705,40 +2726,73 @@ Local version is %1, remote version is %2. + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + + + + + &Cancel + + + + + Shut down server + + + TabAdmin - + Update server &message - + + &Shut down server + + + + Server administration functions - + &Unlock functions - + &Lock functions - + Unlock administration functions - + Do you really want to unlock the administration functions? - + Administration diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 85e2d47ba..33c229395 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -2140,138 +2140,162 @@ + Scheduled server shutdown. + Planmäßige Serverabschaltung. + + + Unknown reason. Unbekannter Grund. - + Connection closed Verbindung geschlossen - + The server has terminated your connection. Reason: %1 Der Server hat Ihre Verbindung beendet. Grund: %1 - + + Scheduled server shutdown + Planmäßige Serverabschaltung + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + Der Server wird in %n Minute neu gestartet. +Alle laufenden Spiele werden beendet. +Grund für die Abschaltung: %1 + Der Server wird in %n Minuten neu gestartet. +Alle laufenden Spiele werden beendet. +Grund für die Abschaltung: %1 + + + + Number of players Spieleranzahl - + Please enter the number of players. Bitte die Spieleranzahl eingeben: - - + + Player %1 Spieler %1 - + About Cockatrice Über Cockatrice - + Version %1 Version %1 - + Authors: Autoren: - + Translators: Übersetzer: - + Spanish: Spanisch: - + Portugese (Portugal): Portugiesisch (Portugal): - + Portugese (Brazil): Portugiesisch (Brasilien): - + French: Französisch: - + Japanese: Japanisch: - + Russian: Russisch: - + Czech: Tschechisch: - + Slovak: Slowakisch: - - + - - + + + Error Fehler - + Server timeout Server Zeitüberschreitung - + Invalid login data. Ungültige Anmeldedaten. - + There is already an active session using this user name. Please close that session first and re-login. Es gibt bereits eine aktive Verbindung mit diesem Benutzernamen. Bitte schließen Sie diese Verbindung zuerst und versuchen Sie es dann erneut. - + Socket error: %1 Netzwerkfehler: %1 - + 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. Sie versuchen sich an einem veralteten Server anzumelden. Bitte verwenden Sie eine ältere Cockatrice-Version oder melden Sie sich an einem aktuellen Server an. Lokale Version ist %1, Serverversion ist %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Ihr Cockatrice-Client ist veraltet. Bitte laden Sie sich die neueste Version herunter. @@ -2282,52 +2306,52 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversionen stimmen nicht überein. Lokale Version: %1, Serverversion: %2. - + Connecting to %1... Verbinde zu %1... - + Disconnected nicht verbunden - + Logged in at %1 Angemeldet bei %1 - + &Connect... &Verbinden... - + &Disconnect Verbindung &trennen - + Start &local game... &Lokales Spiel starten... - + &About Cockatrice &Über Cockatrice - + &Help &Hilfe - + Are you sure? Sind Sie sicher? - + There are still open games. Are you sure you want to quit? Es gibt noch offene Spiele. Wollen Sie das Programm wirklich beenden? @@ -2344,27 +2368,27 @@ Lokale Version ist %1, Serverversion ist %2. Spiel ver&lassen - + &Deck editor &Deck-Editor - + &Full screen &Vollbild - + Ctrl+F Ctrl+F - + &Settings... &Einstellungen... - + &Exit &Beenden @@ -2377,7 +2401,7 @@ Lokale Version ist %1, Serverversion ist %2. Esc - + &Cockatrice &Cockatrice @@ -4021,40 +4045,77 @@ Lokale Version ist %1, Serverversion ist %2. Langer Name + + ShutdownDialog + + + &Reason for shutdown: + G&rund für die Abschaltung: + + + + &Time until shutdown (minutes): + &Zeit bis zur Abschaltung (Minuten): + + + + &OK + &OK + + + + &Cancel + &Abbrechen + + + + Shut down server + Server abschalten + + TabAdmin - + Update server &message Server&nachricht aktualisieren - + Shut down server + Server abschalten + + + + &Shut down server + &Server abschalten + + + Server administration functions Funktionen zur Serverwartung - + &Unlock functions &Sperre aufheben - + &Lock functions Funktionen s&perren - + Unlock administration functions Wartungsfunktionen entsperren - + Do you really want to unlock the administration functions? Möchten Sie wirklich die Sperre der Wartungsfunktionen aufheben? - + Administration Wartung diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 415aa3fd0..a0cd85a43 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -1390,216 +1390,236 @@ + Scheduled server shutdown. + + + + Unknown reason. - + Connection closed - + The server has terminated your connection. Reason: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + Number of players - + Please enter the number of players. - - + + Player %1 - + About Cockatrice - + Version %1 - + Authors: - + Translators: - + Spanish: - + Portugese (Portugal): - + Portugese (Brazil): - + French: - + Japanese: - + Russian: - + Czech: - + Slovak: - - + - - + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -2712,40 +2732,73 @@ Local version is %1, remote version is %2. + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + + + + + &Cancel + + + + + Shut down server + + + TabAdmin - + Update server &message - + + &Shut down server + + + + Server administration functions - + &Unlock functions - + &Lock functions - + Unlock administration functions - + Do you really want to unlock the administration functions? - + Administration diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 116265d52..607579844 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -1755,138 +1755,158 @@ + Scheduled server shutdown. + + + + Unknown reason. Motivo desconocido. - + Connection closed Conexión cerrada - + The server has terminated your connection. Reason: %1 El servidor ha finalizado tu conexión. Motivo: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + Number of players Número de jugadores - + Please enter the number of players. Por favor, introduzca el número de jugadores. - - + + Player %1 Jugador %1 - + About Cockatrice Acerca de Cockatrice - + Version %1 Versión %1 - + Authors: Autores: - + Translators: Traductores: - + Spanish: Español: - + Portugese (Portugal): Portugués (Portugal): - + Portugese (Brazil): Portugués (Brasil): - + French: Francés: - + Japanese: Japonés: - + Russian: Ruso: - + Czech: - + Slovak: - - + - - + + + Error Error - + Server timeout Tiempo de espera del servidor agotado - + Invalid login data. Datos de conexión invalidos. - + There is already an active session using this user name. Please close that session first and re-login. Ya existe una sesión activa usando ese nombre de usuario. Por favor, cierra esa sesión primero y reintentalo. - + Socket error: %1 Error del Socket: %1 - + 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. Estás intentando conectar a un servidor obsoleto. Por favor, usa una versión anterior de Cockatrice o conecta a un servidor apropiado. La versión local es %1, la versión remota es %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Tu cliente de Cockatrice esta obsoleto. Por favor, actualiza tu versión de Cockatrice. @@ -1897,82 +1917,82 @@ La versión local es %1, la versión remota es %2. La versión del protocolo es diferente. Version local: %1, version remota: %2. - + Connecting to %1... Conectando a %1... - + Disconnected Desconectado - + Logged in at %1 Conectado en %1 - + &Connect... &Conectar... - + &Disconnect &Desconectar - + Start &local game... Empezar partida &local... - + &Deck editor Editor de &mazos - + &Full screen &Pantalla completa - + Ctrl+F CTRL+F - + &Settings... &Preferencias... - + &Exit &Salir - + &Cockatrice &Cockatrice - + &About Cockatrice &Acerca de Cockatrice - + &Help A&yuda - + Are you sure? ¿Estás seguro? - + There are still open games. Are you sure you want to quit? Todavía hay partidas abiertas. ¿Estás seguro que quieres salir? @@ -3140,40 +3160,73 @@ La versión local es %1, la versión remota es %2. Nombre largo + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + &Aceptar + + + + &Cancel + &Cancelar + + + + Shut down server + + + TabAdmin - + Update server &message Actualizar &mensaje del servidor - + + &Shut down server + + + + Server administration functions Funciones de administración del servidor - + &Unlock functions &Desbloquear funciones - + &Lock functions &Bloquear funciones - + Unlock administration functions Desbloquear funciones de administración - + Do you really want to unlock the administration functions? ¿Realmente quieres desbloquear las funciones de administración? - + Administration Administración diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index de17833e4..3573db24b 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -1595,23 +1595,23 @@ MainWindow - + Number of players Nombre de joueurs - + Please enter the number of players. Entrez s'il vous plait le nombre de joueurs. - - + + Player %1 Joueur %1 - + About Cockatrice à propos de Cockatrice @@ -1620,67 +1620,67 @@ <font size="8"><b>Cockatrice</b></font><br>Version %1<br><br><br><b>Auteurs:</b><br>Max-Wilhelm Bruker<br>Marcus Schütz<br>Marius van Zundert<br><br><b>Tranducteurs:</b><br>Espagnol: Gocho<br>Portugais: Milton Gonçalves<br>Portugais: Milton Gonçalves<br>Français: Yannick HAMMER<br> - + Version %1 Version %1 - + Authors: Auteurs: - + Translators: Traducteurs: - + Spanish: Espagnol: - + Portugese (Portugal): Portugais (Portugal): - + Portugese (Brazil): Portugais (Brésil): - + French: Français: - + Japanese: Japonais: - - + - - + + + Error Erreur - + Server timeout Délai de la demande dépassé - + Invalid login data. Information de connexion érronée. - + Socket error: %1 Erreur de socket: %1 @@ -1700,136 +1700,156 @@ + Scheduled server shutdown. + + + + Unknown reason. Raison inconnue. - + Connection closed Connection fermée - + The server has terminated your connection. Reason: %1 Le serveur a coupé votre connexion. Raison: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + Russian: putted "France" instead of "Russe" -> meant that I must put the translation laguage country, isn't it? France: - + Czech: - + Slovak: - + There is already an active session using this user name. Please close that session first and re-login. Il y a déjà une session ouvert avec le même pseudo. Fermez cette session puis re-connectez-vous. - + 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. Vous tentez de vous connecter à un serveur obsolète. Chargez la nouvelle version de Cockatrice ou connectez-vous à un serveur approprié. La version la plus récente est %1, l'ancienne version est %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Votre client Cockatrice est obsolète. Veuillez charger la nouvelle version. La version la plus récente est %1, l'ancienne version est %2. - + Connecting to %1... Connexion à %1... - + Disconnected Déconnecté - + Logged in at %1 Connecté à %1 - + &Connect... à verifier &Connecter... - + &Disconnect &Déconnecter - + Start &local game... Démarrer une partie &locale... - + &Deck editor Éditeur de &deck - + &Full screen &Plein écran - + Ctrl+F Ctrl+F - + &Settings... &Paramètres... - + &Exit &Quitter - + &Cockatrice &Cockatrice - + &About Cockatrice À propos de Cock&atrice - + &Help A&ide - + Are you sure? Êtes-vous sûr? - + There are still open games. Are you sure you want to quit? Il y a encore des parties en cours. Êtes-vous sûr de vouloir quitter? @@ -2999,40 +3019,73 @@ La version la plus récente est %1, l'ancienne version est %2.Nom complet + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + &OK + + + + &Cancel + &Annuler + + + + Shut down server + + + TabAdmin - + Update server &message Mettre à jour le &message du serveur - + + &Shut down server + + + + Server administration functions Fonctions d'administration du serveur - + &Unlock functions &Débloquer fonctions - + &Lock functions &Bloquer fonctions - + Unlock administration functions Débloquer fonctions d'administration - + Do you really want to unlock the administration functions? Êtes-vous sûr de vouloir débloquer les fonctions d'administration? - + Administration Administration diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index 4ae3575c8..73682c839 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -1443,220 +1443,239 @@ + Scheduled server shutdown. + + + + Unknown reason. 不明な理由. - + Connection closed 通信切断 - + The server has terminated your connection. Reason: %1 サーバーはあなたの接続を切断しました. 理由: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + Number of players プレイヤー人数 - + Please enter the number of players. プレイヤーの人数を入れてください. - - + + Player %1 プレイヤー %1 - + About Cockatrice Cockatriceについて - + Version %1 - + Authors: 著者: - + Translators: 翻訳者: - + Spanish: スペイン語: - + Portugese (Portugal): ポルトガル語(ポルトガル): - + Portugese (Brazil): ポルトガル語(ブラジル): - + French: フランス語: - + Japanese: 日本語: - + Russian: ロシア語: - + Czech: - + Slovak: - - + - - + + + Error エラー - + Server timeout サーバータイムアウト - + Invalid login data. 無効なログインデータです. - + There is already an active session using this user name. Please close that session first and re-login. これはすでにこのユーザー名で使われているアクティブなセッションです. まずこのセッションを閉じてログインしなおしてください. - + Socket error: %1 ソケットエラー: %1 - + 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. あなたは古いVerのサーバーに接続しようとしています.CockatriceのVerをダウングレードするか適正なサーバーに接続してください. ローカルVer %1,リモートVer %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. あなたのCockatriceのVerが古いです.Cockatriceをアップデートしてください. ローカルVer %1,リモートVer %2. - + Connecting to %1... %1へ接続しています... - + Disconnected 切断されました - + Logged in at %1 %1にログイン中 - + &Connect... 接続... - + &Disconnect 切断 - + Start &local game... ローカルゲームを開始... - + &Deck editor デッキエディター - + &Full screen フルスクリーン - + Ctrl+F - + &Settings... 設定... - + &Exit 終了 - + &Cockatrice - + &About Cockatrice - + &Help ヘルプ - + Are you sure? よろしいですか? - + There are still open games. Are you sure you want to quit? ゲームがまだ開いています.本当に退出しますか? @@ -2779,40 +2798,73 @@ Local version is %1, remote version is %2. 正式名称 + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + + + + + &Cancel + + + + + Shut down server + + + TabAdmin - + Update server &message サーバー更新&メッセージ - + + &Shut down server + + + + Server administration functions サーバー管理機能 - + &Unlock functions 機能をアンロックする - + &Lock functions 機能をロックする - + Unlock administration functions 管理機能をアンロックする - + Do you really want to unlock the administration functions? 本当に管理機能をアンロックしますか? - + Administration 管理者 diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index bdaa82631..093c66681 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -1390,216 +1390,237 @@ + Scheduled server shutdown. + + + + Unknown reason. - + Connection closed - + The server has terminated your connection. Reason: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + + Number of players - + Please enter the number of players. - - + + Player %1 - + About Cockatrice - + Version %1 - + Authors: - + Translators: - + Spanish: - + Portugese (Portugal): - + Portugese (Brazil): - + French: - + Japanese: - + Russian: - + Czech: - + Slovak: - - + - - + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -2705,40 +2726,73 @@ Local version is %1, remote version is %2. + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + + + + + &Cancel + + + + + Shut down server + + + TabAdmin - + Update server &message - + + &Shut down server + + + + Server administration functions - + &Unlock functions - + &Lock functions - + Unlock administration functions - + Do you really want to unlock the administration functions? - + Administration diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index c0549f8d1..8dd17c58f 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -1598,23 +1598,23 @@ MainWindow - + Number of players Número de jogadores - + Please enter the number of players. Por favor, entre o número de jogadores. - - + + Player %1 Jogador %1 - + About Cockatrice Sobre o Cockatrice @@ -1623,72 +1623,72 @@ <font size="8"><b>Cockatrice</b></font><br>Version %1<br><br><br><b>Authors:</b><br>Max-Wilhelm Bruker<br>Marcus Schütz<br>Marius van Zundert<br><br><b>Translators:</b><br>Spanish: Gocho<br>Portugese: Milton Gonçalves<br>Brazilian Portuguese: Thiago Queiroz<br> - + Version %1 Versão %1 - + Authors: Autores: - + Translators: Tradutores: - + Spanish: Espanhol: - + Portugese (Portugal): Português (Portugal): - + Portugese (Brazil): Português (Brasil): - + French: Francês: - + Japanese: Japonês: - + Russian: Russo: - - + - - + + + Error Erro - + Server timeout Tempo esgotado do servidor - + Invalid login data. Informações de login inválidas. - + Socket error: %1 Erro de ligação:%1 @@ -1708,129 +1708,149 @@ + Scheduled server shutdown. + + + + Unknown reason. Razão desconhecida. - + Connection closed Conexão fechada - + The server has terminated your connection. Reason: %1 O servidor terminou sua conexão. Razão: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + Czech: - + Slovak: - + There is already an active session using this user name. Please close that session first and re-login. Já existe uma sessão ativa usando este nome de usuário. Por favor, feche a sessão primeiro e logue novamente. - + 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. Você está tentando conectar a um servidor obsoleto. Por favor, faça um downgrade na versão do seu Cockatrice ou conecte-se ao servidor correto. A versão local é %1 e a versão remota é %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. A versão do seu Cockatrice é obsoleta. Por favor, atualize a sua versão. A versão local é %1 e a versão remota é %2. - + Connecting to %1... Conectando a %1... - + Disconnected Desconectado - + Logged in at %1 Logado em %1 - + &Connect... &Conectar... - + &Disconnect &Desconectar - + Start &local game... Iniciar jogo &local... - + &Deck editor Editor de &decks - + &Full screen Tela &cheia - + Ctrl+F Ctrl+F - + &Settings... &Configurações... - + &Exit &Sair - + &Cockatrice &Cockatrice - + &About Cockatrice So&bre o Cockatrice - + &Help &Ajuda - + Are you sure? Você tem certeza? - + There are still open games. Are you sure you want to quit? Ainda existem jogos abertos. Você tem certeza que deseja sair? @@ -2982,40 +3002,73 @@ A versão local é %1 e a versão remota é %2. Nome longo + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + &OK + + + + &Cancel + &Cancelar + + + + Shut down server + + + TabAdmin - + Update server &message &Atualizar mensagem do servidor - + + &Shut down server + + + + Server administration functions Funções do administrador do servidor - + &Unlock functions &Desbloquear funções - + &Lock functions &Bloquear funções - + Unlock administration functions Desbloquear funções do administrador - + Do you really want to unlock the administration functions? Você quer mesmo desbloquear as funções do administrador? - + Administration Administração diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 9b7dac82c..7ed23d1bc 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -1598,23 +1598,23 @@ MainWindow - + Number of players Número de jogadores - + Please enter the number of players. Por favor introduza o número de jogadores. - - + + Player %1 Jogador %1 - + About Cockatrice Sobre o Cockatrice @@ -1623,22 +1623,22 @@ <font size="8"><b>Cockatrice</b></font><br>Versão %1<br><br><br><b>Autores:</b><br>Max-Wilhelm Bruker<br>Marcus Schütz<br>Marius van Zundert<br><br><b>Tradutores:</b><br>Espanhol: Gocho<br>Português: Milton Gonçalves<br> - + Version %1 Versão %1 - + Authors: Autores: - + Translators: Tradutores: - + Spanish: Espanhol: @@ -1647,52 +1647,52 @@ Português: - + Portugese (Portugal): Português (Portugal): - + Portugese (Brazil): Português (Brasil): - + French: Francês: - + Japanese: Japonês: - + Russian: Russo: - - + - - + + + Error Erro - + Server timeout Tempo do servidor esgotado - + Invalid login data. Informação de login incorrecta. - + Socket error: %1 Erro de ligação:%1 @@ -1712,129 +1712,149 @@ + Scheduled server shutdown. + + + + Unknown reason. Razão desconhecida. - + Connection closed Ligação terminada - + The server has terminated your connection. Reason: %1 O servidor terminou a sua ligação. Motivo: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + Czech: - + Slovak: - + There is already an active session using this user name. Please close that session first and re-login. Já existe uma sessão activa com este nome de utilizador. Por favor termine essa sessão e volte a ligar-se. - + 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. Está a tentar ligar-se a um servidor obsoleto. Por favor faça downgrade à sua versão do Cockatrice ou ligue-se a servidor adequado. Versão local é %1, versão remota é %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. A sua versão do Cockatrice é obsoleta. Por favor actualize-a. Versão local é %1, versão remota é %2. - + Connecting to %1... Ligando a %1... - + Disconnected Desligado - + Logged in at %1 Logado em %1 - + &Connect... &Ligar... - + &Disconnect &Desligar - + Start &local game... Começar &jogo local... - + &Deck editor &Editor de decks - + &Full screen Ecrã &inteiro - + Ctrl+F Ctrl+F - + &Settings... &Configurações... - + &Exit &Sair - + &Cockatrice &Cockatrice - + &About Cockatrice S&obre o Cockatrice - + &Help &Ajuda - + Are you sure? Tens a certeza? - + There are still open games. Are you sure you want to quit? Ainda há jogos abertos. Tem a certeza que deseja sair? @@ -2986,40 +3006,73 @@ Versão local é %1, versão remota é %2. Nome longo + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + + + + + &Cancel + &Cancelar + + + + Shut down server + + + TabAdmin - + Update server &message &Actualizar mensagem do servidor - + + &Shut down server + + + + Server administration functions Funções do administrador do servidor - + &Unlock functions &Desbloquear funções - + &Lock functions &Bloquear funções - + Unlock administration functions Desbloquear funções de administração - + Do you really want to unlock the administration functions? Quer mesmo desbloquear as funçõesde administração? - + Administration Administração diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 1f5e95e59..9d7920e1c 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -1544,220 +1544,241 @@ + Scheduled server shutdown. + + + + Unknown reason. Неизвестная причина. - + Connection closed Соединение прервано - + The server has terminated your connection. Reason: %1 Ваше подключение было прервано сервером. Причина: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + + Number of players Количество игроков - + Please enter the number of players. Введите количество игроков. - - + + Player %1 Игрок %1 - + About Cockatrice О программе - + Version %1 Версия %1 - + Authors: Разработчики: - + Translators: Переводчики: - + Spanish: Испанский: - + Portugese (Portugal): Португальский: - + Portugese (Brazil): Португальский (Brazil): - + French: Французский: - + Japanese: Японский: - + Russian: Русский: - + Czech: - + Slovak: - - + - - + + + Error Ошибка - + Server timeout Временная ошибка - + Invalid login data. Неверный логин/пароль. - + There is already an active session using this user name. Please close that session first and re-login. Пользователь с таким именем уже подключен. Пожалуйста, закройте это подключение и войдите заново. - + Socket error: %1 Ошибка сокета: %1 - + 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. Вы пытаетесь подключиться к несуществующему серверу. Пожалуйста, обновите Cockatrice или выберите другой сервер. Локальная версия %1, удаленная версия %2. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. Ваш клиент Cockatrice устарел. Пожалуйста, обновите Cockatrice. Локальная версия %1, удаленная версия %2. - + Connecting to %1... Подключение к %1... - + Disconnected Подключение прервано - + Logged in at %1 Подключено к %1 - + &Connect... &Подключение... - + &Disconnect П&рервать подключение - + Start &local game... &Начать локальную игру... - + &Deck editor Редактор &колод - + &Full screen П&олный экран - + Ctrl+F - + &Settings... Н&астройки - + &Exit &Выход - + &Cockatrice - + &About Cockatrice О про&грамме - + &Help &Справка - + Are you sure? Вы уверены? - + There are still open games. Are you sure you want to quit? Вы подключены к игре. Выйти? @@ -2903,40 +2924,73 @@ Local version is %1, remote version is %2. Полное название + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + &Ок + + + + &Cancel + &Отмена + + + + Shut down server + + + TabAdmin - + Update server &message Обновить сооб&щения сервера - + + &Shut down server + + + + Server administration functions Функции администрирования сервера - + &Unlock functions &Разблокировать функции - + &Lock functions &Заблокировать функции - + Unlock administration functions Разблокировать административные права - + Do you really want to unlock the administration functions? Вы действительно хотите разблокировать административные права? - + Administration Администрирование diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 30324e939..835301f8c 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -1390,216 +1390,237 @@ + Scheduled server shutdown. + + + + Unknown reason. - + Connection closed - + The server has terminated your connection. Reason: %1 - + + Scheduled server shutdown + + + + + The server is going to be restarted in %n minute(s). +All running games will be lost. +Reason for shutdown: %1 + + + + + + + + Number of players - + Please enter the number of players. - - + + Player %1 - + About Cockatrice - + Version %1 - + Authors: - + Translators: - + Spanish: - + Portugese (Portugal): - + Portugese (Brazil): - + French: - + Japanese: - + Russian: - + Czech: - + Slovak: - - + - - + + + Error - + Server timeout - + Invalid login data. - + There is already an active session using this user name. Please close that session first and re-login. - + Socket error: %1 - + 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. - + Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Connecting to %1... - + Disconnected - + Logged in at %1 - + &Connect... - + &Disconnect - + Start &local game... - + &Deck editor - + &Full screen - + Ctrl+F - + &Settings... - + &Exit - + &Cockatrice - + &About Cockatrice - + &Help - + Are you sure? - + There are still open games. Are you sure you want to quit? @@ -2705,40 +2726,73 @@ Local version is %1, remote version is %2. + + ShutdownDialog + + + &Reason for shutdown: + + + + + &Time until shutdown (minutes): + + + + + &OK + + + + + &Cancel + + + + + Shut down server + + + TabAdmin - + Update server &message - + + &Shut down server + + + + Server administration functions - + &Unlock functions - + &Lock functions - + Unlock administration functions - + Do you really want to unlock the administration functions? - + Administration diff --git a/common/protocol.h b/common/protocol.h index b72deb107..0cb067ee2 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -167,6 +167,15 @@ public: void setGameId(int _gameId) { static_cast(itemMap.value("game_id"))->setData(_gameId); } }; +class ModeratorCommand : public Command { + Q_OBJECT +public: + ModeratorCommand(const QString &_cmdName) + : Command(_cmdName) + { + } +}; + class AdminCommand : public Command { Q_OBJECT public: diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h index 2d89e883c..b00687cf0 100644 --- a/common/protocol_item_ids.h +++ b/common/protocol_item_ids.h @@ -65,19 +65,21 @@ ItemId_Event_DumpZone = 1063, ItemId_Event_StopDumpZone = 1064, ItemId_Event_RemoveFromList = 1065, ItemId_Event_ServerMessage = 1066, -ItemId_Event_ConnectionClosed = 1067, -ItemId_Event_Message = 1068, -ItemId_Event_GameJoined = 1069, -ItemId_Event_UserLeft = 1070, -ItemId_Event_LeaveRoom = 1071, -ItemId_Event_RoomSay = 1072, -ItemId_Context_ReadyStart = 1073, -ItemId_Context_Concede = 1074, -ItemId_Context_DeckSelect = 1075, -ItemId_Context_UndoDraw = 1076, -ItemId_Context_MoveCard = 1077, -ItemId_Context_Mulligan = 1078, -ItemId_Command_UpdateServerMessage = 1079, -ItemId_Command_BanFromServer = 1080, -ItemId_Other = 1081 +ItemId_Event_ServerShutdown = 1067, +ItemId_Event_ConnectionClosed = 1068, +ItemId_Event_Message = 1069, +ItemId_Event_GameJoined = 1070, +ItemId_Event_UserLeft = 1071, +ItemId_Event_LeaveRoom = 1072, +ItemId_Event_RoomSay = 1073, +ItemId_Context_ReadyStart = 1074, +ItemId_Context_Concede = 1075, +ItemId_Context_DeckSelect = 1076, +ItemId_Context_UndoDraw = 1077, +ItemId_Context_MoveCard = 1078, +ItemId_Context_Mulligan = 1079, +ItemId_Command_UpdateServerMessage = 1080, +ItemId_Command_ShutdownServer = 1081, +ItemId_Command_BanFromServer = 1082, +ItemId_Other = 1083 }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index 17aea3839..69de7319f 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -398,6 +398,12 @@ Event_ServerMessage::Event_ServerMessage(const QString &_message) { insertItem(new SerializableItem_String("message", _message)); } +Event_ServerShutdown::Event_ServerShutdown(const QString &_reason, int _minutes) + : GenericEvent("server_shutdown") +{ + insertItem(new SerializableItem_String("reason", _reason)); + insertItem(new SerializableItem_Int("minutes", _minutes)); +} Event_ConnectionClosed::Event_ConnectionClosed(const QString &_reason) : GenericEvent("connection_closed") { @@ -467,8 +473,14 @@ Command_UpdateServerMessage::Command_UpdateServerMessage() : AdminCommand("update_server_message") { } +Command_ShutdownServer::Command_ShutdownServer(const QString &_reason, int _minutes) + : AdminCommand("shutdown_server") +{ + insertItem(new SerializableItem_String("reason", _reason)); + insertItem(new SerializableItem_Int("minutes", _minutes)); +} Command_BanFromServer::Command_BanFromServer(const QString &_userName, int _minutes) - : AdminCommand("ban_from_server") + : ModeratorCommand("ban_from_server") { insertItem(new SerializableItem_String("user_name", _userName)); insertItem(new SerializableItem_Int("minutes", _minutes)); @@ -541,6 +553,7 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("game_eventstop_dump_zone", Event_StopDumpZone::newItem); itemNameHash.insert("generic_eventremove_from_list", Event_RemoveFromList::newItem); itemNameHash.insert("generic_eventserver_message", Event_ServerMessage::newItem); + itemNameHash.insert("generic_eventserver_shutdown", Event_ServerShutdown::newItem); itemNameHash.insert("generic_eventconnection_closed", Event_ConnectionClosed::newItem); itemNameHash.insert("generic_eventmessage", Event_Message::newItem); itemNameHash.insert("generic_eventgame_joined", Event_GameJoined::newItem); @@ -554,5 +567,6 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("game_event_contextmove_card", Context_MoveCard::newItem); itemNameHash.insert("game_event_contextmulligan", Context_Mulligan::newItem); itemNameHash.insert("cmdupdate_server_message", Command_UpdateServerMessage::newItem); + itemNameHash.insert("cmdshutdown_server", Command_ShutdownServer::newItem); itemNameHash.insert("cmdban_from_server", Command_BanFromServer::newItem); } diff --git a/common/protocol_items.dat b/common/protocol_items.dat index 73369c6b4..14e486c92 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -64,6 +64,7 @@ 3:stop_dump_zone:i,zone_owner_id:s,zone 4:remove_from_list:s,list:s,user_name 4:server_message:s,message +4:server_shutdown:s,reason:i,minutes 4:connection_closed:s,reason 4:message:s,sender_name:s,receiver_name:s,text 4:game_joined:i,game_id:s,game_description:i,player_id:b,spectator:b,spectators_can_talk:b,spectators_see_everything:b,resuming @@ -77,4 +78,5 @@ 6:move_card 6:mulligan:i,number 7:update_server_message -7:ban_from_server:s,user_name:i,minutes \ No newline at end of file +7:shutdown_server:s,reason:i,minutes +8:ban_from_server:s,user_name:i,minutes \ No newline at end of file diff --git a/common/protocol_items.h b/common/protocol_items.h index d58d3dec8..d03a7825e 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -598,6 +598,15 @@ public: static SerializableItem *newItem() { return new Event_ServerMessage; } int getItemId() const { return ItemId_Event_ServerMessage; } }; +class Event_ServerShutdown : public GenericEvent { + Q_OBJECT +public: + Event_ServerShutdown(const QString &_reason = QString(), int _minutes = -1); + QString getReason() const { return static_cast(itemMap.value("reason"))->getData(); }; + int getMinutes() const { return static_cast(itemMap.value("minutes"))->getData(); }; + static SerializableItem *newItem() { return new Event_ServerShutdown; } + int getItemId() const { return ItemId_Event_ServerShutdown; } +}; class Event_ConnectionClosed : public GenericEvent { Q_OBJECT public: @@ -706,7 +715,16 @@ public: static SerializableItem *newItem() { return new Command_UpdateServerMessage; } int getItemId() const { return ItemId_Command_UpdateServerMessage; } }; -class Command_BanFromServer : public AdminCommand { +class Command_ShutdownServer : public AdminCommand { + Q_OBJECT +public: + Command_ShutdownServer(const QString &_reason = QString(), int _minutes = -1); + QString getReason() const { return static_cast(itemMap.value("reason"))->getData(); }; + int getMinutes() const { return static_cast(itemMap.value("minutes"))->getData(); }; + static SerializableItem *newItem() { return new Command_ShutdownServer; } + int getItemId() const { return ItemId_Command_ShutdownServer; } +}; +class Command_BanFromServer : public ModeratorCommand { Q_OBJECT public: Command_BanFromServer(const QString &_userName = QString(), int _minutes = -1); diff --git a/common/protocol_mc.pl b/common/protocol_mc.pl index 31e85b1ff..2b1c96b76 100755 --- a/common/protocol_mc.pl +++ b/common/protocol_mc.pl @@ -80,6 +80,13 @@ while () { $parentConstructorCall = "$baseClass(\"$name1\")"; $constructorParamsH = ""; $constructorParamsCpp = ""; + } elsif ($type == 8) { + $type = 'cmd'; + $namePrefix = 'Command'; + $baseClass = 'ModeratorCommand'; + $parentConstructorCall = "$baseClass(\"$name1\")"; + $constructorParamsH = ""; + $constructorParamsCpp = ""; } $className = $namePrefix . '_' . $name2; $itemEnum .= "ItemId_$className = " . ++$itemId . ",\n"; diff --git a/common/server.cpp b/common/server.cpp index a7e4c683a..e4c68ff9a 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -23,6 +23,7 @@ #include "server_room.h" #include "server_protocolhandler.h" #include "protocol_datastructures.h" +#include #include Server::Server(QObject *parent) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index a3ced63a5..10729b8b0 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -142,6 +142,17 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm default: return RespInvalidCommand; } } + ModeratorCommand *moderatorCommand = qobject_cast(command); + if (moderatorCommand) { + qDebug() << "received ModeratorCommand"; + if (!(userInfo->getUserLevel() & ServerInfo_User::IsModerator)) + return RespLoginNeeded; + + switch (command->getItemId()) { + case ItemId_Command_BanFromServer: return cmdBanFromServer(static_cast(command), cont); + default: return RespInvalidCommand; + } + } AdminCommand *adminCommand = qobject_cast(command); if (adminCommand) { qDebug() << "received AdminCommand"; @@ -149,8 +160,8 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm return RespLoginNeeded; switch (command->getItemId()) { + case ItemId_Command_ShutdownServer: return cmdShutdownServer(static_cast(command), cont); case ItemId_Command_UpdateServerMessage: return cmdUpdateServerMessage(static_cast(command), cont); - case ItemId_Command_BanFromServer: return cmdBanFromServer(static_cast(command), cont); default: return RespInvalidCommand; } } diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index c65d8d020..5817da220 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -87,8 +87,9 @@ private: ResponseCode cmdDumpZone(Command_DumpZone *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdStopDumpZone(Command_StopDumpZone *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); ResponseCode cmdRevealCards(Command_RevealCards *cmd, CommandContainer *cont, Server_Game *game, Server_Player *player); - virtual ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer *cont) = 0; + virtual ResponseCode cmdShutdownServer(Command_ShutdownServer *cmd, CommandContainer *cont) = 0; + virtual ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage *cmd, CommandContainer *cont) = 0; ResponseCode processCommandHelper(Command *command, CommandContainer *cont); private slots: diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index a36e33320..6c16c965a 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -130,12 +130,16 @@ int main(int argc, char *argv[]) testRNG(); Servatrice server(settings); + QObject::connect(&server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection); std::cerr << "-------------------------" << std::endl; std::cerr << "Server initialized." << std::endl; int retval = app.exec(); + std::cerr << "Server quit." << std::endl; + std::cerr << "-------------------------" << std::endl; + delete rng; delete settings; diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index eaca1de6f..0cc2dd96d 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -44,7 +44,7 @@ void Servatrice_TcpServer::incomingConnection(int socketDescriptor) } Servatrice::Servatrice(QSettings *_settings, QObject *parent) - : Server(parent), dbMutex(QMutex::Recursive), settings(_settings), uptime(0) + : Server(parent), dbMutex(QMutex::Recursive), settings(_settings), uptime(0), shutdownTimer(0) { pingClock = new QTimer(this); connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); @@ -119,6 +119,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) Servatrice::~Servatrice() { prepareDestroy(); + QSqlDatabase::database().close(); } bool Servatrice::openDatabase() @@ -233,7 +234,7 @@ ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool co int userLevel = ServerInfo_User::IsUser | ServerInfo_User::IsRegistered; if (is_admin == 1) - userLevel |= ServerInfo_User::IsAdmin; + userLevel |= ServerInfo_User::IsAdmin | ServerInfo_User::IsModerator; else if (is_admin == 2) userLevel |= ServerInfo_User::IsModerator; @@ -388,4 +389,38 @@ void Servatrice::statusUpdate() execSqlQuery(query); } +void Servatrice::scheduleShutdown(const QString &reason, int minutes) +{ + QMutexLocker locker(&serverMutex); + + shutdownReason = reason; + shutdownMinutes = minutes + 1; + if (minutes > 0) { + shutdownTimer = new QTimer; + connect(shutdownTimer, SIGNAL(timeout()), this, SLOT(shutdownTimeout())); + shutdownTimer->start(60000); + } + shutdownTimeout(); +} + +void Servatrice::shutdownTimeout() +{ + QMutexLocker locker(&serverMutex); + + --shutdownMinutes; + + GenericEvent *event; + if (shutdownMinutes) + event = new Event_ServerShutdown(shutdownReason, shutdownMinutes); + else + event = new Event_ConnectionClosed("server_shutdown"); + + for (int i = 0; i < clients.size(); ++i) + clients[i]->sendProtocolItem(event, false); + delete event; + + if (!shutdownMinutes) + deleteLater(); +} + const QString Servatrice::versionString = "Servatrice 0.20110527"; diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index f1174c91d..1a3d1d090 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -50,6 +50,7 @@ class Servatrice : public Server private slots: void statusUpdate(); void updateBanTimer(); + void shutdownTimeout(); public: QMutex dbMutex; static const QString versionString; @@ -76,6 +77,7 @@ public: bool getUserBanned(Server_ProtocolHandler *client, const QString &userName) const; void addAddressBan(const QHostAddress &address, int minutes) { addressBanList.append(QPair(address, minutes)); } void addNameBan(const QString &name, int minutes) { nameBanList.append(QPair(name, minutes)); } + void scheduleShutdown(const QString &reason, int minutes); protected: bool userExists(const QString &user); AuthenticationResult checkUserPassword(const QString &user, const QString &password); @@ -92,6 +94,10 @@ private: int maxGameInactivityTime, maxPlayerInactivityTime; int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser; ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete); + + QString shutdownReason; + int shutdownMinutes; + QTimer *shutdownTimer; }; #endif diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index f02747cae..14628a423 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -454,8 +454,8 @@ ResponseCode ServerSocketInterface::cmdDeckDownload(Command_DeckDownload *cmd, C return RespNothing; } -// ADMIN FUNCTIONS. -// Permission is checked by the calling function. +// MODERATOR FUNCTIONS. +// May be called by admins and moderators. Permission is checked by the calling function. ResponseCode ServerSocketInterface::cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/) { @@ -463,6 +463,15 @@ ResponseCode ServerSocketInterface::cmdUpdateServerMessage(Command_UpdateServerM return RespOk; } +// ADMIN FUNCTIONS. +// Permission is checked by the calling function. + +ResponseCode ServerSocketInterface::cmdShutdownServer(Command_ShutdownServer *cmd, CommandContainer * /*cont*/) +{ + servatrice->scheduleShutdown(cmd->getReason(), cmd->getMinutes()); + return RespOk; +} + ResponseCode ServerSocketInterface::cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer * /*cont*/) { QString userName = cmd->getUserName(); diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index 8f7b937ec..a155b4218 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -66,8 +66,9 @@ private: ResponseCode cmdDeckUpload(Command_DeckUpload *cmd, CommandContainer *cont); DeckList *getDeckFromDatabase(int deckId); ResponseCode cmdDeckDownload(Command_DeckDownload *cmd, CommandContainer *cont); - ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage *cmd, CommandContainer *cont); ResponseCode cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer *cont); + ResponseCode cmdShutdownServer(Command_ShutdownServer *cmd, CommandContainer *cont); + ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage *cmd, CommandContainer *cont); public: ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0); ~ServerSocketInterface(); From cc795a2dd73357e9370e2d39ee8d9ad8e55e5bf7 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 25 Jun 2011 01:26:20 +0200 Subject: [PATCH 59/87] don't call alert() when a message in a public chat is received --- cockatrice/src/tab.h | 2 +- cockatrice/src/tab_room.cpp | 2 +- cockatrice/src/tab_supervisor.cpp | 7 ++++--- cockatrice/src/tab_supervisor.h | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cockatrice/src/tab.h b/cockatrice/src/tab.h index 31fdcbab6..5f50813cc 100644 --- a/cockatrice/src/tab.h +++ b/cockatrice/src/tab.h @@ -9,7 +9,7 @@ class TabSupervisor; class Tab : public QWidget { Q_OBJECT signals: - void userEvent(); + void userEvent(bool globalEvent = true); protected: QMenu *tabMenu; TabSupervisor *tabSupervisor; diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index f40458cdd..d72e13ef5 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -262,5 +262,5 @@ void TabRoom::processLeaveRoomEvent(Event_LeaveRoom *event) void TabRoom::processSayEvent(Event_RoomSay *event) { chatView->appendMessage(event->getPlayerName(), event->getMessage()); - emit userEvent(); + emit userEvent(false); } diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index 1dfe7d443..c9cdc5d57 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -101,7 +101,7 @@ void TabSupervisor::retranslateUi() int TabSupervisor::myAddTab(Tab *tab) { - connect(tab, SIGNAL(userEvent()), this, SLOT(tabUserEvent())); + connect(tab, SIGNAL(userEvent(bool)), this, SLOT(tabUserEvent(bool))); return addTab(tab, tab->getTabText()); } @@ -299,14 +299,15 @@ void TabSupervisor::talkLeft(TabMessage *tab) removeTab(indexOf(tab)); } -void TabSupervisor::tabUserEvent() +void TabSupervisor::tabUserEvent(bool globalEvent) { Tab *tab = static_cast(sender()); if (tab != currentWidget()) { tab->setContentsChanged(true); setTabIcon(indexOf(tab), *tabChangedIcon); } - QApplication::alert(this); + if (globalEvent) + QApplication::alert(this); } void TabSupervisor::processRoomEvent(RoomEvent *event) diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index 439ac1f88..5d7a2c9bc 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -78,7 +78,7 @@ private slots: void processUserLeft(const QString &userName); void processUserJoined(const QString &userName); void talkLeft(TabMessage *tab); - void tabUserEvent(); + void tabUserEvent(bool globalEvent); void processRoomEvent(RoomEvent *event); void processGameEventContainer(GameEventContainer *cont); void processMessageEvent(Event_Message *event); From d892d320eabf542664efb61970a86eaefa5593b6 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 25 Jun 2011 15:58:38 +0200 Subject: [PATCH 60/87] dynamic compression support --- cockatrice/src/localserverinterface.h | 3 +- cockatrice/src/remoteclient.cpp | 1 + common/protocol.cpp | 4 +- common/serializable_item.cpp | 49 ++++++++++++++++++++++-- common/serializable_item.h | 8 +++- common/server_protocolhandler.cpp | 20 ++++++++-- common/server_protocolhandler.h | 1 + servatrice/src/serversocketinterface.cpp | 9 ++++- servatrice/src/serversocketinterface.h | 3 ++ 9 files changed, 85 insertions(+), 13 deletions(-) diff --git a/cockatrice/src/localserverinterface.h b/cockatrice/src/localserverinterface.h index 261941476..1db974129 100644 --- a/cockatrice/src/localserverinterface.h +++ b/cockatrice/src/localserverinterface.h @@ -21,12 +21,13 @@ private: ResponseCode cmdBanFromServer(Command_BanFromServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdShutdownServer(Command_ShutdownServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; } +protected: + bool getCompressionSupport() const { return false; } public: LocalServerInterface(LocalServer *_server); ~LocalServerInterface(); void sendProtocolItem(ProtocolItem *item, bool deleteItem = true); - signals: void itemToClient(ProtocolItem *item); public slots: diff --git a/cockatrice/src/remoteclient.cpp b/cockatrice/src/remoteclient.cpp index fac63019a..8f0844870 100644 --- a/cockatrice/src/remoteclient.cpp +++ b/cockatrice/src/remoteclient.cpp @@ -83,6 +83,7 @@ void RemoteClient::readData() xmlWriter->writeStartDocument(); xmlWriter->writeStartElement("cockatrice_client_stream"); xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion)); + xmlWriter->writeAttribute("comp", "1"); topLevelItem = new TopLevelProtocolItem; connect(topLevelItem, SIGNAL(protocolItemReceived(ProtocolItem *)), this, SLOT(processProtocolItem(ProtocolItem *))); diff --git a/common/protocol.cpp b/common/protocol.cpp index fe3997add..1129116e5 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -74,7 +74,7 @@ TopLevelProtocolItem::TopLevelProtocolItem() bool TopLevelProtocolItem::readCurrentItem(QXmlStreamReader *xml) { if (currentItem) { - if (currentItem->readElement(xml)) { + if (currentItem->read(xml)) { emit protocolItemReceived(currentItem); currentItem = 0; } @@ -92,6 +92,8 @@ bool TopLevelProtocolItem::readElement(QXmlStreamReader *xml) currentItem = dynamic_cast(getNewItem(childName + childSubType)); if (!currentItem) currentItem = new ProtocolItem_Invalid; + if (xml->attributes().value("comp").toString().toInt() == 1) + currentItem->setCompressed(true); readCurrentItem(xml); } diff --git a/common/serializable_item.cpp b/common/serializable_item.cpp index 9c1a7c81c..42c142514 100644 --- a/common/serializable_item.cpp +++ b/common/serializable_item.cpp @@ -1,7 +1,8 @@ #include "serializable_item.h" #include #include -#include +#include + QHash SerializableItem::itemNameHash; SerializableItem *SerializableItem::getNewItem(const QString &name) @@ -16,6 +17,32 @@ void SerializableItem::registerSerializableItem(const QString &name, NewItemFunc itemNameHash.insert(name, func); } +bool SerializableItem::read(QXmlStreamReader *xml) +{ + if (!compressed) + return readElement(xml); + if (xml->isEndElement() && (xml->name() == itemType)) { + QByteArray uncompressedData = "" + qUncompress(QByteArray::fromBase64(compressedData)) + ""; + compressedData.clear(); + QBuffer compressedBuffer(&uncompressedData); + compressedBuffer.open(QIODevice::ReadOnly); + QXmlStreamReader *xml2 = new QXmlStreamReader(&compressedBuffer); + while (!xml2->atEnd()) { + xml2->readNext(); + if (xml2->name() == "d") + continue; + readElement(xml2); + } + delete xml2; + compressedBuffer.close(); + + return readElement(xml); + } else { + compressedData.append(xml->text().toString()); + return false; + } +} + bool SerializableItem::readElement(QXmlStreamReader *xml) { if (xml->isEndElement() && (xml->name() == itemType)) @@ -31,7 +58,19 @@ void SerializableItem::write(QXmlStreamWriter *xml) xml->writeStartElement(itemType); if (!itemSubType.isEmpty()) xml->writeAttribute("type", itemSubType); - writeElement(xml); + if (compressed) { + xml->writeAttribute("comp", "1"); + + QBuffer compressBuffer; + compressBuffer.open(QIODevice::WriteOnly); + QXmlStreamWriter *xml2 = new QXmlStreamWriter(&compressBuffer); + writeElement(xml2); + delete xml2; + compressBuffer.close(); + + xml->writeCharacters(qCompress(compressBuffer.data()).toBase64()); + } else + writeElement(xml); xml->writeEndElement(); } @@ -47,7 +86,7 @@ SerializableItem_Map::~SerializableItem_Map() bool SerializableItem_Map::readElement(QXmlStreamReader *xml) { if (currentItem) { - if (currentItem->readElement(xml)) + if (currentItem->read(xml)) currentItem = 0; return false; } else if (firstItem) @@ -57,6 +96,7 @@ bool SerializableItem_Map::readElement(QXmlStreamReader *xml) else if (xml->isStartElement()) { QString childName = xml->name().toString(); QString childSubType = xml->attributes().value("type").toString(); + bool childCompressed = xml->attributes().value("comp").toString().toInt() == 1; currentItem = itemMap.value(childName); if (!currentItem) { currentItem = getNewItem(childName + childSubType); @@ -64,7 +104,8 @@ bool SerializableItem_Map::readElement(QXmlStreamReader *xml) if (!currentItem) currentItem = new SerializableItem_Invalid(childName); } - if (currentItem->readElement(xml)) + currentItem->setCompressed(childCompressed); + if (currentItem->read(xml)) currentItem = 0; } return SerializableItem::readElement(xml); diff --git a/common/serializable_item.h b/common/serializable_item.h index 979ebb981..50da5e368 100644 --- a/common/serializable_item.h +++ b/common/serializable_item.h @@ -15,6 +15,10 @@ class QXmlStreamWriter; class SerializableItem : public QObject { Q_OBJECT +private: + bool compressed; + QByteArray compressedData; + QXmlStreamReader *compressedReader; protected: typedef SerializableItem *(*NewItemFunction)(); static QHash itemNameHash; @@ -23,7 +27,7 @@ protected: bool firstItem; public: SerializableItem(const QString &_itemType, const QString &_itemSubType = QString()) - : QObject(), itemType(_itemType), itemSubType(_itemSubType), firstItem(true) { } + : QObject(), compressed(false), itemType(_itemType), itemSubType(_itemSubType), firstItem(true) { } static void registerSerializableItem(const QString &name, NewItemFunction func); static SerializableItem *getNewItem(const QString &name); const QString &getItemType() const { return itemType; } @@ -31,6 +35,8 @@ public: virtual bool readElement(QXmlStreamReader *xml); virtual void writeElement(QXmlStreamWriter *xml) = 0; virtual bool isEmpty() const = 0; + void setCompressed(bool _compressed) { compressed = _compressed; } + bool read(QXmlStreamReader *xml); void write(QXmlStreamWriter *xml); }; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 10729b8b0..b461f833e 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -286,7 +286,10 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain if (authState == WouldOverwriteOldSession) return RespWouldOverwriteOldSession; - enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage())); + ProtocolItem *serverMessage = new Event_ServerMessage(server->getLoginMessage()); + if (getCompressionSupport()) + serverMessage->setCompressed(true); + enqueueProtocolItem(serverMessage); QList _buddyList, _ignoreList; if (authState == PasswordRight) { @@ -303,7 +306,10 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain _ignoreList.append(new ServerInfo_User(ignoreIterator.next().value())); } - cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList)); + ProtocolResponse *resp = new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList); + if (getCompressionSupport()) + resp->setCompressed(true); + cont->setResponse(resp); return RespNothing; } @@ -395,7 +401,10 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC } } - cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, r->getInfo(true))); + ServerInfo_Room *info = r->getInfo(true); + if (getCompressionSupport()) + info->setCompressed(true); + cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, info)); return RespNothing; } @@ -444,7 +453,10 @@ ResponseCode Server_ProtocolHandler::cmdListUsers(Command_ListUsers * /*cmd*/, C acceptsUserListChanges = true; - cont->setResponse(new Response_ListUsers(cont->getCmdId(), RespOk, resultList)); + ProtocolResponse *resp = new Response_ListUsers(cont->getCmdId(), RespOk, resultList); + if (getCompressionSupport()) + resp->setCompressed(true); + cont->setResponse(resp); return RespNothing; } diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 5817da220..a73c30080 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -30,6 +30,7 @@ protected: QMap buddyList, ignoreList; void prepareDestroy(); + virtual bool getCompressionSupport() const = 0; private: QList itemQueue; QList messageSizeOverTime, messageCountOverTime; diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 14628a423..769e65888 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -33,7 +33,7 @@ #include "server_logger.h" ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent) - : Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0) + : Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0), compressionSupport(false) { xmlWriter = new QXmlStreamWriter(&xmlBuffer); xmlReader = new QXmlStreamReader; @@ -101,6 +101,8 @@ void ServerSocketInterface::readClient() if (topLevelItem) topLevelItem->readElement(xmlReader); else if (xmlReader->isStartElement() && (xmlReader->name().toString() == "cockatrice_client_stream")) { + if (xmlReader->attributes().value("comp").toString().toInt() == 1) + compressionSupport = true; topLevelItem = new TopLevelProtocolItem; connect(topLevelItem, SIGNAL(protocolItemReceived(ProtocolItem *)), this, SLOT(processProtocolItem(ProtocolItem *))); } @@ -295,7 +297,10 @@ ResponseCode ServerSocketInterface::cmdDeckList(Command_DeckList * /*cmd*/, Comm if (!deckListHelper(root)) return RespContextError; - cont->setResponse(new Response_DeckList(cont->getCmdId(), RespOk, root)); + ProtocolResponse *resp = new Response_DeckList(cont->getCmdId(), RespOk, root); + if (getCompressionSupport()) + resp->setCompressed(true); + cont->setResponse(resp); return RespNothing; } diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index a155b4218..14cf7030e 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -51,6 +51,7 @@ private: QXmlStreamReader *xmlReader; QString xmlBuffer; TopLevelProtocolItem *topLevelItem; + bool compressionSupport; int getUserIdInDB(const QString &name) const; ResponseCode cmdAddToList(Command_AddToList *cmd, CommandContainer *cont); @@ -69,6 +70,8 @@ private: ResponseCode cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer *cont); ResponseCode cmdShutdownServer(Command_ShutdownServer *cmd, CommandContainer *cont); ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage *cmd, CommandContainer *cont); +protected: + bool getCompressionSupport() const { return compressionSupport; } public: ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0); ~ServerSocketInterface(); From 4b84168bdaaa24b080db08c205077ae2d15f805d Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 25 Jun 2011 17:50:28 +0200 Subject: [PATCH 61/87] client/server version bump; eventConnectionStateChanged --- cockatrice/src/main.h | 2 +- cockatrice/src/messagelogwidget.cpp | 9 + cockatrice/src/messagelogwidget.h | 1 + cockatrice/src/player.cpp | 6 + cockatrice/src/player.h | 3 + cockatrice/translations/cockatrice_cs.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_de.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_en.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_es.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_fr.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_ja.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_pl.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_pt-br.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_pt.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_ru.ts | 198 ++++++++++---------- cockatrice/translations/cockatrice_sk.ts | 198 ++++++++++---------- common/protocol_item_ids.h | 79 ++++---- common/protocol_items.cpp | 6 + common/protocol_items.dat | 1 + common/protocol_items.h | 8 + common/server_game.cpp | 7 + common/server_game.h | 1 + common/server_protocolhandler.cpp | 5 +- servatrice/src/servatrice.cpp | 2 +- 24 files changed, 1232 insertions(+), 1076 deletions(-) diff --git a/cockatrice/src/main.h b/cockatrice/src/main.h index f8e5a1475..3e7ad1ead 100644 --- a/cockatrice/src/main.h +++ b/cockatrice/src/main.h @@ -9,7 +9,7 @@ extern CardDatabase *db; extern QTranslator *translator; const QString translationPrefix = "cockatrice"; -const QString versionString = "0.20110303"; +const QString versionString = "0.20110625"; void installNewTranslator(); diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index be218d6bc..9bb867067 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -117,6 +117,14 @@ void MessageLogWidget::logGameStart() append(tr("The game has started.")); } +void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState) +{ + if (connectionState) + append(tr("%1 has restored connection to the game.").arg(sanitizeHtml(player->getName()))); + else + append(tr("%1 has lost connection to the game.").arg(sanitizeHtml(player->getName()))); +} + void MessageLogWidget::logSay(Player *player, QString message) { append(QString("getLocal() ? "red" : "#0000fe") + QString("\">%1: %2").arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(message))); @@ -499,6 +507,7 @@ void MessageLogWidget::containerProcessingDone() void MessageLogWidget::connectToPlayer(Player *player) { + connect(player, SIGNAL(logConnectionStateChanged(Player *, bool)), this, SLOT(logConnectionStateChanged(Player *, bool))); connect(player, SIGNAL(logSay(Player *, QString)), this, SLOT(logSay(Player *, QString))); connect(player, SIGNAL(logShuffle(Player *, CardZone *)), this, SLOT(logShuffle(Player *, CardZone *))); connect(player, SIGNAL(logRollDie(Player *, int, int)), this, SLOT(logRollDie(Player *, int, int))); diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index fe548547b..efc8f6b5b 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -65,6 +65,7 @@ public slots: void logNotReadyStart(Player *player); void logConcede(Player *player); void logGameStart(); + void logConnectionStateChanged(Player *player, bool connectionState); void logSay(Player *player, QString message); void logSpectatorSay(QString spectatorName, QString message); void logShuffle(Player *player, CardZone *zone); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 7ebf9cdfe..6dc53152c 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -706,6 +706,11 @@ void Player::setCardAttrHelper(GameEventContext *context, CardItem *card, const } } +void Player::eventConnectionStateChanged(Event_ConnectionStateChanged *event) +{ + emit logConnectionStateChanged(this, event->getConnected()); +} + void Player::eventSay(Event_Say *event) { emit logSay(this, event->getMessage()); @@ -1036,6 +1041,7 @@ void Player::processGameEvent(GameEvent *event, GameEventContext *context) { qDebug() << "player event: id=" << event->getItemId(); switch (event->getItemId()) { + case ItemId_Event_ConnectionStateChanged: eventConnectionStateChanged(static_cast(event)); break; case ItemId_Event_Say: eventSay(static_cast(event)); break; case ItemId_Event_Shuffle: eventShuffle(static_cast(event)); break; case ItemId_Event_RollDie: eventRollDie(static_cast(event)); break; diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 8645d70f0..72f19c260 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -26,6 +26,7 @@ class CommandContainer; class GameCommand; class GameEvent; class GameEventContext; +class Event_ConnectionStateChanged; class Event_Say; class Event_Shuffle; class Event_RollDie; @@ -69,6 +70,7 @@ class Player : public QObject, public QGraphicsItem { signals: void newCardAdded(AbstractCardItem *card); // Log events + void logConnectionStateChanged(Player *player, bool connectionState); void logSay(Player *player, QString message); void logShuffle(Player *player, CardZone *zone); void logRollDie(Player *player, int sides, int roll); @@ -176,6 +178,7 @@ private: void initSayMenu(); + void eventConnectionStateChanged(Event_ConnectionStateChanged *event); void eventSay(Event_Say *event); void eventShuffle(Event_Shuffle *event); void eventRollDie(Event_RollDie *event); diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index bea2660ef..43f214c84 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -1718,17 +1718,27 @@ Local version is %1, remote version is %2. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1737,188 +1747,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1927,57 +1937,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1986,7 +1996,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -1995,7 +2005,7 @@ Local version is %1, remote version is %2. - + red @@ -2004,7 +2014,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2013,7 +2023,7 @@ Local version is %1, remote version is %2. - + green @@ -2022,162 +2032,162 @@ Local version is %1, remote version is %2. - + his permanents - + her permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2536,7 +2546,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2561,27 +2571,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 33c229395..38e343481 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -2485,8 +2485,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten - - + + a card eine Karte @@ -2629,12 +2629,22 @@ Lokale Version ist %1, Serverversion ist %2. %1 hat das Spiel aufgegeben. - + + %1 has restored connection to the game. + %1 ist wieder mit dem Spiel verbunden. + + + + %1 has lost connection to the game. + %1 hat die Verbindung zum Spiel verloren. + + + %1 shuffles %2. %1 mischt %2. - + %1 rolls a %2 with a %3-sided die. %1 würfelt eine %2 mit einem %3-seitigen Würfel. @@ -2647,7 +2657,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten. - + %1 draws %n card(s). %1 zieht eine Karte. @@ -2655,182 +2665,182 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 undoes his last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes her last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes his last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + %1 undoes her last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + the bottom card of her library die unterste Karte ihrer Bibliothek - + from the bottom of his library , die unterste Karte seiner Bibliothek, - + from the bottom of her library , die unterste Karte ihrer Bibliothek, - + the top card of his library die oberste Karte seiner Bibliothek - + the top card of her library die oberste Karte ihrer Bibliothek - + from the top of his library , die oberste Karte seiner Bibliothek, - + from the top of her library , die oberste Karte ihrer Bibliothek, - + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + from the stack vom Stapel - + %1 gives %2 control over %3. %1 überlässt %2 die Kontrolle über %3. - + %1 puts %2 into play tapped%3. %1 bringt %2 getappt%3 ins Spiel. - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + %1 puts %2%3 into her library. %1 legt %2%3 in ihre Bibliothek. - + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + %1 puts %2%3 on bottom of her library. %1 legt %2%3 unter ihre Bibliothek. - + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 on top of her library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + %1 puts %2%3 into her library at position %4. %1 legt %2%3 in ihre Bibliothek an %4. Stelle. - + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 plays %2%3. %1 spielt %2%3 aus. - + %1 takes a mulligan to %n. %1 nimmt einen Mulligan auf %n. @@ -2838,52 +2848,52 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 draws his initial hand. %1 zieht seine Starthand. - + %1 draws her initial hand. %1 zieht ihre Starthand. - + %1 flips %2 face-down. %1 wendet %2 auf die Rückseite. - + %1 flips %2 face-up. %1 wendet %2 auf die Vorderseite. - + %1 destroys %2. %1 zerstört %2. - + %1 attaches %2 to %3's %4. %1 legt %2 an %3s %4 an. - + %1 unattaches %2. %1 löst %2 ab. - + %1 creates token: %2%3. %1 erstellt Token: %2%3. - + %1 points from %2's %3 to %4. %1 zeigt von %2s %3 auf %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 legt eine %2 Marke auf %3 (jetzt %4). @@ -2891,7 +2901,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 entfernt eine %2 Marke von %3 (jetzt %4). @@ -2899,27 +2909,27 @@ Lokale Version ist %1, Serverversion ist %2. - + her permanents ihre bleibenden Karten - + %1 randomly reveals %2%3 to %4. %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3. %1 zeigt zufällig %2%3 offen vor. - + %1 reveals %2%3 to %4. %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3. %1 zeigt %2%3 offen vor. @@ -2928,7 +2938,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 erstellt einen Spielstein: %2 (%3). - + %1 points from %2's %3 to %4's %5. %1 zeigt von %2s %3 auf %4s %5. @@ -2947,7 +2957,7 @@ Lokale Version ist %1, Serverversion ist %2. - + red rote @@ -2955,7 +2965,7 @@ Lokale Version ist %1, Serverversion ist %2. - + yellow gelbe @@ -2963,7 +2973,7 @@ Lokale Version ist %1, Serverversion ist %2. - + green grüne @@ -2971,22 +2981,22 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 sets counter %2 to %3 (%4%5). %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets PT of %2 to %3. %1 setzt Kampfwerte von %2 auf %3. - + %1 sets annotation of %2 to %3. %1 versieht %2 mit dem Hinweis %3. - + %1 is looking at the top %2 cards %3. %1 sieht sich die obersten %2 Karten %3 an. @@ -3083,7 +3093,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4). - + %1 %2 %3. %1 %2 %3. @@ -3096,22 +3106,22 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. %1 sieht sich %2 an. - + %1 stops looking at %2. %1 sieht sich %2 nicht mehr an. - + %1 reveals %2 to %3. %1 zeigt %3 %2. - + %1 reveals %2. %1 zeigt %2 offen vor. @@ -3132,7 +3142,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zeigt %2 aus %3 offen vor. - + ending phase die Zugendphase @@ -3161,57 +3171,57 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich %2s %3 nicht mehr an - + It is now %1's turn. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -3220,7 +3230,7 @@ Lokale Version ist %1, Serverversion ist %2. das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -3229,12 +3239,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 bewegt %2 %3 nach %4 - + taps tappt - + untaps enttappt @@ -3259,7 +3269,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4) - + his permanents seine bleibenden Karten @@ -3272,12 +3282,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 setzt Zähler "%2" auf %3 (%4%5) - + %1 sets %2 to not untap normally. %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. %1 setzt %2 auf normales Enttappen. @@ -3792,7 +3802,7 @@ Lokale Version ist %1, Serverversion ist %2. - + Number: Anzahl: @@ -3807,27 +3817,27 @@ Lokale Version ist %1, Serverversion ist %2. Oberste Karten ins Exil schicken - + Set power/toughness Kampfwerte setzen - + Please enter the new PT: Bitte die neuen Kampfwerte eingeben: - + Set annotation Hinweis setzen - + Please enter the new annotation: Bitte den Hinweis eingeben: - + Set counters Setze Zählmarken diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index a0cd85a43..02e8057db 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -1667,17 +1667,27 @@ Local version is %1, remote version is %2. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). %1 draws a card. @@ -1685,208 +1695,208 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1905,7 +1915,7 @@ Local version is %1, remote version is %2. - + red @@ -1913,7 +1923,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1921,7 +1931,7 @@ Local version is %1, remote version is %2. - + green @@ -1929,22 +1939,22 @@ Local version is %1, remote version is %2. - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. @@ -1999,7 +2009,7 @@ Local version is %1, remote version is %2. - + %1 takes a mulligan to %n. @@ -2007,32 +2017,32 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 places a %2 counter on %3 (now %4). @@ -2040,7 +2050,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 removes a %2 counter from %3 (now %4). @@ -2048,142 +2058,142 @@ Local version is %1, remote version is %2. - + her permanents - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2542,7 +2552,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2567,27 +2577,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 607579844..adb9e23a7 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -2040,17 +2040,27 @@ La versión local es %1, la versión remota es %2. %1 ya no está listo para empezar el juego. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. %1 sacó un %2 con un dado de %3 caras. - + %1 draws %n card(s). %1 roba %n carta. @@ -2058,208 +2068,208 @@ La versión local es %1, la versión remota es %2. - + %1 undoes his last draw. %1 deshace su último robo. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 deshace su último robo (%2). - + %1 undoes her last draw (%2). - + from table de la mesa - + from graveyard del cementerio - + from exile del exilio - + from hand de la mano - + the bottom card of his library el fondo de la biblioteca - + the bottom card of her library - + from the bottom of his library del fondo de la biblioteca - + from the bottom of her library - + the top card of his library la parte superior de la biblioteca - + the top card of her library - + from the top of his library de la parte superior de la biblioteca - + from the top of her library - + from library de la biblioteca - + from sideboard de la reserva - + from the stack de la pila - + %1 gives %2 control over %3. %1 entrega a %2 el control sobre %3. - + %1 puts %2 into play tapped%3. %1 pone %2 en juego%3 girado. - + %1 puts %2 into play%3. %1 pone %2 en juego%3. - + %1 puts %2%3 into graveyard. %1 pone %2%3 en el cementerio. - + %1 exiles %2%3. %1 exilia %2%3. - + %1 moves %2%3 to hand. %1 mueve %2%3 a la mano. - + %1 puts %2%3 into his library. %1 pone %2%3 en la biblioteca. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 pone %2%3 en la parte inferior de su biblioteca. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 pone %2%3 en la parte superior de su biblioteca. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 pone %2%3 en su biblioteca en la posición %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 mueve %2%3 a la reserva. - + %1 plays %2%3. %1 juega %2%3. - - + + a card una carta - + %1 flips %2 face-down. %1 voltea %2 boca abajo. - + %1 flips %2 face-up. %1 voltea %2 boca arriba. - + %1 attaches %2 to %3's %4. %1 anexa %2 a el %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 apunta desde el %3 de %2 al %5 de %4. @@ -2278,7 +2288,7 @@ La versión local es %1, la versión remota es %2. - + red rojo @@ -2286,7 +2296,7 @@ La versión local es %1, la versión remota es %2. - + yellow amarillo @@ -2294,7 +2304,7 @@ La versión local es %1, la versión remota es %2. - + green verde @@ -2302,22 +2312,22 @@ La versión local es %1, la versión remota es %2. - + %1 sets counter %2 to %3 (%4%5). %1 establece los contadores de %2 a %3 (%4%5). - + %1 sets PT of %2 to %3. %1 establece F/R de %2 a %3. - + %1 sets annotation of %2 to %3. %1 establece la anotación de %2 a %3. - + %1 is looking at the top %2 cards %3. %1 esta mirando las primeras %2 cartas de %3. @@ -2380,22 +2390,22 @@ La versión local es %1, la versión remota es %2. %1 roba %2 cartas. - + %1 destroys %2. %1 destruye %2. - + %1 creates token: %2%3. %1 crea una ficha: %2%3. - + %1 points from %2's %3 to %4. %1 apunta desde el %3 de %2 a %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 pone %n %2 contador en %3 (ahora %4). @@ -2403,7 +2413,7 @@ La versión local es %1, la versión remota es %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remueve %n %2 contador en %3 (ahora %4). @@ -2411,37 +2421,37 @@ La versión local es %1, la versión remota es %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está mirando: %2. - + %1 stops looking at %2. %1 termina de mirar: %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase de fin de turno - + It is now %1's turn. Es el turno de %1. @@ -2450,7 +2460,7 @@ La versión local es %1, la versión remota es %2. %1 baraja su biblioteca. - + %1 takes a mulligan to %n. @@ -2458,117 +2468,117 @@ La versión local es %1, la versión remota es %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + her permanents - + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3 a %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step paso de enderezar - + upkeep step paso de mantenimiento - + draw step paso de robar - + first main phase primera fase principal - + beginning of combat step paso de inicio de combate - + declare attackers step paso de declarar atacantes - + declare blockers step paso de declarar bloqueadores - + combat damage step paso de daño de combate - + end of combat step paso de fin de combate - + second main phase segunda fase principal - + It is now the %1. Ahora es el %1. - + taps gira - + untaps endereza - + %1 sets %2 to not untap normally. %1 establece que %2 no se endereze normalmente. - + %1 sets %2 to untap normally. %1 establece que %2 se endereze normalmente. - + his permanents sus permanentes @@ -2935,7 +2945,7 @@ La versión local es %1, la versión remota es %2. - + Number: Número: @@ -2960,27 +2970,27 @@ La versión local es %1, la versión remota es %2. Número de caras: - + Set power/toughness Establecer fuerza/resistencia - + Please enter the new PT: Por favor, introduzca la nueva F/R: - + Set annotation Escribir anotación - + Please enter the new annotation: Por favor, introduza la nueva anotación: - + Set counters Establecer contadores diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 3573db24b..c89507574 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -1952,7 +1952,7 @@ La version la plus récente est %1, l'ancienne version est %2.%1 mélange sa bibliothèque. - + %1 rolls a %2 with a %3-sided die. is it always a dice? %1 lance un %2 à %3 faces. @@ -1966,169 +1966,179 @@ La version la plus récente est %1, l'ancienne version est %2.%1 pioche %2 cartes. - + from table depuis le champ de bataille - + from graveyard depuis son cimetière - + from exile depuis la zone exil - + from hand depuis sa main - + the bottom card of his library la carte du dessous de sa bibliothèque - + the bottom card of her library - + from the bottom of his library du dessous de sa bibliothèque - + from the bottom of her library - + the top card of his library le carte du dessus de sa bibliothèque - + the top card of her library - + from the top of his library du dessus de sa bibliothèque - + from the top of her library - + from library depuis sa bibliothèque - + from sideboard depuis sa réserve - + from the stack depuis la pile - + %1 puts %2 into play tapped%3. %1 met %2 en jeu engagé%3. - + %1 puts %2 into play%3. what is %3? plz exemple (resp. by Ranma : XX met island en jeu -depuis sa main-.) %1 met %2 en jeu %3. - + %1 puts %2%3 into graveyard. %1 met %2%3 dans son cimetière. - + %1 exiles %2%3. %1 exile %2%3. - + %1 moves %2%3 to hand. %1 met %2%3 dans sa main. - + %1 puts %2%3 into his library. %1 met %2%3 dans sa bibliothèque. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 met %2%3 en-dessous de sa bibliothèque. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 met %2%3 au-dessus de sa bibliothèque. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 met %2%3 dans sa bibliothèque à la position n°%4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 met %2%3 à sa réserve. - + %1 plays %2%3. %1 joue %2%3. - - + + a card une carte - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 draws %n card(s). %1 pioche %n carte. @@ -2136,32 +2146,32 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 undoes his last draw. %1 annule sa dernière pioche. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 annule sa dernière pioche (%2). - + %1 undoes her last draw (%2). - + %1 gives %2 control over %3. %1 donne le contrôle de %2 à %3. - + %1 takes a mulligan to %n. @@ -2169,54 +2179,54 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. %1 retourne %2 face cachée. - + %1 flips %2 face-up. %1 retourne %2 face visible. - + %1 destroys %2. %1 détruit %2. - + %1 attaches %2 to %3's %4. need exemple (Resp'.by Ranma: JoueurA attache Adventuring Gear sur -Plated Geopede- de -JoueurB-.) %1 attache %2 sur %4 de %3. - + %1 unattaches %2. %1 détache %2. - + %1 creates token: %2%3. %1 crée un jeton %2%3. - + %1 points from %2's %3 to %4. need exemple %1 désigne le %3 de %2 à %4. - + %1 points from %2's %3 to %4's %5. need exemple %1 désigne le %3 de %2 à %5 de %4. @@ -2238,7 +2248,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 places %n %2 counter(s) on %3 (now %4). %1 met %n %2 marqueur sur %3 (maintenant %4). @@ -2246,7 +2256,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 retire %n %2 marqueur de %3 (maintenant %4). @@ -2254,7 +2264,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + red rouge @@ -2262,7 +2272,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + yellow jaune @@ -2270,7 +2280,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + green vert @@ -2278,169 +2288,169 @@ La version la plus récente est %1, l'ancienne version est %2. - + his permanents ses permanents - + her permanents - + %1 %2 %3. wtf ? %1 %2 %3. - + taps engage - + untaps dégage - + %1 sets counter %2 to %3 (%4%5). need exemple %1 met les marqueurs %2 à %3 (%4%5). - + %1 sets %2 to not untap normally. need exemple %2 de %1 ne se dégagera pas lors de l'étape de dégagement. - + %1 sets %2 to untap normally. %2 de %1 se dégagera lors de l'étape de dégagement. - + %1 sets PT of %2 to %3. exemple plz %1 change la F/E de %2 à %3. - + %1 sets annotation of %2 to %3. %1 met l'annotation %3 à %2. - + %1 is looking at the top %2 cards %3. exemple plz %1 regarde les %2 cartes du dessus %3. - + %1 is looking at %2. exemple plz %1 regarde %2. - + %1 stops looking at %2. need exemple to be sure %1 arrête de regarder %2. - + %1 reveals %2 to %3. %1 révèle %2 à %3. - + %1 reveals %2. %1 révèle %2. - + %1 randomly reveals %2%3 to %4. %1 révèle au hasard %2%3 à %4. - + %1 randomly reveals %2%3. %1 révèle au hasard %2%3. - + %1 reveals %2%3 to %4. %1 révèle %2%3 à %4. - + %1 reveals %2%3. %1 révèle %2%3. - + It is now %1's turn. C'est maintenant le tour de %1. - + untap step étape de dégagement - + upkeep step étape d'entretien - + draw step étape de pioche - + first main phase première phase principale - + beginning of combat step étape de début du combat - + declare attackers step étape de déclaration des attaquants - + declare blockers step étape de déclaration des bloqueurs - + combat damage step étape de répartition et de résolution des blessures - + end of combat step étape de fin de combat - + second main phase seconde phase principale - + ending phase phase de fin de tour - + It is now the %1. need exemple C'est maintenant %1. @@ -2800,7 +2810,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + Number: Nombre: @@ -2825,28 +2835,28 @@ La version la plus récente est %1, l'ancienne version est %2.Nombre de faces: - + Set power/toughness Fixer force/endurance - + Please enter the new PT: maybe better with / Entrer la nouvelle F/E: - + Set annotation Mettre une note - + Please enter the new annotation: Entrez la nouvelle note: - + Set counters Mettre des marqueurs diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index 73682c839..d3bf6ce86 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -1723,225 +1723,235 @@ Local version is %1, remote version is %2. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1958,43 +1968,43 @@ Local version is %1, remote version is %2. - + red - + yellow - + green - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. @@ -2049,188 +2059,188 @@ Local version is %1, remote version is %2. - + %1 takes a mulligan to %n. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). - + %1 removes %n %2 counter(s) from %3 (now %4). - + her permanents - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2589,7 +2599,7 @@ Local version is %1, remote version is %2. - + Number: 枚数 @@ -2614,27 +2624,27 @@ Local version is %1, remote version is %2. 面の数: - + Set power/toughness パワーとタフネスを設定する - + Please enter the new PT: 新しいP/Tを入力してください - + Set annotation 補足を付ける - + Please enter the new annotation: 新しい補足を付けてください - + Set counters カウンターを設定する diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 093c66681..4a1f93071 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -1718,17 +1718,27 @@ Local version is %1, remote version is %2. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1737,188 +1747,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1927,57 +1937,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1986,7 +1996,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -1995,7 +2005,7 @@ Local version is %1, remote version is %2. - + red @@ -2004,7 +2014,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2013,7 +2023,7 @@ Local version is %1, remote version is %2. - + green @@ -2022,162 +2032,162 @@ Local version is %1, remote version is %2. - + his permanents - + her permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2536,7 +2546,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2561,27 +2571,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 8dd17c58f..ea855248f 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -1898,17 +1898,27 @@ A versão local é %1 e a versão remota é %2. %1 não está mais pronto para começar o jogo. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. %1 tirou um %2 com um dado de %3 lados. - + %1 draws %n card(s). %1 compra %n card. @@ -1916,208 +1926,208 @@ A versão local é %1 e a versão remota é %2. - + %1 undoes his last draw. %1 desfaz sua última compra. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 desfaz sua última compra (%2). - + %1 undoes her last draw (%2). - + from table vindo do campo de batalha - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library o card do fundo do seu grimório - + the bottom card of her library - + from the bottom of his library vindo do fundo do seu grimório - + from the bottom of her library - + the top card of his library o card do topo do seu grimório - + the top card of her library - + from the top of his library vindo do topo do seu grimório - + from the top of her library - + from library vindo do grimório - + from sideboard vindo do sideboard - + from the stack vindo da pilha - + %1 gives %2 control over %3. %1 dá controle para %2 sobre %3. - + %1 puts %2 into play tapped%3. %1 põe %2 em jogo virado%3. - + %1 puts %2 into play%3. %1 põe %2 no campo de batalha %3. - + %1 puts %2%3 into graveyard. %1 põe %2 no cemitério%3. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2 para a mão%3. - + %1 puts %2%3 into his library. %1 põe %2 no seu grimório%3. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 põe %2 no fundo do seu grimório%3. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 põe %2 no topo do seu grimório%3. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 põe %2 no seu grimório na posição %4%3. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 move %2 para o sideboard%3. - + %1 plays %2%3. %1 põe %2 na pilha%3. - - + + a card um card - + %1 flips %2 face-down. %1 vira %2 para baixo. - + %1 flips %2 face-up. %1 vira %2 para cima. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 aponta para %5 de %4 com %3 de %2. @@ -2136,7 +2146,7 @@ A versão local é %1 e a versão remota é %2. - + red vermelho @@ -2144,7 +2154,7 @@ A versão local é %1 e a versão remota é %2. - + yellow amarelo @@ -2152,7 +2162,7 @@ A versão local é %1 e a versão remota é %2. - + green verde @@ -2160,22 +2170,22 @@ A versão local é %1 e a versão remota é %2. - + %1 sets counter %2 to %3 (%4%5). %1 altera o marcador %2 para %3 (%4%5). - + %1 sets PT of %2 to %3. %1 altera o P/R de %2 para %3. - + %1 sets annotation of %2 to %3. %1 altera a nota de %2 para%3. - + %1 is looking at the top %2 cards %3. %1 está olhando para os %2 cards do topo %3. @@ -2238,22 +2248,22 @@ A versão local é %1 e a versão remota é %2. %1 compra %2 cards. - + %1 destroys %2. %1 destrói %2. - + %1 creates token: %2%3. %1 cria a ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta para %4 com %3 de %2 . - + %1 places %n %2 counter(s) on %3 (now %4). %1 põe %n marcador %2 em %3 (agora %4). @@ -2261,7 +2271,7 @@ A versão local é %1 e a versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 tira %n marcador %2 em %3 (agora %4). @@ -2269,37 +2279,37 @@ A versão local é %1 e a versão remota é %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está olhando para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 para %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase final - + It is now %1's turn. Agora é o turno de %1. @@ -2308,7 +2318,7 @@ A versão local é %1 e a versão remota é %2. %1 embaralha o seu grimório. - + %1 takes a mulligan to %n. @@ -2316,117 +2326,117 @@ A versão local é %1 e a versão remota é %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + her permanents - + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3. para %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 para %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step etapa de desvirar - + upkeep step etapa de manutenção - + draw step etapa de compra - + first main phase primeira fase principal - + beginning of combat step etapa de início de combate - + declare attackers step etapa de declaracão de atacantes - + declare blockers step etapa de declaração de bloqueadores - + combat damage step etapa de dano de combate - + end of combat step etapa de fim de combate - + second main phase segunda fase principal - + It is now the %1. Agora é a %1. - + taps vira - + untaps desvira - + %1 sets %2 to not untap normally. %1 define que %2 não desvira normalmente. - + %1 sets %2 to untap normally. %1 define que %2 desvira normalmente. - + his permanents as suas permanentes @@ -2785,7 +2795,7 @@ A versão local é %1 e a versão remota é %2. - + Number: Número: @@ -2810,27 +2820,27 @@ A versão local é %1 e a versão remota é %2. Número de lados: - + Set power/toughness Alterar poder/resistência - + Please enter the new PT: Por favor, entre com o novo P/R: - + Set annotation Alterar nota - + Please enter the new annotation: Por favor, entre com a nova nota: - + Set counters Alterar marcadores diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 7ed23d1bc..ed2d3b20f 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -1956,7 +1956,7 @@ Versão local é %1, versão remota é %2. %1 baralha o grimório. - + %1 rolls a %2 with a %3-sided die. %1 obteve %2 com um dado de %3 faces. @@ -1969,157 +1969,157 @@ Versão local é %1, versão remota é %2. %1 compra %2 cartas. - + from table vindo da mesa - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library a carta do fundo do seu grimório - + the bottom card of her library - + from the bottom of his library do fundo do seu grimório - + from the bottom of her library - + the top card of his library a carta do topo do seu grimório - + the top card of her library - + from the top of his library do topo do seu grimório - + from the top of her library - + from library do grimório - + from sideboard do sideboard - + from the stack da pilha - + %1 puts %2 into play tapped%3. %1 coloca %2 em jogo virado(a)%3. - + %1 puts %2 into play%3. %1 coloca %2 em jogo %3. - + %1 puts %2%3 into graveyard. %1 coloca %2%3 no cemitério. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2%3 para a mão. - + %1 puts %2%3 into his library. %1 coloca %2%3 no seu grimório. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 coloca %2%3 no fundo do seu grimório. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 coloca %2%3 no topo do seu grimório. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 coloca %2%3 no seu grimório na posição %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 move %2%3 para o sideboard. - + %1 plays %2%3. %1 joga %2%3. - + %1 takes a mulligan to %n. @@ -2127,17 +2127,17 @@ Versão local é %1, versão remota é %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 places %n %2 counter(s) on %3 (now %4). %1 coloca %n %2 marcador em %3 (agora com %4). @@ -2145,7 +2145,7 @@ Versão local é %1, versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remove %n %2 marcador de %3 (agora com %4). @@ -2153,18 +2153,28 @@ Versão local é %1, versão remota é %2. - - + + a card uma carta - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 draws %n card(s). %1 compra %n carta. @@ -2172,67 +2182,67 @@ Versão local é %1, versão remota é %2. - + %1 undoes his last draw. %1 desfaz a sua última compra. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 desfaz a sua última compra (%2). - + %1 undoes her last draw (%2). - + %1 gives %2 control over %3. %1 dá controlo sobre %3 a %2. - + %1 flips %2 face-down. %1 volta a face de %2 para baixo. - + %1 flips %2 face-up. %1 volta a face de %2 para cima. - + %1 destroys %2. %1 destrói %2. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 creates token: %2%3. %1 cria ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta de %3 de %2 para %4. - + %1 points from %2's %3 to %4's %5. %1 aponta de %3 de %2 para %5 de %4. @@ -2251,7 +2261,7 @@ Versão local é %1, versão remota é %2. - + red vermelho @@ -2259,7 +2269,7 @@ Versão local é %1, versão remota é %2. - + yellow amarelo @@ -2267,7 +2277,7 @@ Versão local é %1, versão remota é %2. - + green verde @@ -2275,162 +2285,162 @@ Versão local é %1, versão remota é %2. - + his permanents as suas permanentes - + her permanents - + %1 %2 %3. %1 %2 %3. - + taps vira - + untaps desvira - + %1 sets counter %2 to %3 (%4%5). %1 altera o número de marcadores %2 para %3(%4%5). - + %1 sets %2 to not untap normally. %1 define %2 para não desvirar normalmente. - + %1 sets %2 to untap normally. %1 define %2 para desvirar normalmente. - + %1 sets PT of %2 to %3. %1 define o P/R de %2 como %3. - + %1 sets annotation of %2 to %3. %1 coloca uma nota de %2 em%3. - + %1 is looking at the top %2 cards %3. %1 está a olhar para as %2 cartas do topo %3. - + %1 is looking at %2. %1 está a olhar para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + %1 randomly reveals %2%3 to %4. %1 revela aleatoreamente %2%3. a %4. - + %1 randomly reveals %2%3. %1 revela aleatoreamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + It is now %1's turn. É agora o turno de %1. - + untap step Etapa de Desvirar - + upkeep step Etapa de Manutenção - + draw step Etapa de Compra - + first main phase 1ª Fase Principal (pré-combate) - + beginning of combat step Etapa de Início de Combate - + declare attackers step Etapa de Declaração de Atacantes - + declare blockers step Etapa de Declaração de Bloqueadores - + combat damage step Etapa de Dano de Combate - + end of combat step Etapa de Fim de Combate - + second main phase 2ª Fase Principal (pós-combate) - + ending phase Fase Final - + It is now the %1. É agora a %1. @@ -2789,7 +2799,7 @@ Versão local é %1, versão remota é %2. - + Number: Número: @@ -2814,27 +2824,27 @@ Versão local é %1, versão remota é %2. Número de faces: - + Set power/toughness Definir poder/resistência - + Please enter the new PT: Por favor introduza o novo P/R: - + Set annotation Colocar nota - + Please enter the new annotation: Por favor introduza a nova nota: - + Set counters Definir marcadores diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 9d7920e1c..43d41057f 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -1880,7 +1880,7 @@ Local version is %1, remote version is %2. %1 размешивает библиотеку. - + %1 rolls a %2 with a %3-sided die. %1 выкинул %2 / %3. @@ -1893,168 +1893,168 @@ Local version is %1, remote version is %2. %1 взял %2 карт. - + %1 undoes his last draw. %1 отменил последнее взятие. - + %1 undoes his last draw (%2). %1 отменил %2 последних взятий. - + from table с поля битвы - + from graveyard из кладбища - + from exile из изгнания - + from hand из руки - + the bottom card of his library нижнюю карту своей библиотеки - + from the bottom of his library со дна своей библиотеки - + the top card of his library верхнюю карту своей библиотеки - + from the top of his library с верха своей библиотеки - + from library из библиотеки - + from sideboard из сайда - + from the stack из стека - - + + a card карту - + %1 gives %2 control over %3. %1 передает %2 контроль над %3. - + %1 puts %2 into play%3. %1 поместил %2 на поле битвы %3. - + %1 puts %2%3 into graveyard. %1 поместил %2%3 на кладбище. - + %1 exiles %2%3. %1 изгоняет %2%3. - + %1 moves %2%3 to hand. %1 поместил %2%3 в руку. - + %1 puts %2%3 into his library. %1 поместил %2%3 в свою библиотеку. - + %1 puts %2%3 on bottom of his library. %1 поместил %2%3 на дно своей библиотеки. - + %1 puts %2%3 on top of his library. %1 поместил %2%3 на верх своей библиотеки. - + %1 puts %2%3 into his library at position %4. %1 поместил %2%3 в свою библиотеку %4 сверху. - + %1 moves %2%3 to sideboard. %1 поместил %2%3 в сайд. - + %1 plays %2%3. %1 разыгрывает %2%3. - + %1 flips %2 face-down. %1 перевернул %2 лицом вниз. - + %1 flips %2 face-up. %1 перевернул %2 лицом вверх. - + %1 destroys %2. %1 уничтожил %2. - + %1 attaches %2 to %3's %4. %1 присоединил %2 к %4 игрока %3. - + %1 unattaches %2. %1 отсоединил %2. - + %1 creates token: %2%3. %1 создал фишку: %2%3. - + %1 points from %2's %3 to %4. %1 указывает с %3 контролируемого %2 на %4. - + %1 points from %2's %3 to %4's %5. %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. @@ -2075,12 +2075,22 @@ Local version is %1, remote version is %2. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 draws %n card(s). %1 взял %n карту. @@ -2089,62 +2099,62 @@ Local version is %1, remote version is %2. - + %1 undoes her last draw. - + %1 undoes her last draw (%2). - + the bottom card of her library - + from the bottom of her library - + the top card of her library - + from the top of her library - + %1 puts %2 into play tapped%3. %1 положил %2 повернутым на поле битвы%3. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into her library at position %4. - + %1 takes a mulligan to %n. @@ -2153,17 +2163,17 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 places %n %2 counter(s) on %3 (now %4). %1 поместил %n %2 жетон на %3 (теперь %4). @@ -2172,7 +2182,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 снял %n %2 жетон с %3 (теперь %4). @@ -2181,7 +2191,7 @@ Local version is %1, remote version is %2. - + red красный @@ -2190,7 +2200,7 @@ Local version is %1, remote version is %2. - + yellow желтый @@ -2199,7 +2209,7 @@ Local version is %1, remote version is %2. - + green зеленый @@ -2208,162 +2218,162 @@ Local version is %1, remote version is %2. - + his permanents свои перманенты - + her permanents - + %1 %2 %3. %1 %2 %3. - + taps повернул - + untaps развернул - + %1 sets counter %2 to %3 (%4%5). %1 установил жетон %2 на %3 (%4%5). - + %1 sets %2 to not untap normally. %2 теперь не разворачивается как обычно (%1). - + %1 sets %2 to untap normally. %2 теперь разворачивается как обычно (%1). - + %1 sets PT of %2 to %3. %1 установил Силу/Защиту %2 %3. - + %1 sets annotation of %2 to %3. %1 сделал пометку на %2 "%3". - + %1 is looking at the top %2 cards %3. %1 смотрит верхние %2 карт библиотеки %3. - + %1 is looking at %2. %1 просматривает %2. - + %1 stops looking at %2. %1 закончил просматривать %2. - + %1 reveals %2 to %3. %1 показывает его %2 %3. - + %1 reveals %2. %1 открыл его %2. - + %1 randomly reveals %2%3 to %4. %1 показывает случайно выбранную%3 карту (%2) %4. - + %1 randomly reveals %2%3. %1 открывает случайно выбранную%3 карту (%2). - + %1 reveals %2%3 to %4. %1 показывает%2%3 %4. - + %1 reveals %2%3. %1 открывает%2%3. - + It is now %1's turn. Ход игрока %1. - + untap step шаг разворота - + upkeep step шаг поддержки - + draw step шаг взятия карты - + first main phase первая главная фаза - + beginning of combat step шаг начала битвы - + declare attackers step шаг назначения атакующих - + declare blockers step шаг назначения блокирующих - + combat damage step шаг нанесения повреждений - + end of combat step шаг завершения битвы - + second main phase вторая главная фаза - + ending phase заключительный шаг - + It is now the %1. Сейчас %1. @@ -2722,7 +2732,7 @@ Local version is %1, remote version is %2. - + Number: Количество: @@ -2747,27 +2757,27 @@ Local version is %1, remote version is %2. Количество граней: - + Set power/toughness Установить Силу/Защиту - + Please enter the new PT: Введите новые Силу/Защиту: - + Set annotation Пометка - + Please enter the new annotation: Введите текст: - + Set counters Установить жетоны diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 835301f8c..aca97b8b3 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -1718,17 +1718,27 @@ Local version is %1, remote version is %2. - + + %1 has restored connection to the game. + + + + + %1 has lost connection to the game. + + + + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1737,188 +1747,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1927,57 +1937,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1986,7 +1996,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -1995,7 +2005,7 @@ Local version is %1, remote version is %2. - + red @@ -2004,7 +2014,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2013,7 +2023,7 @@ Local version is %1, remote version is %2. - + green @@ -2022,162 +2032,162 @@ Local version is %1, remote version is %2. - + his permanents - + her permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2536,7 +2546,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2561,27 +2571,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h index b00687cf0..cbec3eb02 100644 --- a/common/protocol_item_ids.h +++ b/common/protocol_item_ids.h @@ -43,43 +43,44 @@ ItemId_Command_SetActivePhase = 1041, ItemId_Command_DumpZone = 1042, ItemId_Command_StopDumpZone = 1043, ItemId_Command_RevealCards = 1044, -ItemId_Event_Say = 1045, -ItemId_Event_Leave = 1046, -ItemId_Event_GameClosed = 1047, -ItemId_Event_Kicked = 1048, -ItemId_Event_Shuffle = 1049, -ItemId_Event_RollDie = 1050, -ItemId_Event_MoveCard = 1051, -ItemId_Event_FlipCard = 1052, -ItemId_Event_DestroyCard = 1053, -ItemId_Event_AttachCard = 1054, -ItemId_Event_CreateToken = 1055, -ItemId_Event_DeleteArrow = 1056, -ItemId_Event_SetCardAttr = 1057, -ItemId_Event_SetCardCounter = 1058, -ItemId_Event_SetCounter = 1059, -ItemId_Event_DelCounter = 1060, -ItemId_Event_SetActivePlayer = 1061, -ItemId_Event_SetActivePhase = 1062, -ItemId_Event_DumpZone = 1063, -ItemId_Event_StopDumpZone = 1064, -ItemId_Event_RemoveFromList = 1065, -ItemId_Event_ServerMessage = 1066, -ItemId_Event_ServerShutdown = 1067, -ItemId_Event_ConnectionClosed = 1068, -ItemId_Event_Message = 1069, -ItemId_Event_GameJoined = 1070, -ItemId_Event_UserLeft = 1071, -ItemId_Event_LeaveRoom = 1072, -ItemId_Event_RoomSay = 1073, -ItemId_Context_ReadyStart = 1074, -ItemId_Context_Concede = 1075, -ItemId_Context_DeckSelect = 1076, -ItemId_Context_UndoDraw = 1077, -ItemId_Context_MoveCard = 1078, -ItemId_Context_Mulligan = 1079, -ItemId_Command_UpdateServerMessage = 1080, -ItemId_Command_ShutdownServer = 1081, -ItemId_Command_BanFromServer = 1082, -ItemId_Other = 1083 +ItemId_Event_ConnectionStateChanged = 1045, +ItemId_Event_Say = 1046, +ItemId_Event_Leave = 1047, +ItemId_Event_GameClosed = 1048, +ItemId_Event_Kicked = 1049, +ItemId_Event_Shuffle = 1050, +ItemId_Event_RollDie = 1051, +ItemId_Event_MoveCard = 1052, +ItemId_Event_FlipCard = 1053, +ItemId_Event_DestroyCard = 1054, +ItemId_Event_AttachCard = 1055, +ItemId_Event_CreateToken = 1056, +ItemId_Event_DeleteArrow = 1057, +ItemId_Event_SetCardAttr = 1058, +ItemId_Event_SetCardCounter = 1059, +ItemId_Event_SetCounter = 1060, +ItemId_Event_DelCounter = 1061, +ItemId_Event_SetActivePlayer = 1062, +ItemId_Event_SetActivePhase = 1063, +ItemId_Event_DumpZone = 1064, +ItemId_Event_StopDumpZone = 1065, +ItemId_Event_RemoveFromList = 1066, +ItemId_Event_ServerMessage = 1067, +ItemId_Event_ServerShutdown = 1068, +ItemId_Event_ConnectionClosed = 1069, +ItemId_Event_Message = 1070, +ItemId_Event_GameJoined = 1071, +ItemId_Event_UserLeft = 1072, +ItemId_Event_LeaveRoom = 1073, +ItemId_Event_RoomSay = 1074, +ItemId_Context_ReadyStart = 1075, +ItemId_Context_Concede = 1076, +ItemId_Context_DeckSelect = 1077, +ItemId_Context_UndoDraw = 1078, +ItemId_Context_MoveCard = 1079, +ItemId_Context_Mulligan = 1080, +ItemId_Command_UpdateServerMessage = 1081, +ItemId_Command_ShutdownServer = 1082, +ItemId_Command_BanFromServer = 1083, +ItemId_Other = 1084 }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index 69de7319f..b92a182b9 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -255,6 +255,11 @@ Command_RevealCards::Command_RevealCards(int _gameId, const QString &_zoneName, insertItem(new SerializableItem_Int("card_id", _cardId)); insertItem(new SerializableItem_Int("player_id", _playerId)); } +Event_ConnectionStateChanged::Event_ConnectionStateChanged(int _playerId, bool _connected) + : GameEvent("connection_state_changed", _playerId) +{ + insertItem(new SerializableItem_Bool("connected", _connected)); +} Event_Say::Event_Say(int _playerId, const QString &_message) : GameEvent("say", _playerId) { @@ -531,6 +536,7 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("cmddump_zone", Command_DumpZone::newItem); itemNameHash.insert("cmdstop_dump_zone", Command_StopDumpZone::newItem); itemNameHash.insert("cmdreveal_cards", Command_RevealCards::newItem); + itemNameHash.insert("game_eventconnection_state_changed", Event_ConnectionStateChanged::newItem); itemNameHash.insert("game_eventsay", Event_Say::newItem); itemNameHash.insert("game_eventleave", Event_Leave::newItem); itemNameHash.insert("game_eventgame_closed", Event_GameClosed::newItem); diff --git a/common/protocol_items.dat b/common/protocol_items.dat index 14e486c92..ab83e15ab 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -42,6 +42,7 @@ 2:dump_zone:i,player_id:s,zone_name:i,number_cards 2:stop_dump_zone:i,player_id:s,zone_name 2:reveal_cards:s,zone_name:i,card_id:i,player_id +3:connection_state_changed:b,connected 3:say:s,message 3:leave 3:game_closed diff --git a/common/protocol_items.h b/common/protocol_items.h index d03a7825e..810357a88 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -389,6 +389,14 @@ public: static SerializableItem *newItem() { return new Command_RevealCards; } int getItemId() const { return ItemId_Command_RevealCards; } }; +class Event_ConnectionStateChanged : public GameEvent { + Q_OBJECT +public: + Event_ConnectionStateChanged(int _playerId = -1, bool _connected = false); + bool getConnected() const { return static_cast(itemMap.value("connected"))->getData(); }; + static SerializableItem *newItem() { return new Event_ConnectionStateChanged; } + int getItemId() const { return ItemId_Event_ConnectionStateChanged; } +}; class Event_Say : public GameEvent { Q_OBJECT public: diff --git a/common/server_game.cpp b/common/server_game.cpp index 74e65ed92..85b3a1512 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -341,6 +341,13 @@ void Server_Game::nextTurn() setActivePlayer(keys[listPos]); } +void Server_Game::postConnectionStatusUpdate(Server_Player *player, bool connectionStatus) +{ + QMutexLocker locker(&gameMutex); + + sendGameEvent(new Event_ConnectionStateChanged(player->getPlayerId(), connectionStatus)); +} + QList Server_Game::getGameState(Server_Player *playerWhosAsking) const { QMutexLocker locker(&gameMutex); diff --git a/common/server_game.h b/common/server_game.h index 2042a4441..b34301d47 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -88,6 +88,7 @@ public: void setActivePlayer(int _activePlayer); void setActivePhase(int _activePhase); void nextTurn(); + void postConnectionStatusUpdate(Server_Player *player, bool connectionStatus); QList getGameState(Server_Player *playerWhosAsking) const; void sendGameEvent(GameEvent *event, GameEventContext *context = 0, Server_Player *exclude = 0); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index b461f833e..b929edb60 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -46,8 +46,10 @@ void Server_ProtocolHandler::prepareDestroy() if ((authState == UnknownUser) || p->getSpectator()) g->removePlayer(p); - else + else { p->setProtocolHandler(0); + g->postConnectionStatusUpdate(p, false); + } } gameListMutex.unlock(); @@ -392,6 +394,7 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC for (int j = 0; j < gamePlayers.size(); ++j) if (gamePlayers[j]->getUserInfo()->getName() == userInfo->getName()) { gamePlayers[j]->setProtocolHandler(this); + game->postConnectionStatusUpdate(gamePlayers[j], true); games.insert(game->getGameId(), QPair(game, gamePlayers[j])); enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), true)); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 0cc2dd96d..fffc1cec3 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -423,4 +423,4 @@ void Servatrice::shutdownTimeout() deleteLater(); } -const QString Servatrice::versionString = "Servatrice 0.20110527"; +const QString Servatrice::versionString = "Servatrice 0.20110625"; From 05ebb83ba4276aba863b59db32a2a2f1a6ac759a Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 25 Jun 2011 21:21:19 +0200 Subject: [PATCH 62/87] improved banning; added [url] and [card] tags for chat --- cockatrice/cockatrice.pro | 1 + cockatrice/src/chatview.cpp | 144 +++++++- cockatrice/src/chatview.h | 26 +- cockatrice/src/localserver.h | 2 +- cockatrice/src/messagelogwidget.cpp | 200 ++++------- cockatrice/src/messagelogwidget.h | 21 +- cockatrice/src/tab.cpp | 30 ++ cockatrice/src/tab.h | 8 +- cockatrice/src/tab_game.cpp | 29 +- cockatrice/src/tab_game.h | 5 +- cockatrice/src/tab_message.cpp | 4 +- cockatrice/src/tab_room.cpp | 4 +- cockatrice/src/tab_supervisor.cpp | 4 +- cockatrice/src/userlist.cpp | 54 ++- cockatrice/src/userlist.h | 14 + cockatrice/translations/cockatrice_cs.ts | 361 ++++++++++--------- cockatrice/translations/cockatrice_de.ts | 362 +++++++++++--------- cockatrice/translations/cockatrice_en.ts | 361 ++++++++++--------- cockatrice/translations/cockatrice_es.ts | 357 ++++++++++--------- cockatrice/translations/cockatrice_fr.ts | 357 ++++++++++--------- cockatrice/translations/cockatrice_ja.ts | 356 ++++++++++--------- cockatrice/translations/cockatrice_pl.ts | 361 ++++++++++--------- cockatrice/translations/cockatrice_pt-br.ts | 357 ++++++++++--------- cockatrice/translations/cockatrice_pt.ts | 357 ++++++++++--------- cockatrice/translations/cockatrice_ru.ts | 357 ++++++++++--------- cockatrice/translations/cockatrice_sk.ts | 361 ++++++++++--------- common/protocol_items.cpp | 3 +- common/protocol_items.dat | 2 +- common/protocol_items.h | 3 +- common/server.cpp | 2 +- common/server.h | 3 +- common/server_protocolhandler.cpp | 2 - servatrice/servatrice.sql | 10 +- servatrice/src/servatrice.cpp | 35 +- servatrice/src/servatrice.h | 5 +- servatrice/src/serversocketinterface.cpp | 16 +- 36 files changed, 2501 insertions(+), 2073 deletions(-) create mode 100644 cockatrice/src/tab.cpp diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index 045994096..b126f14a0 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -136,6 +136,7 @@ SOURCES += src/abstractcounter.cpp \ src/gamescene.cpp \ src/arrowitem.cpp \ src/arrowtarget.cpp \ + src/tab.cpp \ src/tab_server.cpp \ src/tab_room.cpp \ src/tab_message.cpp \ diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index 625301e39..700313ee9 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -2,34 +2,41 @@ #include #include #include +#include +#include #include "chatview.h" -ChatView::ChatView(const QString &_ownName, QWidget *parent) - : QTextEdit(parent), ownName(_ownName) +ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent) + : QTextBrowser(parent), ownName(_ownName), showTimestamps(_showTimestamps) { - setTextInteractionFlags(Qt::TextSelectableByMouse); + setReadOnly(true); + setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); + setOpenLinks(false); + connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &))); } -void ChatView::appendMessage(QString sender, const QString &message) +void ChatView::appendMessage(QString sender, QString message) { QTextCursor cursor(document()->lastBlock()); cursor.movePosition(QTextCursor::End); QTextBlockFormat blockFormat; - blockFormat.setBottomMargin(3); + blockFormat.setBottomMargin(2); cursor.insertBlock(blockFormat); - QTextCharFormat timeFormat; - timeFormat.setForeground(Qt::black); - cursor.setCharFormat(timeFormat); - cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] ")); + if (showTimestamps) { + QTextCharFormat timeFormat; + timeFormat.setForeground(Qt::black); + cursor.setCharFormat(timeFormat); + cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] ")); + } QTextCharFormat senderFormat; if (sender == ownName) { senderFormat.setFontWeight(QFont::Bold); senderFormat.setForeground(Qt::red); } else - senderFormat.setForeground(Qt::blue); + senderFormat.setForeground(QColor(0, 0, 254)); cursor.setCharFormat(senderFormat); if (!sender.isEmpty()) sender.append(": "); @@ -39,7 +46,122 @@ void ChatView::appendMessage(QString sender, const QString &message) if (sender.isEmpty()) messageFormat.setForeground(Qt::darkGreen); cursor.setCharFormat(messageFormat); - cursor.insertText(message); + + int from = 0, index = 0; + while ((index = message.indexOf('[', from)) != -1) { + cursor.insertText(message.left(index)); + message = message.mid(index); + if (message.isEmpty()) + break; + + if (message.startsWith("[card]")) { + message = message.mid(6); + QTextCharFormat tempFormat = messageFormat; + tempFormat.setForeground(Qt::blue); + cursor.setCharFormat(tempFormat); + int closeTagIndex = message.indexOf("[/card]"); + cursor.insertText(message.left(closeTagIndex)); + cursor.setCharFormat(messageFormat); + if (closeTagIndex == -1) + message.clear(); + else + message = message.mid(closeTagIndex + 7); + } else if (message.startsWith("[url]")) { + message = message.mid(5); + int closeTagIndex = message.indexOf("[/url]"); + QString url = message.left(closeTagIndex); + if (!url.startsWith("http://")) + url.prepend("http://"); + QTextCharFormat tempFormat = messageFormat; + tempFormat.setForeground(QColor(0, 0, 254)); + tempFormat.setAnchor(true); + tempFormat.setAnchorHref(url); + cursor.setCharFormat(tempFormat); + cursor.insertText(url); + cursor.setCharFormat(messageFormat); + if (closeTagIndex == -1) + message.clear(); + else + message = message.mid(closeTagIndex + 6); + } else + from = 1; + } + if (!message.isEmpty()) + cursor.insertText(message); verticalScrollBar()->setValue(verticalScrollBar()->maximum()); } + +void ChatView::enterEvent(QEvent * /*event*/) +{ + setMouseTracking(true); +} + +void ChatView::leaveEvent(QEvent * /*event*/) +{ + setMouseTracking(false); +} + +QTextFragment ChatView::getFragmentUnderMouse(const QPoint &pos) const +{ + QTextCursor cursor(cursorForPosition(pos)); + QTextBlock block(cursor.block()); + QTextBlock::iterator it; + for (it = block.begin(); !(it.atEnd()); ++it) { + QTextFragment frag = it.fragment(); + if (frag.contains(cursor.position())) + return frag; + } + return QTextFragment(); +} + +QString ChatView::getCardNameUnderMouse(QTextFragment frag) const +{ + if (frag.charFormat().foreground().color() == Qt::blue) + return frag.text(); + return QString(); +} + +QString ChatView::getCardNameUnderMouse(const QPoint &pos) const +{ + return getCardNameUnderMouse(getFragmentUnderMouse(pos)); +} + +void ChatView::mouseMoveEvent(QMouseEvent *event) +{ + QTextFragment frag = getFragmentUnderMouse(event->pos()); + QString cardName = getCardNameUnderMouse(frag); + if (!cardName.isEmpty()) { + viewport()->setCursor(Qt::PointingHandCursor); + emit cardNameHovered(cardName); + } else if (frag.charFormat().isAnchor()) + viewport()->setCursor(Qt::PointingHandCursor); + else + viewport()->setCursor(Qt::IBeamCursor); + + QTextBrowser::mouseMoveEvent(event); +} + +void ChatView::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::MidButton) { + QString cardName = getCardNameUnderMouse(event->pos()); + if (!cardName.isEmpty()) + emit showCardInfoPopup(event->globalPos(), cardName); + } + + QTextBrowser::mousePressEvent(event); +} + +void ChatView::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::MidButton) + emit deleteCardInfoPopup(); + + QTextBrowser::mouseReleaseEvent(event); +} + +void ChatView::openLink(const QUrl &link) +{ + QDesktopServices::openUrl(link); +} diff --git a/cockatrice/src/chatview.h b/cockatrice/src/chatview.h index bd7e763aa..c17f2375f 100644 --- a/cockatrice/src/chatview.h +++ b/cockatrice/src/chatview.h @@ -1,18 +1,36 @@ #ifndef CHATVIEW_H #define CHATVIEW_H -#include +#include +#include class QTextTable; +class QMouseEvent; -class ChatView : public QTextEdit { +class ChatView : public QTextBrowser { Q_OBJECT; private: QTextTable *table; QString ownName; + bool showTimestamps; + QTextFragment getFragmentUnderMouse(const QPoint &pos) const; + QString getCardNameUnderMouse(QTextFragment frag) const; + QString getCardNameUnderMouse(const QPoint &pos) const; +private slots: + void openLink(const QUrl &link); public: - ChatView(const QString &_ownName, QWidget *parent = 0); - void appendMessage(QString sender, const QString &message); + ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent = 0); + void appendMessage(QString sender, QString message); +protected: + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); +signals: + void cardNameHovered(QString cardName); + void showCardInfoPopup(QPoint pos, QString cardName); + void deleteCardInfoPopup(); }; #endif \ No newline at end of file diff --git a/cockatrice/src/localserver.h b/cockatrice/src/localserver.h index b68e4f25a..406b3bff8 100644 --- a/cockatrice/src/localserver.h +++ b/cockatrice/src/localserver.h @@ -11,7 +11,7 @@ class LocalServer : public Server public: LocalServer(QObject *parent = 0); ~LocalServer(); - AuthenticationResult checkUserPassword(const QString & /*user*/, const QString & /*password*/) { return UnknownUser; } + AuthenticationResult checkUserPassword(Server_ProtocolHandler * /*handler*/, const QString & /*user*/, const QString & /*password*/) { return UnknownUser; } QString getLoginMessage() const { return QString(); } bool getGameShouldPing() const { return false; } int getMaxGameInactivityTime() const { return 9999999; } diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 9bb867067..216fe138e 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -1,11 +1,9 @@ #include "messagelogwidget.h" #include "player.h" #include "cardzone.h" -#include "cardinfowidget.h" #include "protocol_items.h" #include "soundengine.h" -#include -#include +#include QString MessageLogWidget::sanitizeHtml(QString dirty) const { @@ -15,6 +13,20 @@ QString MessageLogWidget::sanitizeHtml(QString dirty) const .replace(">", ">"); } +void MessageLogWidget::myAppend(const QString &message) +{ + QTextCursor cursor(document()->lastBlock()); + cursor.movePosition(QTextCursor::End); + + QTextBlockFormat blockFormat; + blockFormat.setBottomMargin(2); + cursor.insertBlock(blockFormat); + + cursor.insertHtml(message); + + verticalScrollBar()->setValue(verticalScrollBar()->maximum()); +} + bool MessageLogWidget::isFemale(Player *player) const { return player->getUserInfo()->getGender() == ServerInfo_User::Female; @@ -22,129 +34,129 @@ bool MessageLogWidget::isFemale(Player *player) const void MessageLogWidget::logConnecting(QString hostname) { - append(tr("Connecting to %1...").arg(sanitizeHtml(hostname))); + myAppend(tr("Connecting to %1...").arg(sanitizeHtml(hostname))); } void MessageLogWidget::logConnected() { - append(tr("Connected.")); + myAppend(tr("Connected.")); } void MessageLogWidget::logDisconnected() { - append(tr("Disconnected from server.")); + myAppend(tr("Disconnected from server.")); } void MessageLogWidget::logSocketError(const QString &errorString) { - append(sanitizeHtml(errorString)); + myAppend(sanitizeHtml(errorString)); } void MessageLogWidget::logServerError(ResponseCode response) { switch (response) { - case RespWrongPassword: append(tr("Invalid password.")); break; + case RespWrongPassword: myAppend(tr("Invalid password.")); break; default: ; } } void MessageLogWidget::logProtocolVersionMismatch(int clientVersion, int serverVersion) { - append(tr("Protocol version mismatch. Client: %1, Server: %2").arg(clientVersion).arg(serverVersion)); + myAppend(tr("Protocol version mismatch. Client: %1, Server: %2").arg(clientVersion).arg(serverVersion)); } void MessageLogWidget::logProtocolError() { - append(tr("Protocol error.")); + myAppend(tr("Protocol error.")); } void MessageLogWidget::logGameJoined(int gameId) { - append(tr("You have joined game #%1.").arg(gameId)); + myAppend(tr("You have joined game #%1.").arg(gameId)); } void MessageLogWidget::logJoin(Player *player) { soundEngine->notification(); - append(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logLeave(Player *player) { - append(tr("%1 has left the game.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 has left the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logGameClosed() { - append(tr("The game has been closed.")); + myAppend(tr("The game has been closed.")); } void MessageLogWidget::logJoinSpectator(QString name) { - append(tr("%1 is now watching the game.").arg(sanitizeHtml(name))); + myAppend(tr("%1 is now watching the game.").arg(sanitizeHtml(name))); } void MessageLogWidget::logLeaveSpectator(QString name) { - append(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name))); + myAppend(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name))); } void MessageLogWidget::logDeckSelect(Player *player, int deckId) { if (deckId == -1) - append(tr("%1 has loaded a local deck.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 has loaded a local deck.").arg(sanitizeHtml(player->getName()))); else - append(tr("%1 has loaded deck #%2.").arg(sanitizeHtml(player->getName())).arg(deckId)); + myAppend(tr("%1 has loaded deck #%2.").arg(sanitizeHtml(player->getName())).arg(deckId)); } void MessageLogWidget::logReadyStart(Player *player) { - append(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logNotReadyStart(Player *player) { - append(tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logConcede(Player *player) { - append(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logGameStart() { - append(tr("The game has started.")); + myAppend(tr("The game has started.")); } void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState) { if (connectionState) - append(tr("%1 has restored connection to the game.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 has restored connection to the game.").arg(sanitizeHtml(player->getName()))); else - append(tr("%1 has lost connection to the game.").arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 has lost connection to the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logSay(Player *player, QString message) { - append(QString("getLocal() ? "red" : "#0000fe") + QString("\">%1: %2").arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(message))); + appendMessage(player->getName(), message); } void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) { - append(QString("%1: %2").arg(sanitizeHtml(spectatorName)).arg(sanitizeHtml(message))); + myAppend(QString("%1: %2").arg(sanitizeHtml(spectatorName)).arg(sanitizeHtml(message))); } void MessageLogWidget::logShuffle(Player *player, CardZone *zone) { soundEngine->shuffle(); if (currentContext != MessageContext_Mulligan) - append(tr("%1 shuffles %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + myAppend(tr("%1 shuffles %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); } void MessageLogWidget::logRollDie(Player *player, int sides, int roll) { - append(tr("%1 rolls a %2 with a %3-sided die.").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides)); + myAppend(tr("%1 rolls a %2 with a %3-sided die.").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides)); } void MessageLogWidget::logDrawCards(Player *player, int number) @@ -153,16 +165,16 @@ void MessageLogWidget::logDrawCards(Player *player, int number) mulliganPlayer = player; else { soundEngine->draw(); - append(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); } } void MessageLogWidget::logUndoDraw(Player *player, QString cardName) { if (cardName.isEmpty()) - append((isFemale(player) ? tr("%1 undoes her last draw.") : tr("%1 undoes his last draw.")).arg(sanitizeHtml(player->getName()))); + myAppend((isFemale(player) ? tr("%1 undoes her last draw.") : tr("%1 undoes his last draw.")).arg(sanitizeHtml(player->getName()))); else - append((isFemale(player) ? tr("%1 undoes her last draw (%2).") : tr("%1 undoes his last draw (%2).")).arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + myAppend((isFemale(player) ? tr("%1 undoes her last draw (%2).") : tr("%1 undoes his last draw (%2).")).arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } QPair MessageLogWidget::getFromStr(CardZone *zone, QString cardName, int position) const @@ -227,7 +239,7 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes) cardStr = QString("%1").arg(sanitizeHtml(cardName)); if (attributes.startZone->getPlayer() != attributes.targetZone->getPlayer()) { - append(tr("%1 gives %2 control over %3.").arg(sanitizeHtml(attributes.player->getName())).arg(sanitizeHtml(attributes.targetZone->getPlayer()->getName())).arg(cardStr)); + myAppend(tr("%1 gives %2 control over %3.").arg(sanitizeHtml(attributes.player->getName())).arg(sanitizeHtml(attributes.targetZone->getPlayer()->getName())).arg(cardStr)); return; } @@ -260,7 +272,7 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes) finalStr = tr("%1 plays %2%3."); } - append(finalStr.arg(sanitizeHtml(attributes.player->getName())).arg(cardStr).arg(fromStr).arg(attributes.newX)); + myAppend(finalStr.arg(sanitizeHtml(attributes.player->getName())).arg(cardStr).arg(fromStr).arg(attributes.newX)); } void MessageLogWidget::logMoveCard(Player *player, CardItem *card, CardZone *startZone, int oldX, CardZone *targetZone, int newX) @@ -280,50 +292,50 @@ void MessageLogWidget::logMulligan(Player *player, int number) return; if (number > -1) - append(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); + myAppend(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); else - append((isFemale(player) ? tr("%1 draws her initial hand.") : tr("%1 draws his initial hand.")).arg(sanitizeHtml(player->getName()))); + myAppend((isFemale(player) ? tr("%1 draws her initial hand.") : tr("%1 draws his initial hand.")).arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown) { if (faceDown) - append(tr("%1 flips %2 face-down.").arg(sanitizeHtml(player->getName())).arg(cardName)); + myAppend(tr("%1 flips %2 face-down.").arg(sanitizeHtml(player->getName())).arg(cardName)); else - append(tr("%1 flips %2 face-up.").arg(sanitizeHtml(player->getName())).arg(cardName)); + myAppend(tr("%1 flips %2 face-up.").arg(sanitizeHtml(player->getName())).arg(cardName)); } void MessageLogWidget::logDestroyCard(Player *player, QString cardName) { - append(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + myAppend(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName) { - append(tr("%1 attaches %2 to %3's %4.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("%1").arg(sanitizeHtml(targetCardName)))); + myAppend(tr("%1 attaches %2 to %3's %4.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("%1").arg(sanitizeHtml(targetCardName)))); } void MessageLogWidget::logUnattachCard(Player *player, QString cardName) { - append(tr("%1 unattaches %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + myAppend(tr("%1 unattaches %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt) { - append(tr("%1 creates token: %2%3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); + myAppend(tr("%1 creates token: %2%3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); } void MessageLogWidget::logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard, bool playerTarget) { if (playerTarget) - append(tr("%1 points from %2's %3 to %4.") + myAppend(tr("%1 points from %2's %3 to %4.") .arg(sanitizeHtml(player->getName())) .arg(sanitizeHtml(startPlayer->getName())) .arg(sanitizeHtml(startCard)) .arg(sanitizeHtml(targetPlayer->getName())) ); else - append(tr("%1 points from %2's %3 to %4's %5.") + myAppend(tr("%1 points from %2's %3 to %4's %5.") .arg(sanitizeHtml(player->getName())) .arg(sanitizeHtml(startPlayer->getName())) .arg(sanitizeHtml(startCard)) @@ -349,7 +361,7 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c default: ; } - append(finalStr.arg(sanitizeHtml(player->getName())).arg(colorStr).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(value)); + myAppend(finalStr.arg(sanitizeHtml(player->getName())).arg(colorStr).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(value)); } void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) @@ -367,13 +379,13 @@ void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) cardStr = isFemale(player) ? tr("her permanents") : tr("his permanents"); else cardStr = QString("%1").arg(sanitizeHtml(card->getName())); - append(tr("%1 %2 %3.").arg(sanitizeHtml(player->getName())).arg(tapped ? tr("taps") : tr("untaps")).arg(cardStr)); + myAppend(tr("%1 %2 %3.").arg(sanitizeHtml(player->getName())).arg(tapped ? tr("taps") : tr("untaps")).arg(cardStr)); } } void MessageLogWidget::logSetCounter(Player *player, QString counterName, int value, int oldValue) { - append(tr("%1 sets counter %2 to %3 (%4%5).").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(counterName))).arg(QString("%1").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue)); + myAppend(tr("%1 sets counter %2 to %3 (%4%5).").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(counterName))).arg(QString("%1").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue)); } void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap) @@ -383,7 +395,7 @@ void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool do finalStr = tr("%1 sets %2 to not untap normally."); else finalStr = tr("%1 sets %2 to untap normally."); - append(finalStr.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName())))); + myAppend(finalStr.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName())))); } void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT) @@ -391,26 +403,26 @@ void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT) if (currentContext == MessageContext_MoveCard) moveCardPT.insert(card, newPT); else - append(tr("%1 sets PT of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newPT)))); + myAppend(tr("%1 sets PT of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newPT)))); } void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString newAnnotation) { - append(tr("%1 sets annotation of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newAnnotation)))); + myAppend(tr("%1 sets annotation of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newAnnotation)))); } void MessageLogWidget::logDumpZone(Player *player, CardZone *zone, int numberCards) { if (numberCards != -1) - append(tr("%1 is looking at the top %2 cards %3.").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive))); + myAppend(tr("%1 is looking at the top %2 cards %3.").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive))); else - append(tr("%1 is looking at %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative))); + myAppend(tr("%1 is looking at %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative))); } void MessageLogWidget::logStopDumpZone(Player *player, CardZone *zone) { QString zoneName = zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative); - append(tr("%1 stops looking at %2.").arg(sanitizeHtml(player->getName())).arg(zoneName)); + myAppend(tr("%1 stops looking at %2.").arg(sanitizeHtml(player->getName())).arg(zoneName)); } void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer) @@ -433,28 +445,28 @@ void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId if (cardId == -1) { if (otherPlayer) - append(tr("%1 reveals %2 to %3.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName()))); + myAppend(tr("%1 reveals %2 to %3.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName()))); else - append(tr("%1 reveals %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + myAppend(tr("%1 reveals %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); } else if (cardId == -2) { if (otherPlayer) - append(tr("%1 randomly reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); + myAppend(tr("%1 randomly reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); else - append(tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + myAppend(tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); } else { if (otherPlayer) - append(tr("%1 reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); + myAppend(tr("%1 reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); else - append(tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + myAppend(tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); } } void MessageLogWidget::logSetActivePlayer(Player *player) { soundEngine->notification(); - append(QString()); - append("" + tr("It is now %1's turn.").arg(player->getName()) + ""); - append(QString()); + myAppend(QString()); + myAppend("" + tr("It is now %1's turn.").arg(player->getName()) + ""); + myAppend(QString()); } void MessageLogWidget::logSetActivePhase(int phase) @@ -474,7 +486,7 @@ void MessageLogWidget::logSetActivePhase(int phase) case 9: phaseName = tr("second main phase"); break; case 10: phaseName = tr("ending phase"); break; } - append("" + tr("It is now the %1.").arg(phaseName) + ""); + myAppend("" + tr("It is now the %1.").arg(phaseName) + ""); } void MessageLogWidget::containerProcessingStarted(GameEventContext *_context) @@ -531,67 +543,7 @@ void MessageLogWidget::connectToPlayer(Player *player) connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *)), this, SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *))); } -MessageLogWidget::MessageLogWidget(QWidget *parent) - : QTextEdit(parent) +MessageLogWidget::MessageLogWidget(const QString &_ownName, QWidget *parent) + : ChatView(_ownName, false, parent) { - setReadOnly(true); -} - -void MessageLogWidget::enterEvent(QEvent * /*event*/) -{ - setMouseTracking(true); -} - -void MessageLogWidget::leaveEvent(QEvent * /*event*/) -{ - setMouseTracking(false); -} - -QString MessageLogWidget::getCardNameUnderMouse(const QPoint &pos) const -{ - QTextCursor cursor(cursorForPosition(pos)); - QTextBlock block(cursor.block()); - QTextBlock::iterator it; - for (it = block.begin(); !(it.atEnd()); ++it) { - QTextFragment frag = it.fragment(); - if (!frag.contains(cursor.position())) - continue; - - if (frag.charFormat().foreground().color() == Qt::blue) - return frag.text(); - - break; - } - return QString(); -} - -void MessageLogWidget::mouseMoveEvent(QMouseEvent *event) -{ - QString cardName = getCardNameUnderMouse(event->pos()); - if (!cardName.isEmpty()) { - viewport()->setCursor(Qt::PointingHandCursor); - emit cardNameHovered(cardName); - } else - viewport()->setCursor(Qt::IBeamCursor); - - QTextEdit::mouseMoveEvent(event); -} - -void MessageLogWidget::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::MidButton) { - QString cardName = getCardNameUnderMouse(event->pos()); - if (!cardName.isEmpty()) - emit showCardInfoPopup(event->globalPos(), cardName); - } - - QTextEdit::mousePressEvent(event); -} - -void MessageLogWidget::mouseReleaseEvent(QMouseEvent *event) -{ - if (event->button() == Qt::MidButton) - emit deleteCardInfoPopup(); - - QTextEdit::mouseReleaseEvent(event); } diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index efc8f6b5b..c99851af0 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -1,15 +1,13 @@ #ifndef MESSAGELOGWIDGET_H #define MESSAGELOGWIDGET_H -#include +#include "chatview.h" #include #include "translation.h" #include "protocol_datastructures.h" class Player; class CardZone; -class QMouseEvent; -class QEvent; class CardInfoWidget; class GameEventContext; class CardItem; @@ -24,16 +22,15 @@ struct LogMoveCard { int newX; }; -class MessageLogWidget : public QTextEdit { +class MessageLogWidget : public ChatView { Q_OBJECT private: enum MessageContext { MessageContext_None, MessageContext_MoveCard, MessageContext_Mulligan }; - CardInfoWidget *infoWidget; QString sanitizeHtml(QString dirty) const; + void myAppend(const QString &message); bool isFemale(Player *player) const; QPair getFromStr(CardZone *zone, QString cardName, int position) const; - QString getCardNameUnderMouse(const QPoint &pos) const; MessageContext currentContext; QList moveCardQueue; @@ -42,10 +39,6 @@ private: Player *mulliganPlayer; int mulliganNumber; -signals: - void cardNameHovered(QString cardName); - void showCardInfoPopup(QPoint pos, QString cardName); - void deleteCardInfoPopup(); public slots: void logConnecting(QString hostname); void logConnected(); @@ -96,13 +89,7 @@ public slots: void containerProcessingDone(); public: void connectToPlayer(Player *player); - MessageLogWidget(QWidget *parent = 0); -protected: - void enterEvent(QEvent *event); - void leaveEvent(QEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); + MessageLogWidget(const QString &_ownName, QWidget *parent = 0); }; #endif diff --git a/cockatrice/src/tab.cpp b/cockatrice/src/tab.cpp new file mode 100644 index 000000000..e85d4091c --- /dev/null +++ b/cockatrice/src/tab.cpp @@ -0,0 +1,30 @@ +#include "tab.h" +#include "cardinfowidget.h" +#include +#include + +Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent) + : QWidget(parent), tabMenu(0), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0) +{ +} + +void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName) +{ + infoPopup = new CardInfoWidget(CardInfoWidget::ModePopUp, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint); + infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents); + infoPopup->setCard(cardName); + QRect screenRect = qApp->desktop()->screenGeometry(this); + infoPopup->move( + qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())), + qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height())) + ); + infoPopup->show(); +} + +void Tab::deleteCardInfoPopup() +{ + if (infoPopup) { + infoPopup->deleteLater(); + infoPopup = 0; + } +} diff --git a/cockatrice/src/tab.h b/cockatrice/src/tab.h index 5f50813cc..ac4b0ea5a 100644 --- a/cockatrice/src/tab.h +++ b/cockatrice/src/tab.h @@ -5,6 +5,7 @@ class QMenu; class TabSupervisor; +class CardInfoWidget; class Tab : public QWidget { Q_OBJECT @@ -13,11 +14,14 @@ signals: protected: QMenu *tabMenu; TabSupervisor *tabSupervisor; +protected slots: + void showCardInfoPopup(const QPoint &pos, const QString &cardName); + void deleteCardInfoPopup(); private: bool contentsChanged; + CardInfoWidget *infoPopup; public: - Tab(TabSupervisor *_tabSupervisor, QWidget *parent = 0) - : QWidget(parent), tabMenu(0), tabSupervisor(_tabSupervisor), contentsChanged(false) { } + Tab(TabSupervisor *_tabSupervisor, QWidget *parent = 0); QMenu *getTabMenu() const { return tabMenu; } bool getContentsChanged() const { return contentsChanged; } void setContentsChanged(bool _contentsChanged) { contentsChanged = _contentsChanged; } diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index e8018c984..04c15c50b 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include "tab_game.h" #include "cardinfowidget.h" #include "playerlistwidget.h" @@ -160,8 +158,8 @@ void DeckViewContainer::setDeck(DeckList *deck) readyStartButton->setEnabled(true); } -TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) - : Tab(_tabSupervisor), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1), infoPopup(0) +TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, const QString &_userName, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) + : Tab(_tabSupervisor), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1) { phasesToolbar = new PhasesToolbar; phasesToolbar->hide(); @@ -178,7 +176,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client timeElapsedLabel = new QLabel; timeElapsedLabel->setAlignment(Qt::AlignCenter); - messageLog = new MessageLogWidget; + messageLog = new MessageLogWidget(_userName); connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString))); connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(messageLog, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup())); @@ -779,24 +777,3 @@ Player *TabGame::getActiveLocalPlayer() const return 0; } - -void TabGame::showCardInfoPopup(const QPoint &pos, const QString &cardName) -{ - infoPopup = new CardInfoWidget(CardInfoWidget::ModePopUp, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint); - infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents); - infoPopup->setCard(cardName); - QRect screenRect = qApp->desktop()->screenGeometry(this); - infoPopup->move( - qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2, screenRect.left() + screenRect.width() - infoPopup->width())), - qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2, screenRect.top() + screenRect.height() - infoPopup->height())) - ); - infoPopup->show(); -} - -void TabGame::deleteCardInfoPopup() -{ - if (infoPopup) { - infoPopup->deleteLater(); - infoPopup = 0; - } -} diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 5982b42b3..289451f14 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -100,7 +100,6 @@ private: int activePlayer; QSplitter *splitter; - CardInfoWidget *infoPopup; CardInfoWidget *cardInfo; PlayerListWidget *playerListWidget; QLabel *timeElapsedLabel; @@ -147,8 +146,6 @@ signals: void openMessageDialog(const QString &userName, bool focus); private slots: void newCardAdded(AbstractCardItem *card); - void showCardInfoPopup(const QPoint &pos, const QString &cardName); - void deleteCardInfoPopup(); void actConcede(); void actLeaveGame(); @@ -158,7 +155,7 @@ private slots: void actNextPhase(); void actNextTurn(); public: - TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); + TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, const QString &_userName, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); ~TabGame(); void retranslateUi(); void closeRequest(); diff --git a/cockatrice/src/tab_message.cpp b/cockatrice/src/tab_message.cpp index 03fb401f0..c79fbfee8 100644 --- a/cockatrice/src/tab_message.cpp +++ b/cockatrice/src/tab_message.cpp @@ -11,7 +11,9 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, const QString &_userName) : Tab(_tabSupervisor), client(_client), userName(_userName), userOnline(true) { - chatView = new ChatView(_ownName); + chatView = new ChatView(_ownName, true); + connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); + connect(chatView, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup())); sayEdit = new QLineEdit; connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage())); diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index d72e13ef5..621b4b085 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -137,7 +137,9 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q userList = new UserList(tabSupervisor, client, UserList::RoomList); connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); - chatView = new ChatView(ownName); + chatView = new ChatView(ownName, true); + connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); + connect(chatView, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup())); sayLabel = new QLabel; sayEdit = new QLineEdit; sayLabel->setBuddy(sayEdit); diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index c9cdc5d57..10e33afff 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -221,7 +221,7 @@ void TabSupervisor::addCloseButtonToTab(Tab *tab, int tabIndex) void TabSupervisor::gameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(this, QList() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + TabGame *tab = new TabGame(this, QList() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userName, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); int tabIndex = myAddTab(tab); @@ -232,7 +232,7 @@ void TabSupervisor::gameJoined(Event_GameJoined *event) void TabSupervisor::localGameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), QString(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); int tabIndex = myAddTab(tab); addCloseButtonToTab(tab, tabIndex); diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index c904513cb..02a04a6e3 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -10,6 +10,53 @@ #include #include #include +#include +#include +#include +#include +#include + +BanDialog::BanDialog(QWidget *parent) + : QDialog(parent) +{ + QLabel *durationLabel = new QLabel(tr("Please enter the duration of the ban (in minutes).\nEnter 0 for an indefinite ban.")); + durationEdit = new QSpinBox; + durationEdit->setMinimum(0); + durationEdit->setValue(5); + QLabel *reasonLabel = new QLabel(tr("Please enter the reason for the ban.\nThis is only saved for moderators and cannot be seen by the banned person.")); + reasonEdit = new QPlainTextEdit; + + QPushButton *okButton = new QPushButton(tr("&OK")); + okButton->setAutoDefault(true); + connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); + QPushButton *cancelButton = new QPushButton(tr("&Cancel")); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(); + buttonLayout->addWidget(okButton); + buttonLayout->addWidget(cancelButton); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(durationLabel); + vbox->addWidget(durationEdit); + vbox->addWidget(reasonLabel); + vbox->addWidget(reasonEdit); + vbox->addLayout(buttonLayout); + + setLayout(vbox); + setWindowTitle(tr("Ban user from server")); +} + +int BanDialog::getMinutes() const +{ + return durationEdit->value(); +} + +QString BanDialog::getReason() const +{ + return reasonEdit->toPlainText(); +} UserListItemDelegate::UserListItemDelegate(QObject *const parent) : QStyledItemDelegate(parent) @@ -215,10 +262,9 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) else if (actionClicked == aRemoveFromIgnoreList) client->sendCommand(new Command_RemoveFromList("ignore", userName)); else if (actionClicked == aBan) { - bool ok; - int minutes = QInputDialog::getInt(this, tr("Duration"), tr("Please enter the duration of the ban (in minutes).\nEnter 0 for an indefinite ban."), 0, 0, 2147483647, 10, &ok); - if (ok) - client->sendCommand(new Command_BanFromServer(userName, minutes)); + BanDialog dlg(this); + if (dlg.exec()) + client->sendCommand(new Command_BanFromServer(userName, dlg.getMinutes(), dlg.getReason())); } delete menu; diff --git a/cockatrice/src/userlist.h b/cockatrice/src/userlist.h index a611bf5de..a40fca0f9 100644 --- a/cockatrice/src/userlist.h +++ b/cockatrice/src/userlist.h @@ -1,6 +1,7 @@ #ifndef USERLIST_H #define USERLIST_H +#include #include #include #include @@ -9,6 +10,19 @@ class QTreeWidget; class ServerInfo_User; class AbstractClient; class TabSupervisor; +class QSpinBox; +class QPlainTextEdit; + +class BanDialog : public QDialog { + Q_OBJECT +private: + QSpinBox *durationEdit; + QPlainTextEdit *reasonEdit; +public: + BanDialog(QWidget *parent = 0); + int getMinutes() const; + QString getReason() const; +}; class UserListItemDelegate : public QStyledItemDelegate { public: diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index 43f214c84..db45c0b21 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -121,6 +121,36 @@ + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + + + + + &Cancel + + + + + Ban user from server + + + CardDatabaseModel @@ -787,22 +817,22 @@ DeckViewContainer - + Load &local deck - + Load d&eck from server - + Ready to s&tart - + Load deck @@ -1628,117 +1658,117 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Connected. - + Disconnected from server. - + Invalid password. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1747,188 +1777,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1937,57 +1967,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1996,7 +2026,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -2005,7 +2035,7 @@ Local version is %1, remote version is %2. - + red @@ -2014,7 +2044,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2023,7 +2053,7 @@ Local version is %1, remote version is %2. - + green @@ -2032,162 +2062,162 @@ Local version is %1, remote version is %2. - + his permanents - + her permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2877,137 +2907,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases - + &Game - + Next &phase - + Ctrl+Space - + Next &turn - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows - + Ctrl+R - + &Concede - + F2 - + &Leave game - + Ctrl+Q - + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + Kicked - + You have been kicked out of the game. - + Game %1: %2 @@ -3015,27 +3045,27 @@ Please enter a name: TabMessage - + Personal &talk - + &Leave - + This user is ignoring you. - + %1 has left the server. - + %1 has joined the server. @@ -3048,27 +3078,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3178,71 +3208,60 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + User &details - + Direct &chat - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server - - - Duration - - - - - Please enter the duration of the ban (in minutes). -Enter 0 for an indefinite ban. - - WndDeckEditor diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 38e343481..ce769bacb 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -156,6 +156,42 @@ Pfad auswählen + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + Bitte geben Sie die Dauer des Banns ein (in Minuten). +Geben Sie 0 ein für einen unbefristeten Bann. + + + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. + Bitte geben Sie den Grund für den Bann ein. Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nicht gesehen werden. + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + Bitte geben Sie den Grund für den Bann ein. +Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nicht gesehen werden. + + + + &OK + &OK + + + + &Cancel + &Abbrechen + + + + Ban user from server + Benutzer vom Server bannen + + CardDatabaseModel @@ -1209,22 +1245,22 @@ DeckViewContainer - + Load &local deck &Lokales Deck laden - + Load d&eck from server Deck vom Server l&aden - + Ready to s&tart Bereit zum S&tarten - + Load deck Deck laden @@ -2429,22 +2465,22 @@ Lokale Version ist %1, Serverversion ist %2. MessageLogWidget - + Connecting to %1... Verbinde zu %1... - + Connected. Verbunden. - + Disconnected from server. Verbindung zum Server getrennt. - + Invalid password. Ungültiges Passwort. @@ -2485,8 +2521,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten - - + + a card eine Karte @@ -2543,7 +2579,7 @@ Lokale Version ist %1, Serverversion ist %2. %1s Sideboard - + The game has started. Das Spiel hat begonnen. @@ -2564,87 +2600,87 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversion stimmt nicht überein. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. Protokollfehler. - + You have joined game #%1. Sie sind dem Spiel %1 beigetreten. - + %1 has joined the game. %1 ist dem Spiel beigetreten. - + %1 has left the game. %1 hat das Spiel verlassen. - + The game has been closed. Das Spiel wurde geschlossen. - + %1 is now watching the game. %1 schaut nun dem Spiel zu. - + %1 is not watching the game any more. %1 schaut dem Spiel nicht mehr zu. - + %1 has loaded a local deck. %1 hat ein lokales Deck geladen. - + %1 has loaded deck #%2. %1 hat das Deck Nr. %2 geladen. - + %1 is ready to start the game. %1 ist bereit, das Spiel zu starten. - + %1 is not ready to start the game any more. %1 ist nicht mehr bereit, das Spiel zu starten. - + %1 has conceded the game. %1 hat das Spiel aufgegeben. - + %1 has restored connection to the game. %1 ist wieder mit dem Spiel verbunden. - + %1 has lost connection to the game. %1 hat die Verbindung zum Spiel verloren. - + %1 shuffles %2. %1 mischt %2. - + %1 rolls a %2 with a %3-sided die. %1 würfelt eine %2 mit einem %3-seitigen Würfel. @@ -2657,7 +2693,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten. - + %1 draws %n card(s). %1 zieht eine Karte. @@ -2665,182 +2701,182 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 undoes his last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes her last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes his last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + %1 undoes her last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + the bottom card of her library die unterste Karte ihrer Bibliothek - + from the bottom of his library , die unterste Karte seiner Bibliothek, - + from the bottom of her library , die unterste Karte ihrer Bibliothek, - + the top card of his library die oberste Karte seiner Bibliothek - + the top card of her library die oberste Karte ihrer Bibliothek - + from the top of his library , die oberste Karte seiner Bibliothek, - + from the top of her library , die oberste Karte ihrer Bibliothek, - + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + from the stack vom Stapel - + %1 gives %2 control over %3. %1 überlässt %2 die Kontrolle über %3. - + %1 puts %2 into play tapped%3. %1 bringt %2 getappt%3 ins Spiel. - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + %1 puts %2%3 into her library. %1 legt %2%3 in ihre Bibliothek. - + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + %1 puts %2%3 on bottom of her library. %1 legt %2%3 unter ihre Bibliothek. - + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 on top of her library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + %1 puts %2%3 into her library at position %4. %1 legt %2%3 in ihre Bibliothek an %4. Stelle. - + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 plays %2%3. %1 spielt %2%3 aus. - + %1 takes a mulligan to %n. %1 nimmt einen Mulligan auf %n. @@ -2848,52 +2884,52 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 draws his initial hand. %1 zieht seine Starthand. - + %1 draws her initial hand. %1 zieht ihre Starthand. - + %1 flips %2 face-down. %1 wendet %2 auf die Rückseite. - + %1 flips %2 face-up. %1 wendet %2 auf die Vorderseite. - + %1 destroys %2. %1 zerstört %2. - + %1 attaches %2 to %3's %4. %1 legt %2 an %3s %4 an. - + %1 unattaches %2. %1 löst %2 ab. - + %1 creates token: %2%3. %1 erstellt Token: %2%3. - + %1 points from %2's %3 to %4. %1 zeigt von %2s %3 auf %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 legt eine %2 Marke auf %3 (jetzt %4). @@ -2901,7 +2937,7 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 entfernt eine %2 Marke von %3 (jetzt %4). @@ -2909,27 +2945,27 @@ Lokale Version ist %1, Serverversion ist %2. - + her permanents ihre bleibenden Karten - + %1 randomly reveals %2%3 to %4. %1 zeigt %4 zufällig %2%3 vor. - + %1 randomly reveals %2%3. %1 zeigt zufällig %2%3 offen vor. - + %1 reveals %2%3 to %4. %1 zeigt %4 %2%3 vor. - + %1 reveals %2%3. %1 zeigt %2%3 offen vor. @@ -2938,7 +2974,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 erstellt einen Spielstein: %2 (%3). - + %1 points from %2's %3 to %4's %5. %1 zeigt von %2s %3 auf %4s %5. @@ -2957,7 +2993,7 @@ Lokale Version ist %1, Serverversion ist %2. - + red rote @@ -2965,7 +3001,7 @@ Lokale Version ist %1, Serverversion ist %2. - + yellow gelbe @@ -2973,7 +3009,7 @@ Lokale Version ist %1, Serverversion ist %2. - + green grüne @@ -2981,22 +3017,22 @@ Lokale Version ist %1, Serverversion ist %2. - + %1 sets counter %2 to %3 (%4%5). %1 setzt Zähler %2 auf %3 (%4%5). - + %1 sets PT of %2 to %3. %1 setzt Kampfwerte von %2 auf %3. - + %1 sets annotation of %2 to %3. %1 versieht %2 mit dem Hinweis %3. - + %1 is looking at the top %2 cards %3. %1 sieht sich die obersten %2 Karten %3 an. @@ -3093,7 +3129,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4). - + %1 %2 %3. %1 %2 %3. @@ -3106,22 +3142,22 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich die obersten %2 Karten %3 an. - + %1 is looking at %2. %1 sieht sich %2 an. - + %1 stops looking at %2. %1 sieht sich %2 nicht mehr an. - + %1 reveals %2 to %3. %1 zeigt %3 %2. - + %1 reveals %2. %1 zeigt %2 offen vor. @@ -3142,7 +3178,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zeigt %2 aus %3 offen vor. - + ending phase die Zugendphase @@ -3171,57 +3207,57 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich %2s %3 nicht mehr an - + It is now %1's turn. %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -3230,7 +3266,7 @@ Lokale Version ist %1, Serverversion ist %2. das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -3239,12 +3275,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 bewegt %2 %3 nach %4 - + taps tappt - + untaps enttappt @@ -3269,7 +3305,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4) - + his permanents seine bleibenden Karten @@ -3282,12 +3318,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 setzt Zähler "%2" auf %3 (%4%5) - + %1 sets %2 to not untap normally. %1 setzt %2 auf explizites Enttappen. - + %1 sets %2 to untap normally. %1 setzt %2 auf normales Enttappen. @@ -4220,107 +4256,107 @@ Bitte geben Sie einen Namen ein: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases &Phasen - + &Game Spi&el - + Next &phase Nächste &Phase - + Ctrl+Space Ctrl+Space - + Next &turn Nächster &Zug - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Lokale Pfeile entfernen - + Ctrl+R Ctrl+R - + &Concede - + F2 F2 - + &Leave game Spiel ver&lassen - + Ctrl+Q Ctrl+Q - + Kicked Herausgeworfen - + You have been kicked out of the game. Sie wurden aus dem Spiel geworfen. @@ -4341,7 +4377,7 @@ Bitte geben Sie einen Namen ein: Spiel s&tarten - + &Say: &Sagen: @@ -4354,22 +4390,22 @@ Bitte geben Sie einen Namen ein: Esc - + Concede Aufgeben - + Are you sure you want to concede this game? Sind Sie sicher, dass Sie das Spiel aufgeben möchten? - + Leave game Spiel verlassen - + Are you sure you want to leave this game? Sind Sie sicher, dass Sie das Spiel verlassen möchten? @@ -4378,7 +4414,7 @@ Bitte geben Sie einen Namen ein: Deck laden - + Game %1: %2 Spiel %1: %2 @@ -4386,27 +4422,27 @@ Bitte geben Sie einen Namen ein: TabMessage - + Personal &talk Persönliches &Gespräch - + &Leave Ver&lassen - + This user is ignoring you. Dieser Benutzer ignoriert Sie. - + %1 has left the server. %1 hat den Server verlassen. - + %1 has joined the server. %1 hat den Server betreten. @@ -4419,27 +4455,27 @@ Bitte geben Sie einen Namen ein: TabRoom - + &Say: &Sagen: - + Chat Unterhaltung - + &Room &Raum - + &Leave room Raum ver&lassen - + You are flooding the chat. Please wait a couple of seconds. Sie überfluten den Chatraum. Bitte warten Sie ein paar Sekunden. @@ -4576,70 +4612,68 @@ Bitte geben Sie einen Namen ein: UserList - + Users online: %1 Benutzer online: %1 - + Users in this room: %1 Benutzer in diesem Raum: %1 - + Buddies online: %1 / %2 Freunde online: %1 / %2 - + Ignored users online: %1 / %2 Ignorierte Benutzer online: %1 / %2 - + User &details Benutzer&details - + Direct &chat &Persönliches Gespräch - + Add to &buddy list Zur &Freundesliste hinzufügen - + Remove from &buddy list Von &Freundesliste entfernen - + Add to &ignore list &Ignorieren - + Remove from &ignore list Nicht mehr &ignorieren - + Ban from &server Vom &Server bannen - Duration - Dauer + Dauer - Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - Bitte geben Sie die Dauer des Banns ein (in Minuten). + Bitte geben Sie die Dauer des Banns ein (in Minuten). Geben Sie 0 ein für einen unbefristeten Bann. diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 02e8057db..c0d65f991 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -121,6 +121,36 @@ + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + + + + + &Cancel + + + + + Ban user from server + + + CardDatabaseModel @@ -787,22 +817,22 @@ DeckViewContainer - + Load &local deck - + Load d&eck from server - + Ready to s&tart - + Load deck @@ -1627,67 +1657,67 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). %1 draws a card. @@ -1695,208 +1725,208 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1915,7 +1945,7 @@ Local version is %1, remote version is %2. - + red @@ -1923,7 +1953,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1931,7 +1961,7 @@ Local version is %1, remote version is %2. - + green @@ -1939,77 +1969,77 @@ Local version is %1, remote version is %2. - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. - + %1 takes a mulligan to %n. @@ -2017,32 +2047,32 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 places a %2 counter on %3 (now %4). @@ -2050,7 +2080,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 removes a %2 counter from %3 (now %4). @@ -2058,142 +2088,142 @@ Local version is %1, remote version is %2. - + her permanents - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2883,137 +2913,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases - + &Game - + Next &phase - + Ctrl+Space - + Next &turn - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows - + Ctrl+R - + &Concede - + F2 - + &Leave game - + Ctrl+Q - + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + Kicked - + You have been kicked out of the game. - + Game %1: %2 @@ -3021,27 +3051,27 @@ Please enter a name: TabMessage - + Personal &talk - + &Leave - + This user is ignoring you. - + %1 has left the server. - + %1 has joined the server. @@ -3054,27 +3084,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3184,71 +3214,60 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + User &details - + Direct &chat - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server - - - Duration - - - - - Please enter the duration of the ban (in minutes). -Enter 0 for an indefinite ban. - - WndDeckEditor diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index adb9e23a7..d39522e99 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -129,6 +129,37 @@ Elija ruta + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + Por favor, introduce la duración del ban (en minutos) +Indica 0 para un ban indefinido. + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + &Aceptar + + + + &Cancel + &Cancelar + + + + Ban user from server + + + CardDatabaseModel @@ -1129,22 +1160,22 @@ DeckViewContainer - + Load &local deck Cargar mazo &local - + Load d&eck from server Cargar mazo del &servidor - + Ready to s&tart Listo para &empezar - + Load deck Cargar mazo @@ -2000,67 +2031,67 @@ La versión local es %1, la versión remota es %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado del servidor. - + Invalid password. Contraseña incorrecta. - + Protocol error. Error del protocolo. - + The game has been closed. La partida ha sido cerrada. - + %1 is now watching the game. %1 está ahora observando la partida. - + %1 is not watching the game any more. %1 ya no está observado más la partida. - + %1 is not ready to start the game any more. %1 ya no está listo para empezar el juego. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. %1 sacó un %2 con un dado de %3 caras. - + %1 draws %n card(s). %1 roba %n carta. @@ -2068,208 +2099,208 @@ La versión local es %1, la versión remota es %2. - + %1 undoes his last draw. %1 deshace su último robo. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 deshace su último robo (%2). - + %1 undoes her last draw (%2). - + from table de la mesa - + from graveyard del cementerio - + from exile del exilio - + from hand de la mano - + the bottom card of his library el fondo de la biblioteca - + the bottom card of her library - + from the bottom of his library del fondo de la biblioteca - + from the bottom of her library - + the top card of his library la parte superior de la biblioteca - + the top card of her library - + from the top of his library de la parte superior de la biblioteca - + from the top of her library - + from library de la biblioteca - + from sideboard de la reserva - + from the stack de la pila - + %1 gives %2 control over %3. %1 entrega a %2 el control sobre %3. - + %1 puts %2 into play tapped%3. %1 pone %2 en juego%3 girado. - + %1 puts %2 into play%3. %1 pone %2 en juego%3. - + %1 puts %2%3 into graveyard. %1 pone %2%3 en el cementerio. - + %1 exiles %2%3. %1 exilia %2%3. - + %1 moves %2%3 to hand. %1 mueve %2%3 a la mano. - + %1 puts %2%3 into his library. %1 pone %2%3 en la biblioteca. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 pone %2%3 en la parte inferior de su biblioteca. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 pone %2%3 en la parte superior de su biblioteca. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 pone %2%3 en su biblioteca en la posición %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 mueve %2%3 a la reserva. - + %1 plays %2%3. %1 juega %2%3. - - + + a card una carta - + %1 flips %2 face-down. %1 voltea %2 boca abajo. - + %1 flips %2 face-up. %1 voltea %2 boca arriba. - + %1 attaches %2 to %3's %4. %1 anexa %2 a el %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 apunta desde el %3 de %2 al %5 de %4. @@ -2288,7 +2319,7 @@ La versión local es %1, la versión remota es %2. - + red rojo @@ -2296,7 +2327,7 @@ La versión local es %1, la versión remota es %2. - + yellow amarillo @@ -2304,7 +2335,7 @@ La versión local es %1, la versión remota es %2. - + green verde @@ -2312,72 +2343,72 @@ La versión local es %1, la versión remota es %2. - + %1 sets counter %2 to %3 (%4%5). %1 establece los contadores de %2 a %3 (%4%5). - + %1 sets PT of %2 to %3. %1 establece F/R de %2 a %3. - + %1 sets annotation of %2 to %3. %1 establece la anotación de %2 a %3. - + %1 is looking at the top %2 cards %3. %1 esta mirando las primeras %2 cartas de %3. - + The game has started. La partida ha comenzado. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 La versión del protocolo es diferente. Cliente: %1, Servidor: %2 - + You have joined game #%1. Te has unido a la partida #%1. - + %1 has joined the game. %1 se ha unido a la partida. - + %1 has left the game. %1 ha dejado la partida. - + %1 has loaded a local deck. %1 ha cargado un mazo local. - + %1 has loaded deck #%2. %1 ha cargado el mazo #%2. - + %1 is ready to start the game. %1 está preparado para empezar la partida. - + %1 has conceded the game. %1 ha concedido la partida. @@ -2390,22 +2421,22 @@ La versión local es %1, la versión remota es %2. %1 roba %2 cartas. - + %1 destroys %2. %1 destruye %2. - + %1 creates token: %2%3. %1 crea una ficha: %2%3. - + %1 points from %2's %3 to %4. %1 apunta desde el %3 de %2 a %4. - + %1 places %n %2 counter(s) on %3 (now %4). %1 pone %n %2 contador en %3 (ahora %4). @@ -2413,7 +2444,7 @@ La versión local es %1, la versión remota es %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remueve %n %2 contador en %3 (ahora %4). @@ -2421,37 +2452,37 @@ La versión local es %1, la versión remota es %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está mirando: %2. - + %1 stops looking at %2. %1 termina de mirar: %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase de fin de turno - + It is now %1's turn. Es el turno de %1. @@ -2460,7 +2491,7 @@ La versión local es %1, la versión remota es %2. %1 baraja su biblioteca. - + %1 takes a mulligan to %n. @@ -2468,117 +2499,117 @@ La versión local es %1, la versión remota es %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + her permanents - + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3 a %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step paso de enderezar - + upkeep step paso de mantenimiento - + draw step paso de robar - + first main phase primera fase principal - + beginning of combat step paso de inicio de combate - + declare attackers step paso de declarar atacantes - + declare blockers step paso de declarar bloqueadores - + combat damage step paso de daño de combate - + end of combat step paso de fin de combate - + second main phase segunda fase principal - + It is now the %1. Ahora es el %1. - + taps gira - + untaps endereza - + %1 sets %2 to not untap normally. %1 establece que %2 no se endereze normalmente. - + %1 sets %2 to untap normally. %1 establece que %2 se endereze normalmente. - + his permanents sus permanentes @@ -3331,137 +3362,137 @@ Por favor, introduzca un nombre: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases &Fases - + &Game &Partida - + Next &phase Próxima &fase - + Ctrl+Space Ctrl+Space - + Next &turn Próximo &turno - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Retirar todas las flechas locales - + Ctrl+R Ctrl+R - + &Concede &Conceder - + F2 F2 - + &Leave game &Abandonar la partida - + Ctrl+Q Ctrl+Q - + &Say: &Decir: - + Concede Conceder - + Are you sure you want to concede this game? ¿Estás seguro de que quieres conceder esta partida? - + Leave game Abandonar la partida - + Are you sure you want to leave this game? ¿Estás seguro de que quieres abandonar la partida? - + Kicked Expulsado - + You have been kicked out of the game. Has sido expulsado de la partida. - + Game %1: %2 Partida %1: %2 @@ -3469,27 +3500,27 @@ Por favor, introduzca un nombre: TabMessage - + Personal &talk &Conversación personal - + &Leave &Cerrar - + This user is ignoring you. Este usuario está ignorandote. - + %1 has left the server. %1 ha abandonado el servidor. - + %1 has joined the server. %1 se ha unido al servidor. @@ -3502,27 +3533,27 @@ Por favor, introduzca un nombre: TabRoom - + &Say: &Decir: - + Chat Chat - + &Room &Sala - + &Leave room &Dejar sala - + You are flooding the chat. Please wait a couple of seconds. Estás floodeando el chat. Por favor, espera unos segundos. @@ -3644,70 +3675,68 @@ Por favor, introduzca un nombre: UserList - + Users online: %1 Usuarios online: %1 - + Users in this room: %1 Usuarios en esta sala: %1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Usuarios ignorados online: %1 / %2 - + User &details &Detalles del usuario - + Direct &chat &Chat privado - + Add to &buddy list Añadir a la lista de &amigos - + Remove from &buddy list Quitar de la lista de &amigos - + Add to &ignore list Añadir a la lista de &ignorados - + Remove from &ignore list Quitar de la lista de &ignorados - + Ban from &server Banear del &servidor - Duration - Duración + Duración - Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - Por favor, introduce la duración del ban (en minutos) + Por favor, introduce la duración del ban (en minutos) Indica 0 para un ban indefinido. diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index c89507574..ecdd4519b 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -121,6 +121,37 @@ Choisir le chemin + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + Entrez la durée de temps du ban (en minutes). +Entrez 0 pour une durée illimitée du ban. + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + &OK + + + + &Cancel + &Annuler + + + + Ban user from server + + + CardDatabaseModel @@ -991,22 +1022,22 @@ DeckViewContainer - + Load &local deck Charger un deck &local - + Load d&eck from server Charger un d&eck depuis le serveur - + Ready to s&tart P&rêt à démarrer - + Load deck Charger deck @@ -1857,93 +1888,93 @@ La version la plus récente est %1, l'ancienne version est %2. MessageLogWidget - + Connecting to %1... Connexion à %1... - + Connected. Connecté. - + Disconnected from server. Déconnecté du serveur. - + Invalid password. Mot de passe invalide. - + Protocol version mismatch. Client: %1, Server: %2 Version de protocole différente. Version locale: %1 ,version distante: %2 - + Protocol error. Erreur de protocole. - + You have joined game #%1. Vous avez rejoint la partie #%1. - + %1 has joined the game. %1 a rejoint la partie. - + %1 has left the game. %1 a quitté la partie. - + The game has been closed. La partie a été fermée. - + %1 is now watching the game. %1 est maintenant spectateur. - + %1 is not watching the game any more. %1 n'est plus spectateur. - + %1 has loaded a local deck. %1 a chargé un deck local. - + %1 has loaded deck #%2. %1 a chargé le deck #%2. - + %1 is ready to start the game. %1 est prêt à démarrer la partie. - + %1 is not ready to start the game any more. %1 n'est plus prêt à démarrer la partie. - + %1 has conceded the game. partie ou jeu %1 a concédé la partie. - + The game has started. La partie commence. @@ -1952,7 +1983,7 @@ La version la plus récente est %1, l'ancienne version est %2.%1 mélange sa bibliothèque. - + %1 rolls a %2 with a %3-sided die. is it always a dice? %1 lance un %2 à %3 faces. @@ -1966,179 +1997,179 @@ La version la plus récente est %1, l'ancienne version est %2.%1 pioche %2 cartes. - + from table depuis le champ de bataille - + from graveyard depuis son cimetière - + from exile depuis la zone exil - + from hand depuis sa main - + the bottom card of his library la carte du dessous de sa bibliothèque - + the bottom card of her library - + from the bottom of his library du dessous de sa bibliothèque - + from the bottom of her library - + the top card of his library le carte du dessus de sa bibliothèque - + the top card of her library - + from the top of his library du dessus de sa bibliothèque - + from the top of her library - + from library depuis sa bibliothèque - + from sideboard depuis sa réserve - + from the stack depuis la pile - + %1 puts %2 into play tapped%3. %1 met %2 en jeu engagé%3. - + %1 puts %2 into play%3. what is %3? plz exemple (resp. by Ranma : XX met island en jeu -depuis sa main-.) %1 met %2 en jeu %3. - + %1 puts %2%3 into graveyard. %1 met %2%3 dans son cimetière. - + %1 exiles %2%3. %1 exile %2%3. - + %1 moves %2%3 to hand. %1 met %2%3 dans sa main. - + %1 puts %2%3 into his library. %1 met %2%3 dans sa bibliothèque. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 met %2%3 en-dessous de sa bibliothèque. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 met %2%3 au-dessus de sa bibliothèque. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 met %2%3 dans sa bibliothèque à la position n°%4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 met %2%3 à sa réserve. - + %1 plays %2%3. %1 joue %2%3. - - + + a card une carte - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 draws %n card(s). %1 pioche %n carte. @@ -2146,32 +2177,32 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 undoes his last draw. %1 annule sa dernière pioche. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 annule sa dernière pioche (%2). - + %1 undoes her last draw (%2). - + %1 gives %2 control over %3. %1 donne le contrôle de %2 à %3. - + %1 takes a mulligan to %n. @@ -2179,54 +2210,54 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. %1 retourne %2 face cachée. - + %1 flips %2 face-up. %1 retourne %2 face visible. - + %1 destroys %2. %1 détruit %2. - + %1 attaches %2 to %3's %4. need exemple (Resp'.by Ranma: JoueurA attache Adventuring Gear sur -Plated Geopede- de -JoueurB-.) %1 attache %2 sur %4 de %3. - + %1 unattaches %2. %1 détache %2. - + %1 creates token: %2%3. %1 crée un jeton %2%3. - + %1 points from %2's %3 to %4. need exemple %1 désigne le %3 de %2 à %4. - + %1 points from %2's %3 to %4's %5. need exemple %1 désigne le %3 de %2 à %5 de %4. @@ -2248,7 +2279,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 places %n %2 counter(s) on %3 (now %4). %1 met %n %2 marqueur sur %3 (maintenant %4). @@ -2256,7 +2287,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 retire %n %2 marqueur de %3 (maintenant %4). @@ -2264,7 +2295,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + red rouge @@ -2272,7 +2303,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + yellow jaune @@ -2280,7 +2311,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + green vert @@ -2288,169 +2319,169 @@ La version la plus récente est %1, l'ancienne version est %2. - + his permanents ses permanents - + her permanents - + %1 %2 %3. wtf ? %1 %2 %3. - + taps engage - + untaps dégage - + %1 sets counter %2 to %3 (%4%5). need exemple %1 met les marqueurs %2 à %3 (%4%5). - + %1 sets %2 to not untap normally. need exemple %2 de %1 ne se dégagera pas lors de l'étape de dégagement. - + %1 sets %2 to untap normally. %2 de %1 se dégagera lors de l'étape de dégagement. - + %1 sets PT of %2 to %3. exemple plz %1 change la F/E de %2 à %3. - + %1 sets annotation of %2 to %3. %1 met l'annotation %3 à %2. - + %1 is looking at the top %2 cards %3. exemple plz %1 regarde les %2 cartes du dessus %3. - + %1 is looking at %2. exemple plz %1 regarde %2. - + %1 stops looking at %2. need exemple to be sure %1 arrête de regarder %2. - + %1 reveals %2 to %3. %1 révèle %2 à %3. - + %1 reveals %2. %1 révèle %2. - + %1 randomly reveals %2%3 to %4. %1 révèle au hasard %2%3 à %4. - + %1 randomly reveals %2%3. %1 révèle au hasard %2%3. - + %1 reveals %2%3 to %4. %1 révèle %2%3 à %4. - + %1 reveals %2%3. %1 révèle %2%3. - + It is now %1's turn. C'est maintenant le tour de %1. - + untap step étape de dégagement - + upkeep step étape d'entretien - + draw step étape de pioche - + first main phase première phase principale - + beginning of combat step étape de début du combat - + declare attackers step étape de déclaration des attaquants - + declare blockers step étape de déclaration des bloqueurs - + combat damage step étape de répartition et de résolution des blessures - + end of combat step étape de fin de combat - + second main phase seconde phase principale - + ending phase phase de fin de tour - + It is now the %1. need exemple C'est maintenant %1. @@ -3190,137 +3221,137 @@ Entrez un nom s'il vous plaît: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases - + &Game &Partie - + Next &phase &Prochaine phase - + Ctrl+Space Ctrl+Space - + Next &turn Prochain &Tour - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Retirer toutes les flèches locales - + Ctrl+R Ctrl+R - + &Concede &Concéder - + F2 F2 - + &Leave game &Quitter la partie - + Ctrl+Q Ctrl+Q - + &Say: &Dire: - + Concede Concéder - + Are you sure you want to concede this game? Êtes-vous sûr de vouloir concéder la partie? - + Leave game Quitter la partie - + Are you sure you want to leave this game? Êtes-vous sûr de vouloir quitter la partie? - + Kicked Exclu - + You have been kicked out of the game. Vous avez été exclu de la partie. - + Game %1: %2 Partie %1:%2 @@ -3328,28 +3359,28 @@ Entrez un nom s'il vous plaît: TabMessage - + Personal &talk need exemple &Discussion privée - + &Leave &Quitter - + This user is ignoring you. Cet utilisateur vous a ignoré. - + %1 has left the server. %1 a quitté le serveur. - + %1 has joined the server. %1 a rejoint le serveur. @@ -3362,27 +3393,27 @@ Entrez un nom s'il vous plaît: TabRoom - + &Say: &Dire: - + Chat Chat - + &Room &Salon - + &Leave room &Quitter le salon - + You are flooding the chat. Please wait a couple of seconds. Vous floodez le chat. Veuillez patienter quelques secondes. @@ -3505,70 +3536,68 @@ Entrez un nom s'il vous plaît: UserList - + Users online: %1 Utilisateurs en ligne:%1 - + Users in this room: %1 Utilisateurs dans ce salon: %1 - + Buddies online: %1 / %2 Amis connectés; %1 / %2 - + Ignored users online: %1 / %2 Personnes sur liste noire connectés: %1 / %2 - + User &details &Détails utilisateur - + Direct &chat &Chat direct - + Add to &buddy list Ajouter à la liste d'&amis - + Remove from &buddy list Retirer de la liste d'&amis - + Add to &ignore list Ajouter à la liste &noire - + Remove from &ignore list Retirer de la liste &noire - + Ban from &server Bannir du &serveur - Duration - Durée + Durée - Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - Entrez la durée de temps du ban (en minutes). + Entrez la durée de temps du ban (en minutes). Entrez 0 pour une durée illimitée du ban. diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index d3bf6ce86..5f63f5619 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -126,6 +126,36 @@ 画像の指定 + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + バンする期間を入力してください(分単位).0でバンを解除します. + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + + + + + &Cancel + + + + + Ban user from server + + + CardDatabaseModel @@ -835,22 +865,22 @@ DeckViewContainer - + Load &local deck ローカルからデッキをロード - + Load d&eck from server サーバーからデッキをロード - + Ready to s&tart 開始準備完了 - + Load deck デッキをロード @@ -1683,275 +1713,275 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Disconnected from server. - + Invalid password. - + Protocol error. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 is not ready to start the game any more. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - + + a card - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 points from %2's %3 to %4's %5. @@ -1968,279 +1998,279 @@ Local version is %1, remote version is %2. - + red - + yellow - + green - + %1 sets counter %2 to %3 (%4%5). - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + The game has started. - + Connected. - + Protocol version mismatch. Client: %1, Server: %2 - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 has conceded the game. - + %1 takes a mulligan to %n. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 destroys %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 places %n %2 counter(s) on %3 (now %4). - + %1 removes %n %2 counter(s) from %3 (now %4). - + her permanents - + %1 %2 %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + ending phase - + It is now %1's turn. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - + taps - + untaps - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + his permanents @@ -2968,137 +2998,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases フェイズ - + &Game ゲーム - + Next &phase 次のフェイズ - + Ctrl+Space - + Next &turn 次のターン - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows 全ての矢印を消す - + Ctrl+R - + &Concede 投了する - + F2 - + &Leave game ゲームを退出する - + Ctrl+Q - + &Say: 発言する - + Concede 投了する - + Are you sure you want to concede this game? 本当にこのゲームに投了しますか? - + Leave game ゲームから退出する - + Are you sure you want to leave this game? 本当にこのゲームから退出しますか? - + Kicked キック - + You have been kicked out of the game. あなたはこのゲームからキックされました. - + Game %1: %2 ゲーム %1: %2 @@ -3106,27 +3136,27 @@ Please enter a name: TabMessage - + Personal &talk 個人会話 - + &Leave 退出する - + This user is ignoring you. このユーザーはあなたを無視しています. - + %1 has left the server. %1はサーバーから退出しました. - + %1 has joined the server. %1がサーバーに参加しました. @@ -3139,27 +3169,27 @@ Please enter a name: TabRoom - + &Say: 発言する - + Chat チャット - + &Room 部屋 - + &Leave room 部屋から出る - + You are flooding the chat. Please wait a couple of seconds. あなたはチャットルームから弾かれました.少々お待ちください. @@ -3281,70 +3311,68 @@ Please enter a name: UserList - + Users online: %1 ユーザー オンライン: %1 - + Users in this room: %1 部屋のユーザー数: %1 - + Buddies online: %1 / %2 フレンドオンライン: %1 / %2 - + Ignored users online: %1 / %2 無視ユーザーオンライン: %1 / %2 - + User &details ユーザー補足 - + Direct &chat 個人チャット - + Add to &buddy list フレンドリストに追加 - + Remove from &buddy list フレンドリストから削除 - + Add to &ignore list 無視リストに追加 - + Remove from &ignore list 無視リストから削除 - + Ban from &server サーバーからバンする - Duration - 期間 + 期間 - Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - バンする期間を入力してください(分単位).0でバンを解除します. + バンする期間を入力してください(分単位).0でバンを解除します. diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 4a1f93071..564e6ac25 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -121,6 +121,36 @@ + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + + + + + &Cancel + + + + + Ban user from server + + + CardDatabaseModel @@ -787,22 +817,22 @@ DeckViewContainer - + Load &local deck - + Load d&eck from server - + Ready to s&tart - + Load deck @@ -1628,117 +1658,117 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Connected. - + Disconnected from server. - + Invalid password. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1747,188 +1777,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1937,57 +1967,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1996,7 +2026,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -2005,7 +2035,7 @@ Local version is %1, remote version is %2. - + red @@ -2014,7 +2044,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2023,7 +2053,7 @@ Local version is %1, remote version is %2. - + green @@ -2032,162 +2062,162 @@ Local version is %1, remote version is %2. - + his permanents - + her permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2877,137 +2907,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases - + &Game - + Next &phase - + Ctrl+Space - + Next &turn - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows - + Ctrl+R - + &Concede - + F2 - + &Leave game - + Ctrl+Q - + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + Kicked - + You have been kicked out of the game. - + Game %1: %2 @@ -3015,27 +3045,27 @@ Please enter a name: TabMessage - + Personal &talk - + &Leave - + This user is ignoring you. - + %1 has left the server. - + %1 has joined the server. @@ -3048,27 +3078,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3178,71 +3208,60 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + User &details - + Direct &chat - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server - - - Duration - - - - - Please enter the duration of the ban (in minutes). -Enter 0 for an indefinite ban. - - WndDeckEditor diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index ea855248f..e94fc66b5 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -125,6 +125,37 @@ Escolher caminho + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + Por favor, digite a duração do banimento (em minutos). +Digite 0 para banir indefinidamente. + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + &OK + + + + &Cancel + &Cancelar + + + + Ban user from server + + + CardDatabaseModel @@ -995,22 +1026,22 @@ DeckViewContainer - + Load &local deck Carregar dec&k local - + Load d&eck from server Carregar deck do &servidor - + Ready to s&tart &Pronto para começar - + Load deck Carregar deck @@ -1858,67 +1889,67 @@ A versão local é %1 e a versão remota é %2. MessageLogWidget - + Connecting to %1... Conectando a %1... - + Disconnected from server. Desconectado do servidor. - + Invalid password. Senha incorreta. - + Protocol error. Erro de protocolo. - + The game has been closed. O jogo foi fechado. - + %1 is now watching the game. %1 está assistindo o jogo agora. - + %1 is not watching the game any more. %1 não está mais assistindo o jogo. - + %1 is not ready to start the game any more. %1 não está mais pronto para começar o jogo. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. %1 tirou um %2 com um dado de %3 lados. - + %1 draws %n card(s). %1 compra %n card. @@ -1926,208 +1957,208 @@ A versão local é %1 e a versão remota é %2. - + %1 undoes his last draw. %1 desfaz sua última compra. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 desfaz sua última compra (%2). - + %1 undoes her last draw (%2). - + from table vindo do campo de batalha - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library o card do fundo do seu grimório - + the bottom card of her library - + from the bottom of his library vindo do fundo do seu grimório - + from the bottom of her library - + the top card of his library o card do topo do seu grimório - + the top card of her library - + from the top of his library vindo do topo do seu grimório - + from the top of her library - + from library vindo do grimório - + from sideboard vindo do sideboard - + from the stack vindo da pilha - + %1 gives %2 control over %3. %1 dá controle para %2 sobre %3. - + %1 puts %2 into play tapped%3. %1 põe %2 em jogo virado%3. - + %1 puts %2 into play%3. %1 põe %2 no campo de batalha %3. - + %1 puts %2%3 into graveyard. %1 põe %2 no cemitério%3. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2 para a mão%3. - + %1 puts %2%3 into his library. %1 põe %2 no seu grimório%3. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 põe %2 no fundo do seu grimório%3. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 põe %2 no topo do seu grimório%3. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 põe %2 no seu grimório na posição %4%3. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 move %2 para o sideboard%3. - + %1 plays %2%3. %1 põe %2 na pilha%3. - - + + a card um card - + %1 flips %2 face-down. %1 vira %2 para baixo. - + %1 flips %2 face-up. %1 vira %2 para cima. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 points from %2's %3 to %4's %5. %1 aponta para %5 de %4 com %3 de %2. @@ -2146,7 +2177,7 @@ A versão local é %1 e a versão remota é %2. - + red vermelho @@ -2154,7 +2185,7 @@ A versão local é %1 e a versão remota é %2. - + yellow amarelo @@ -2162,7 +2193,7 @@ A versão local é %1 e a versão remota é %2. - + green verde @@ -2170,72 +2201,72 @@ A versão local é %1 e a versão remota é %2. - + %1 sets counter %2 to %3 (%4%5). %1 altera o marcador %2 para %3 (%4%5). - + %1 sets PT of %2 to %3. %1 altera o P/R de %2 para %3. - + %1 sets annotation of %2 to %3. %1 altera a nota de %2 para%3. - + %1 is looking at the top %2 cards %3. %1 está olhando para os %2 cards do topo %3. - + The game has started. O jogo começou. - + Connected. Conectado. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + You have joined game #%1. Você entrou no jogo nº %1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 saiu do jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck nº %2. - + %1 is ready to start the game. %1 está pronto para começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. @@ -2248,22 +2279,22 @@ A versão local é %1 e a versão remota é %2. %1 compra %2 cards. - + %1 destroys %2. %1 destrói %2. - + %1 creates token: %2%3. %1 cria a ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta para %4 com %3 de %2 . - + %1 places %n %2 counter(s) on %3 (now %4). %1 põe %n marcador %2 em %3 (agora %4). @@ -2271,7 +2302,7 @@ A versão local é %1 e a versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 tira %n marcador %2 em %3 (agora %4). @@ -2279,37 +2310,37 @@ A versão local é %1 e a versão remota é %2. - + %1 %2 %3. %1 %2 %3. - + %1 is looking at %2. %1 está olhando para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 para %3. - + %1 reveals %2. %1 revela %2. - + ending phase fase final - + It is now %1's turn. Agora é o turno de %1. @@ -2318,7 +2349,7 @@ A versão local é %1 e a versão remota é %2. %1 embaralha o seu grimório. - + %1 takes a mulligan to %n. @@ -2326,117 +2357,117 @@ A versão local é %1 e a versão remota é %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + her permanents - + %1 randomly reveals %2%3 to %4. %1 revela aleatoriamente %2%3. para %4. - + %1 randomly reveals %2%3. %1 revela aleatoriamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 para %4. - + %1 reveals %2%3. %1 revela %2%3. - + untap step etapa de desvirar - + upkeep step etapa de manutenção - + draw step etapa de compra - + first main phase primeira fase principal - + beginning of combat step etapa de início de combate - + declare attackers step etapa de declaracão de atacantes - + declare blockers step etapa de declaração de bloqueadores - + combat damage step etapa de dano de combate - + end of combat step etapa de fim de combate - + second main phase segunda fase principal - + It is now the %1. Agora é a %1. - + taps vira - + untaps desvira - + %1 sets %2 to not untap normally. %1 define que %2 não desvira normalmente. - + %1 sets %2 to untap normally. %1 define que %2 desvira normalmente. - + his permanents as suas permanentes @@ -3173,137 +3204,137 @@ Por favor, entre um nome: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases &Etapas - + &Game &Jogo - + Next &phase Próxima &etapa - + Ctrl+Space Ctrl+Espaço - + Next &turn Próximo &turno - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Apagar todas as setas locais - + Ctrl+R Ctrl+R - + &Concede &Conceder - + F2 F2 - + &Leave game &Sair do jogo - + Ctrl+Q Ctrl+Q - + &Say: &Falar: - + Concede Conceder - + Are you sure you want to concede this game? Você tem certeza que deseja conceder este jogo? - + Leave game Sair do jogo - + Are you sure you want to leave this game? Você tem certeza que deseja sair deste jogo? - + Kicked Chutado - + You have been kicked out of the game. Você foi chutado do jogo. - + Game %1: %2 Jogo %1: %2 @@ -3311,27 +3342,27 @@ Por favor, entre um nome: TabMessage - + Personal &talk Chat &privado - + &Leave &Sair - + This user is ignoring you. Este usuário está ignorando você. - + %1 has left the server. %1 saiu do servidor. - + %1 has joined the server. %1 entrou no servidor. @@ -3344,27 +3375,27 @@ Por favor, entre um nome: TabRoom - + &Say: &Falar: - + Chat Chat - + &Room &Sala - + &Leave room S&air da sala - + You are flooding the chat. Please wait a couple of seconds. Você está flodando o chat. Por favor, espere alguns segundos. @@ -3486,70 +3517,68 @@ Por favor, entre um nome: UserList - + Users online: %1 Usuários online: %1 - + Users in this room: %1 Usuários nesta sala: %1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Usuários ignorados online: %1 / %2 - + User &details &Detalhes do usuário - + Direct &chat &Chat direto - + Add to &buddy list Adicionar à &lista de amigos - + Remove from &buddy list Remover da li&sta de amigos - + Add to &ignore list Adicionar à li&sta dos ignorados - + Remove from &ignore list Remover da lista dos i&gnorados - + Ban from &server Ban&ir do servidor - Duration - Duração + Duração - Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - Por favor, digite a duração do banimento (em minutos). + Por favor, digite a duração do banimento (em minutos). Digite 0 para banir indefinidamente. diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index ed2d3b20f..ea4aa9044 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -125,6 +125,37 @@ Escolher directório + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + Por favor introduza a duração do banimento (em minutos). +Introduza 0 para um banimento indefinido. + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + + + + + &Cancel + &Cancelar + + + + Ban user from server + + + CardDatabaseModel @@ -995,22 +1026,22 @@ DeckViewContainer - + Load &local deck Carregar deck l&ocal - + Load d&eck from server Carregar deck do &servidor - + Ready to s&tart &Pronto para começar - + Load deck Carregar deck @@ -1862,92 +1893,92 @@ Versão local é %1, versão remota é %2. MessageLogWidget - + Connecting to %1... Ligando a %1... - + Connected. Ligado. - + Disconnected from server. Desligado do servidor. - + Invalid password. Password incorrecto. - + Protocol version mismatch. Client: %1, Server: %2 Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - + Protocol error. Erro de protocolo. - + You have joined game #%1. Você entrou no jogo #%1. - + %1 has joined the game. %1 entrou no jogo. - + %1 has left the game. %1 abandonou o jogo. - + The game has been closed. Este jogo foi encerrado. - + %1 is now watching the game. %1 está agora a ver o jogo. - + %1 is not watching the game any more. %1 já não está a ver o jogo. - + %1 has loaded a local deck. %1 carregou um deck local. - + %1 has loaded deck #%2. %1 carregou o deck #%2. - + %1 is ready to start the game. %1 está pronto a começar o jogo. - + %1 is not ready to start the game any more. %1 já não está pronto a começar o jogo. - + %1 has conceded the game. %1 concedeu o jogo. - + The game has started. O jogo começou. @@ -1956,7 +1987,7 @@ Versão local é %1, versão remota é %2. %1 baralha o grimório. - + %1 rolls a %2 with a %3-sided die. %1 obteve %2 com um dado de %3 faces. @@ -1969,157 +2000,157 @@ Versão local é %1, versão remota é %2. %1 compra %2 cartas. - + from table vindo da mesa - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library a carta do fundo do seu grimório - + the bottom card of her library - + from the bottom of his library do fundo do seu grimório - + from the bottom of her library - + the top card of his library a carta do topo do seu grimório - + the top card of her library - + from the top of his library do topo do seu grimório - + from the top of her library - + from library do grimório - + from sideboard do sideboard - + from the stack da pilha - + %1 puts %2 into play tapped%3. %1 coloca %2 em jogo virado(a)%3. - + %1 puts %2 into play%3. %1 coloca %2 em jogo %3. - + %1 puts %2%3 into graveyard. %1 coloca %2%3 no cemitério. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2%3 para a mão. - + %1 puts %2%3 into his library. %1 coloca %2%3 no seu grimório. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 coloca %2%3 no fundo do seu grimório. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 coloca %2%3 no topo do seu grimório. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 coloca %2%3 no seu grimório na posição %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 move %2%3 para o sideboard. - + %1 plays %2%3. %1 joga %2%3. - + %1 takes a mulligan to %n. @@ -2127,17 +2158,17 @@ Versão local é %1, versão remota é %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 places %n %2 counter(s) on %3 (now %4). %1 coloca %n %2 marcador em %3 (agora com %4). @@ -2145,7 +2176,7 @@ Versão local é %1, versão remota é %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 remove %n %2 marcador de %3 (agora com %4). @@ -2153,28 +2184,28 @@ Versão local é %1, versão remota é %2. - - + + a card uma carta - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 draws %n card(s). %1 compra %n carta. @@ -2182,67 +2213,67 @@ Versão local é %1, versão remota é %2. - + %1 undoes his last draw. %1 desfaz a sua última compra. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 desfaz a sua última compra (%2). - + %1 undoes her last draw (%2). - + %1 gives %2 control over %3. %1 dá controlo sobre %3 a %2. - + %1 flips %2 face-down. %1 volta a face de %2 para baixo. - + %1 flips %2 face-up. %1 volta a face de %2 para cima. - + %1 destroys %2. %1 destrói %2. - + %1 attaches %2 to %3's %4. %1 anexa %2 a %4 de %3. - + %1 unattaches %2. %1 desanexa %2. - + %1 creates token: %2%3. %1 cria ficha: %2%3. - + %1 points from %2's %3 to %4. %1 aponta de %3 de %2 para %4. - + %1 points from %2's %3 to %4's %5. %1 aponta de %3 de %2 para %5 de %4. @@ -2261,7 +2292,7 @@ Versão local é %1, versão remota é %2. - + red vermelho @@ -2269,7 +2300,7 @@ Versão local é %1, versão remota é %2. - + yellow amarelo @@ -2277,7 +2308,7 @@ Versão local é %1, versão remota é %2. - + green verde @@ -2285,162 +2316,162 @@ Versão local é %1, versão remota é %2. - + his permanents as suas permanentes - + her permanents - + %1 %2 %3. %1 %2 %3. - + taps vira - + untaps desvira - + %1 sets counter %2 to %3 (%4%5). %1 altera o número de marcadores %2 para %3(%4%5). - + %1 sets %2 to not untap normally. %1 define %2 para não desvirar normalmente. - + %1 sets %2 to untap normally. %1 define %2 para desvirar normalmente. - + %1 sets PT of %2 to %3. %1 define o P/R de %2 como %3. - + %1 sets annotation of %2 to %3. %1 coloca uma nota de %2 em%3. - + %1 is looking at the top %2 cards %3. %1 está a olhar para as %2 cartas do topo %3. - + %1 is looking at %2. %1 está a olhar para %2. - + %1 stops looking at %2. %1 para de olhar para %2. - + %1 reveals %2 to %3. %1 revela %2 a %3. - + %1 reveals %2. %1 revela %2. - + %1 randomly reveals %2%3 to %4. %1 revela aleatoreamente %2%3. a %4. - + %1 randomly reveals %2%3. %1 revela aleatoreamente %2%3. - + %1 reveals %2%3 to %4. %1 revela %2%3 a %4. - + %1 reveals %2%3. %1 revela %2%3. - + It is now %1's turn. É agora o turno de %1. - + untap step Etapa de Desvirar - + upkeep step Etapa de Manutenção - + draw step Etapa de Compra - + first main phase 1ª Fase Principal (pré-combate) - + beginning of combat step Etapa de Início de Combate - + declare attackers step Etapa de Declaração de Atacantes - + declare blockers step Etapa de Declaração de Bloqueadores - + combat damage step Etapa de Dano de Combate - + end of combat step Etapa de Fim de Combate - + second main phase 2ª Fase Principal (pós-combate) - + ending phase Fase Final - + It is now the %1. É agora a %1. @@ -3177,137 +3208,137 @@ Por favor introduza um nome: TabGame - + F5 F5 - + F6 F6 - + F7 F7 - + F8 F8 - + F9 F9 - + F10 F10 - + &Phases Fa&ses - + &Game &Jogo - + Next &phase Próxima &fase - + Ctrl+Space Ctrl+Space - + Next &turn Próximo &turno - + Ctrl+Return Ctrl+Return - + Ctrl+Enter Ctrl+Enter - + &Remove all local arrows &Remover todas as setas locais - + Ctrl+R Ctrl+R - + &Concede &Conceder - + F2 F2 - + &Leave game Sair do &jogo - + Ctrl+Q Ctrl+Q - + &Say: &Dizer: - + Concede Conceder - + Are you sure you want to concede this game? Tem a certeza que deseja conceder este jogo? - + Leave game Sair do jogo - + Are you sure you want to leave this game? Tem a certeza que deseja sair deste jogo? - + Kicked Expulso - + You have been kicked out of the game. Você foi expulso do jogo. - + Game %1: %2 Jogo %1: %2 @@ -3315,27 +3346,27 @@ Por favor introduza um nome: TabMessage - + Personal &talk Conversação &privada - + &Leave &Abandonar - + This user is ignoring you. Este utilizador esta a ignorar-te. - + %1 has left the server. %1 abandonou o servidor. - + %1 has joined the server. %1 entrou no servidor. @@ -3348,27 +3379,27 @@ Por favor introduza um nome: TabRoom - + &Say: &Dizer: - + Chat - + &Room &Sala - + &Leave room &Abandonar a sala - + You are flooding the chat. Please wait a couple of seconds. Estás a inundar o chat .Por favor aguarde alguns segundos. @@ -3490,70 +3521,68 @@ Por favor introduza um nome: UserList - + Users online: %1 Utilizadores online: %1 - + Users in this room: %1 Utilizadores nesta sala:%1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Utilizadores ignorados online %1 / %2 - + User &details Detalhes do &utilizador - + Direct &chat Conversação &directa - + Add to &buddy list Adicionar a lista de &amigos - + Remove from &buddy list Remover da lista de &amigos - + Add to &ignore list Adicionar a lista a &ignorar - + Remove from &ignore list Remover da lista a &ignorar - + Ban from &server Banir do &servidor - Duration - Duração + Duração - Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - Por favor introduza a duração do banimento (em minutos). + Por favor introduza a duração do banimento (em minutos). Introduza 0 para um banimento indefinido. diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 43d41057f..94e9d03af 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -121,6 +121,37 @@ Выберите путь + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + Введите продолжительность бана (в минутах). +Введите 0 чтобы забанить пожизненно. + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + &Ок + + + + &Cancel + &Отмена + + + + Ban user from server + + + CardDatabaseModel @@ -941,22 +972,22 @@ DeckViewContainer - + Load &local deck Загрузить &колоду с диска - + Load d&eck from server Загрузить к&олоду с сервера - + Ready to s&tart &Готов - + Load deck Загрузить колоду @@ -1786,92 +1817,92 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... Подключение к %1... - + Connected. Подключено. - + Disconnected from server. Нет соединения с сервером. - + Invalid password. Неверный пароль. - + Protocol version mismatch. Client: %1, Server: %2 Несовпадение версий. Клиент: %1, Сервер: %2 - + Protocol error. Ошибка протокола. - + You have joined game #%1. Вы присоединились к игре #%1. - + %1 has joined the game. %1 присоединился к игре. - + %1 has left the game. %1 покиул игру. - + The game has been closed. Игра закрыта. - + %1 is now watching the game. %1 вошел как зритель. - + %1 is not watching the game any more. %1 покинул зрительскую ложу. - + %1 has loaded a local deck. %1 загрузил колоду с диска. - + %1 has loaded deck #%2. %1 загрузил колоду #%2. - + %1 is ready to start the game. %1 готов начать игру. - + %1 is not ready to start the game any more. %1 все еще не готов. - + %1 has conceded the game. %1 решил сдаться. - + The game has started. Игра началась. @@ -1880,7 +1911,7 @@ Local version is %1, remote version is %2. %1 размешивает библиотеку. - + %1 rolls a %2 with a %3-sided die. %1 выкинул %2 / %3. @@ -1893,168 +1924,168 @@ Local version is %1, remote version is %2. %1 взял %2 карт. - + %1 undoes his last draw. %1 отменил последнее взятие. - + %1 undoes his last draw (%2). %1 отменил %2 последних взятий. - + from table с поля битвы - + from graveyard из кладбища - + from exile из изгнания - + from hand из руки - + the bottom card of his library нижнюю карту своей библиотеки - + from the bottom of his library со дна своей библиотеки - + the top card of his library верхнюю карту своей библиотеки - + from the top of his library с верха своей библиотеки - + from library из библиотеки - + from sideboard из сайда - + from the stack из стека - - + + a card карту - + %1 gives %2 control over %3. %1 передает %2 контроль над %3. - + %1 puts %2 into play%3. %1 поместил %2 на поле битвы %3. - + %1 puts %2%3 into graveyard. %1 поместил %2%3 на кладбище. - + %1 exiles %2%3. %1 изгоняет %2%3. - + %1 moves %2%3 to hand. %1 поместил %2%3 в руку. - + %1 puts %2%3 into his library. %1 поместил %2%3 в свою библиотеку. - + %1 puts %2%3 on bottom of his library. %1 поместил %2%3 на дно своей библиотеки. - + %1 puts %2%3 on top of his library. %1 поместил %2%3 на верх своей библиотеки. - + %1 puts %2%3 into his library at position %4. %1 поместил %2%3 в свою библиотеку %4 сверху. - + %1 moves %2%3 to sideboard. %1 поместил %2%3 в сайд. - + %1 plays %2%3. %1 разыгрывает %2%3. - + %1 flips %2 face-down. %1 перевернул %2 лицом вниз. - + %1 flips %2 face-up. %1 перевернул %2 лицом вверх. - + %1 destroys %2. %1 уничтожил %2. - + %1 attaches %2 to %3's %4. %1 присоединил %2 к %4 игрока %3. - + %1 unattaches %2. %1 отсоединил %2. - + %1 creates token: %2%3. %1 создал фишку: %2%3. - + %1 points from %2's %3 to %4. %1 указывает с %3 контролируемого %2 на %4. - + %1 points from %2's %3 to %4's %5. %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. @@ -2075,22 +2106,22 @@ Local version is %1, remote version is %2. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 draws %n card(s). %1 взял %n карту. @@ -2099,62 +2130,62 @@ Local version is %1, remote version is %2. - + %1 undoes her last draw. - + %1 undoes her last draw (%2). - + the bottom card of her library - + from the bottom of her library - + the top card of her library - + from the top of her library - + %1 puts %2 into play tapped%3. %1 положил %2 повернутым на поле битвы%3. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into her library at position %4. - + %1 takes a mulligan to %n. @@ -2163,17 +2194,17 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 places %n %2 counter(s) on %3 (now %4). %1 поместил %n %2 жетон на %3 (теперь %4). @@ -2182,7 +2213,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). %1 снял %n %2 жетон с %3 (теперь %4). @@ -2191,7 +2222,7 @@ Local version is %1, remote version is %2. - + red красный @@ -2200,7 +2231,7 @@ Local version is %1, remote version is %2. - + yellow желтый @@ -2209,7 +2240,7 @@ Local version is %1, remote version is %2. - + green зеленый @@ -2218,162 +2249,162 @@ Local version is %1, remote version is %2. - + his permanents свои перманенты - + her permanents - + %1 %2 %3. %1 %2 %3. - + taps повернул - + untaps развернул - + %1 sets counter %2 to %3 (%4%5). %1 установил жетон %2 на %3 (%4%5). - + %1 sets %2 to not untap normally. %2 теперь не разворачивается как обычно (%1). - + %1 sets %2 to untap normally. %2 теперь разворачивается как обычно (%1). - + %1 sets PT of %2 to %3. %1 установил Силу/Защиту %2 %3. - + %1 sets annotation of %2 to %3. %1 сделал пометку на %2 "%3". - + %1 is looking at the top %2 cards %3. %1 смотрит верхние %2 карт библиотеки %3. - + %1 is looking at %2. %1 просматривает %2. - + %1 stops looking at %2. %1 закончил просматривать %2. - + %1 reveals %2 to %3. %1 показывает его %2 %3. - + %1 reveals %2. %1 открыл его %2. - + %1 randomly reveals %2%3 to %4. %1 показывает случайно выбранную%3 карту (%2) %4. - + %1 randomly reveals %2%3. %1 открывает случайно выбранную%3 карту (%2). - + %1 reveals %2%3 to %4. %1 показывает%2%3 %4. - + %1 reveals %2%3. %1 открывает%2%3. - + It is now %1's turn. Ход игрока %1. - + untap step шаг разворота - + upkeep step шаг поддержки - + draw step шаг взятия карты - + first main phase первая главная фаза - + beginning of combat step шаг начала битвы - + declare attackers step шаг назначения атакующих - + declare blockers step шаг назначения блокирующих - + combat damage step шаг нанесения повреждений - + end of combat step шаг завершения битвы - + second main phase вторая главная фаза - + ending phase заключительный шаг - + It is now the %1. Сейчас %1. @@ -3076,137 +3107,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases &Фазы - + &Game &Игра - + Next &phase Следующая &фаза - + Ctrl+Space - + Next &turn Следующий &ход - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows &Удалить все указатели - + Ctrl+R - + &Concede Сда&юсь! - + F2 - + &Leave game Покинуть и&гру - + Ctrl+Q - + &Say: Ска&зать: - + Concede Сдаться - + Are you sure you want to concede this game? Испугался? - + Leave game Покинуть игру - + Are you sure you want to leave this game? Вы уверены, что хотите уйти? - + Kicked Выкинут - + You have been kicked out of the game. Вас выкинули из игры. - + Game %1: %2 Игра %1: %2 @@ -3214,27 +3245,27 @@ Please enter a name: TabMessage - + Personal &talk Личная &беседа - + &Leave &Покинуть - + This user is ignoring you. Этот пользователь добавил вас в игнор-лист. - + %1 has left the server. %1 отключился. - + %1 has joined the server. %1 зашел на сервер. @@ -3247,27 +3278,27 @@ Please enter a name: TabRoom - + &Say: &Сказать: - + Chat Чат - + &Room &Комната - + &Leave room &Покинуть комнату - + You are flooding the chat. Please wait a couple of seconds. Кажется, Вы нафлудили. Пожалуйста, подождите пару секунд. @@ -3381,70 +3412,68 @@ Please enter a name: UserList - + Users online: %1 Пользователей онлайн: %1 - + Users in this room: %1 Пользователей в этой комнате: %1 - + Buddies online: %1 / %2 Друзей онлайн: %1 / %2 - + Ignored users online: %1 / %2 Игнорируемых пользователей онлайн: %1 / %2 - + User &details Данные о &пользователе - + Direct &chat Обратиться &лично - + Add to &buddy list Добавить в список &друзей - + Remove from &buddy list &Удалить из друзей - + Add to &ignore list Добавить в &игнор-лист - + Remove from &ignore list Удалить и&з игнор-листа - + Ban from &server За&банить на сервере - Duration - Продолжительность + Продолжительность - Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - Введите продолжительность бана (в минутах). + Введите продолжительность бана (в минутах). Введите 0 чтобы забанить пожизненно. diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index aca97b8b3..596131a71 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -121,6 +121,36 @@ + + BanDialog + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + + + + + Please enter the reason for the ban. +This is only saved for moderators and cannot be seen by the banned person. + + + + + &OK + + + + + &Cancel + + + + + Ban user from server + + + CardDatabaseModel @@ -787,22 +817,22 @@ DeckViewContainer - + Load &local deck - + Load d&eck from server - + Ready to s&tart - + Load deck @@ -1628,117 +1658,117 @@ Local version is %1, remote version is %2. MessageLogWidget - + Connecting to %1... - + Connected. - + Disconnected from server. - + Invalid password. - + Protocol version mismatch. Client: %1, Server: %2 - + Protocol error. - + You have joined game #%1. - + %1 has joined the game. - + %1 has left the game. - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + %1 has loaded a local deck. - + %1 has loaded deck #%2. - + %1 is ready to start the game. - + %1 is not ready to start the game any more. - + %1 has conceded the game. - + The game has started. - + %1 has restored connection to the game. - + %1 has lost connection to the game. - + %1 shuffles %2. - + %1 rolls a %2 with a %3-sided die. - + %1 draws %n card(s). @@ -1747,188 +1777,188 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. @@ -1937,57 +1967,57 @@ Local version is %1, remote version is %2. - + %1 draws his initial hand. - + %1 draws her initial hand. - + %1 flips %2 face-down. - + %1 flips %2 face-up. - + %1 destroys %2. - + %1 attaches %2 to %3's %4. - + %1 unattaches %2. - + %1 creates token: %2%3. - + %1 points from %2's %3 to %4. - + %1 points from %2's %3 to %4's %5. - + %1 places %n %2 counter(s) on %3 (now %4). @@ -1996,7 +2026,7 @@ Local version is %1, remote version is %2. - + %1 removes %n %2 counter(s) from %3 (now %4). @@ -2005,7 +2035,7 @@ Local version is %1, remote version is %2. - + red @@ -2014,7 +2044,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2023,7 +2053,7 @@ Local version is %1, remote version is %2. - + green @@ -2032,162 +2062,162 @@ Local version is %1, remote version is %2. - + his permanents - + her permanents - + %1 %2 %3. - + taps - + untaps - + %1 sets counter %2 to %3 (%4%5). - + %1 sets %2 to not untap normally. - + %1 sets %2 to untap normally. - + %1 sets PT of %2 to %3. - + %1 sets annotation of %2 to %3. - + %1 is looking at the top %2 cards %3. - + %1 is looking at %2. - + %1 stops looking at %2. - + %1 reveals %2 to %3. - + %1 reveals %2. - + %1 randomly reveals %2%3 to %4. - + %1 randomly reveals %2%3. - + %1 reveals %2%3 to %4. - + %1 reveals %2%3. - + It is now %1's turn. - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -2877,137 +2907,137 @@ Please enter a name: TabGame - + F5 - + F6 - + F7 - + F8 - + F9 - + F10 - + &Phases - + &Game - + Next &phase - + Ctrl+Space - + Next &turn - + Ctrl+Return - + Ctrl+Enter - + &Remove all local arrows - + Ctrl+R - + &Concede - + F2 - + &Leave game - + Ctrl+Q - + &Say: - + Concede - + Are you sure you want to concede this game? - + Leave game - + Are you sure you want to leave this game? - + Kicked - + You have been kicked out of the game. - + Game %1: %2 @@ -3015,27 +3045,27 @@ Please enter a name: TabMessage - + Personal &talk - + &Leave - + This user is ignoring you. - + %1 has left the server. - + %1 has joined the server. @@ -3048,27 +3078,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3178,71 +3208,60 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + User &details - + Direct &chat - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server - - - Duration - - - - - Please enter the duration of the ban (in minutes). -Enter 0 for an indefinite ban. - - WndDeckEditor diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index b92a182b9..33670ef43 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -484,11 +484,12 @@ Command_ShutdownServer::Command_ShutdownServer(const QString &_reason, int _minu insertItem(new SerializableItem_String("reason", _reason)); insertItem(new SerializableItem_Int("minutes", _minutes)); } -Command_BanFromServer::Command_BanFromServer(const QString &_userName, int _minutes) +Command_BanFromServer::Command_BanFromServer(const QString &_userName, int _minutes, const QString &_reason) : ModeratorCommand("ban_from_server") { insertItem(new SerializableItem_String("user_name", _userName)); insertItem(new SerializableItem_Int("minutes", _minutes)); + insertItem(new SerializableItem_String("reason", _reason)); } void ProtocolItem::initializeHashAuto() { diff --git a/common/protocol_items.dat b/common/protocol_items.dat index ab83e15ab..2e0f86031 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -80,4 +80,4 @@ 6:mulligan:i,number 7:update_server_message 7:shutdown_server:s,reason:i,minutes -8:ban_from_server:s,user_name:i,minutes \ No newline at end of file +8:ban_from_server:s,user_name:i,minutes:s,reason \ No newline at end of file diff --git a/common/protocol_items.h b/common/protocol_items.h index 810357a88..efeb7f932 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -735,9 +735,10 @@ public: class Command_BanFromServer : public ModeratorCommand { Q_OBJECT public: - Command_BanFromServer(const QString &_userName = QString(), int _minutes = -1); + Command_BanFromServer(const QString &_userName = QString(), int _minutes = -1, const QString &_reason = QString()); QString getUserName() const { return static_cast(itemMap.value("user_name"))->getData(); }; int getMinutes() const { return static_cast(itemMap.value("minutes"))->getData(); }; + QString getReason() const { return static_cast(itemMap.value("reason"))->getData(); }; static SerializableItem *newItem() { return new Command_BanFromServer; } int getItemId() const { return ItemId_Command_BanFromServer; } }; diff --git a/common/server.cpp b/common/server.cpp index e4c68ff9a..07f7c7cfe 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -52,7 +52,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString QMutexLocker locker(&serverMutex); if (name.size() > 35) name = name.left(35); - AuthenticationResult authState = checkUserPassword(name, password); + AuthenticationResult authState = checkUserPassword(session, name, password); if (authState == PasswordWrong) return authState; diff --git a/common/server.h b/common/server.h index 1c35f5a1b..d2f15e76f 100644 --- a/common/server.h +++ b/common/server.h @@ -43,7 +43,6 @@ public: virtual QMap getBuddyList(const QString &name) = 0; virtual QMap getIgnoreList(const QString &name) = 0; - virtual bool getUserBanned(Server_ProtocolHandler * /*client*/, const QString & /*userName*/) const { return false; } protected: void prepareDestroy(); QList clients; @@ -51,7 +50,7 @@ protected: QMap rooms; virtual bool userExists(const QString &user) = 0; - virtual AuthenticationResult checkUserPassword(const QString &user, const QString &password) = 0; + virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password) = 0; virtual ServerInfo_User *getUserData(const QString &name) = 0; int getUsersCount() const; int getGamesCount() const; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index b929edb60..de50435a5 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -280,8 +280,6 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain QString userName = cmd->getUsername().simplified(); if (userName.isEmpty() || (userInfo != 0)) return RespContextError; - if (server->getUserBanned(this, userName)) - return RespWrongPassword; authState = server->loginUser(this, userName, cmd->getPassword()); if (authState == PasswordWrong) return RespWrongPassword; diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index 06effa016..7bd64c58d 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -111,7 +111,6 @@ CREATE TABLE IF NOT EXISTS `cockatrice_users` ( `avatar_bmp` blob NOT NULL, `registrationDate` datetime NOT NULL, `active` tinyint(1) NOT NULL, - `banned` tinyint(1) NOT NULL, `token` char(32) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) @@ -149,3 +148,12 @@ CREATE TABLE `cockatrice_buddylist` ( KEY `id_user2` (`id_user2`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `cockatrice_bans` ( + `id_user` int(7) unsigned zerofill NOT NULL, + `id_admin` int(7) unsigned zerofill NOT NULL, + `time_from` datetime NOT NULL, + `minutes` int(6) NOT NULL, + `reason` text NOT NULL, + KEY `id_user` (`id_user`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index fffc1cec3..1bb126e53 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -169,25 +169,32 @@ bool Servatrice::execSqlQuery(QSqlQuery &query) return false; } -AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QString &password) +AuthenticationResult Servatrice::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password) { + serverMutex.lock(); + QHostAddress address = static_cast(handler)->getPeerAddress(); + for (int i = 0; i < addressBanList.size(); ++i) + if (address == addressBanList[i].first) + return PasswordWrong; + serverMutex.unlock(); + QMutexLocker locker(&dbMutex); const QString method = settings->value("authentication/method").toString(); if (method == "none") return UnknownUser; else if (method == "sql") { checkSql(); - + QSqlQuery query; - query.prepare("select banned, password from " + dbPrefix + "_users where name = :name and active = 1"); + query.prepare("select a.password, timediff(now(), date_add(b.time_from, interval b.minutes minute)) < 0, b.minutes <=> 0 from " + dbPrefix + "_users a left join " + dbPrefix + "_bans b on b.id_user = a.id and b.time_from = (select max(c.time_from) from " + dbPrefix + "_bans c where c.id_user = a.id) where a.name = :name and a.active = 1"); query.bindValue(":name", user); if (!execSqlQuery(query)) return PasswordWrong; if (query.next()) { - if (query.value(0).toInt()) + if (query.value(1).toInt() || query.value(2).toInt()) return PasswordWrong; - if (query.value(1).toString() == password) + if (query.value(0).toString() == password) return PasswordRight; else return PasswordWrong; @@ -325,19 +332,6 @@ QMap Servatrice::getIgnoreList(const QString &name) return result; } -bool Servatrice::getUserBanned(Server_ProtocolHandler *client, const QString &userName) const -{ - QMutexLocker locker(&serverMutex); - QHostAddress address = static_cast(client)->getPeerAddress(); - for (int i = 0; i < addressBanList.size(); ++i) - if (address == addressBanList[i].first) - return true; - for (int i = 0; i < nameBanList.size(); ++i) - if (userName == nameBanList[i].first) - return true; - return false; -} - void Servatrice::updateBanTimer() { QMutexLocker locker(&serverMutex); @@ -346,11 +340,6 @@ void Servatrice::updateBanTimer() addressBanList.removeAt(i); else ++i; - for (int i = 0; i < nameBanList.size(); ) - if (--(nameBanList[i].second) <= 0) - nameBanList.removeAt(i); - else - ++i; } void Servatrice::updateLoginMessage() diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 1a3d1d090..5a2fb1b89 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -74,13 +74,11 @@ public: int getUsersWithAddress(const QHostAddress &address) const; QMap getBuddyList(const QString &name); QMap getIgnoreList(const QString &name); - bool getUserBanned(Server_ProtocolHandler *client, const QString &userName) const; void addAddressBan(const QHostAddress &address, int minutes) { addressBanList.append(QPair(address, minutes)); } - void addNameBan(const QString &name, int minutes) { nameBanList.append(QPair(name, minutes)); } void scheduleShutdown(const QString &reason, int minutes); protected: bool userExists(const QString &user); - AuthenticationResult checkUserPassword(const QString &user, const QString &password); + AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password); private: QTimer *pingClock, *statusUpdateClock, *banTimeoutClock; QTcpServer *tcpServer; @@ -90,7 +88,6 @@ private: int serverId; int uptime; QList > addressBanList; - QList > nameBanList; int maxGameInactivityTime, maxPlayerInactivityTime; int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser; ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 769e65888..895fcee2b 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -488,14 +488,14 @@ ResponseCode ServerSocketInterface::cmdBanFromServer(Command_BanFromServer *cmd, ServerSocketInterface *user = static_cast(server->getUsers().value(userName)); if (user->getUserInfo()->getUserLevel() & ServerInfo_User::IsRegistered) { // Registered users can be banned by name. - if (minutes == 0) { - QMutexLocker locker(&servatrice->dbMutex); - QSqlQuery query; - query.prepare("update " + servatrice->getDbPrefix() + "_users set banned=1 where name = :name"); - query.bindValue(":name", userName); - servatrice->execSqlQuery(query); - } else - servatrice->addNameBan(userName, minutes); + QMutexLocker locker(&servatrice->dbMutex); + QSqlQuery query; + query.prepare("insert into " + servatrice->getDbPrefix() + "_bans (id_user, id_admin, time_from, minutes, reason) values(:id_user, :id_admin, NOW(), :minutes, :reason)"); + query.bindValue(":id_user", getUserIdInDB(userName)); + query.bindValue(":id_admin", getUserIdInDB(userInfo->getName())); + query.bindValue(":minutes", minutes); + query.bindValue(":reason", cmd->getReason()); + servatrice->execSqlQuery(query); } else { // Unregistered users must be banned by IP address. // Indefinite address bans are not reasonable -> default to 30 minutes. From 7bfa3e6d3ad32bc42c1b173fa1c45e7edb316eba Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 25 Jun 2011 23:42:16 +0200 Subject: [PATCH 63/87] cuckoo --- cockatrice/src/messagelogwidget.cpp | 2 +- cockatrice/src/soundengine.cpp | 7 ++++++- cockatrice/src/soundengine.h | 1 + sounds/cuckoo.wav | Bin 0 -> 43340 bytes 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 sounds/cuckoo.wav diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 216fe138e..fa69419f1 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -77,7 +77,7 @@ void MessageLogWidget::logGameJoined(int gameId) void MessageLogWidget::logJoin(Player *player) { - soundEngine->notification(); + soundEngine->cuckoo(); myAppend(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); } diff --git a/cockatrice/src/soundengine.cpp b/cockatrice/src/soundengine.cpp index 5daeae9a0..247567ccc 100644 --- a/cockatrice/src/soundengine.cpp +++ b/cockatrice/src/soundengine.cpp @@ -25,7 +25,7 @@ SoundEngine::SoundEngine(QObject *parent) void SoundEngine::cacheData() { static const QStringList fileNames = QStringList() - << "notification" << "draw" << "playcard" << "shuffle" << "tap" << "untap"; + << "notification" << "draw" << "playcard" << "shuffle" << "tap" << "untap" << "cuckoo"; for (int i = 0; i < fileNames.size(); ++i) { QFile file(settingsCache->getSoundPath() + "/" + fileNames[i] + ".raw"); file.open(QIODevice::ReadOnly); @@ -75,3 +75,8 @@ void SoundEngine::untap() { playSound("untap"); } + +void SoundEngine::cuckoo() +{ + playSound("cuckoo"); +} diff --git a/cockatrice/src/soundengine.h b/cockatrice/src/soundengine.h index 312a476bc..d65b3f2dd 100644 --- a/cockatrice/src/soundengine.h +++ b/cockatrice/src/soundengine.h @@ -25,6 +25,7 @@ public slots: void shuffle(); void tap(); void untap(); + void cuckoo(); }; extern SoundEngine *soundEngine; diff --git a/sounds/cuckoo.wav b/sounds/cuckoo.wav new file mode 100644 index 0000000000000000000000000000000000000000..5eba46f976c5b40f8371e2a048cd9bdfb0efe564 GIT binary patch literal 43340 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 siEX`1O? Date: Mon, 27 Jun 2011 14:42:57 +0200 Subject: [PATCH 64/87] limit game name length to 50 characters --- common/server_protocolhandler.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index de50435a5..d1df01775 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -475,7 +475,10 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm for (int i = 0; i < gameTypeList.size(); ++i) gameTypes.append(gameTypeList[i]->getData()); - Server_Game *game = room->createGame(cmd->getDescription(), cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); + QString description = cmd->getDescription(); + if (description.size() > 50) + description = description.left(50); + Server_Game *game = room->createGame(description, cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); Server_Player *creator = game->getPlayers().values().first(); From aa38733f0393e9a6c9fc5b3ae5e749e4227b6771 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 27 Jun 2011 14:50:07 +0200 Subject: [PATCH 65/87] fixed Server_Card::resetState --- common/server_card.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/server_card.cpp b/common/server_card.cpp index 4c47f20d2..3d34ac530 100644 --- a/common/server_card.cpp +++ b/common/server_card.cpp @@ -39,8 +39,8 @@ void Server_Card::resetState() counters.clear(); setTapped(false); setAttacking(false); - power = 0; - toughness = 0; + power = -1; + toughness = -1; setAnnotation(QString()); setDoesntUntap(false); } From d2d06b853f2fe2becc9a5a533a6eeff698c5089d Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 27 Jun 2011 15:29:17 +0200 Subject: [PATCH 66/87] edit field for minimum number of players to allow multi-column layout for --- cockatrice/src/dlg_settings.cpp | 11 +++++++++++ cockatrice/src/dlg_settings.h | 4 +++- cockatrice/src/gamescene.cpp | 4 +++- cockatrice/src/settingscache.cpp | 8 ++++++++ cockatrice/src/settingscache.h | 4 ++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index 3f1c5a3d4..01d4445a5 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "carddatabase.h" #include "dlg_settings.h" #include "main.h" @@ -242,8 +243,17 @@ AppearanceSettingsPage::AppearanceSettingsPage() invertVerticalCoordinateCheckBox->setChecked(settingsCache->getInvertVerticalCoordinate()); connect(invertVerticalCoordinateCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setInvertVerticalCoordinate(int))); + minPlayersForMultiColumnLayoutLabel = new QLabel; + minPlayersForMultiColumnLayoutEdit = new QSpinBox; + minPlayersForMultiColumnLayoutEdit->setMinimum(2); + minPlayersForMultiColumnLayoutEdit->setValue(settingsCache->getMinPlayersForMultiColumnLayout()); + connect(minPlayersForMultiColumnLayoutEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setMinPlayersForMultiColumnLayout(int))); + minPlayersForMultiColumnLayoutLabel->setBuddy(minPlayersForMultiColumnLayoutEdit); + QGridLayout *tableGrid = new QGridLayout; tableGrid->addWidget(invertVerticalCoordinateCheckBox, 0, 0, 1, 2); + tableGrid->addWidget(minPlayersForMultiColumnLayoutLabel, 1, 0, 1, 1); + tableGrid->addWidget(minPlayersForMultiColumnLayoutEdit, 1, 1, 1, 1); tableGroupBox = new QGroupBox; tableGroupBox->setLayout(tableGrid); @@ -289,6 +299,7 @@ void AppearanceSettingsPage::retranslateUi() tableGroupBox->setTitle(tr("Table grid layout")); invertVerticalCoordinateCheckBox->setText(tr("Invert vertical coordinate")); + minPlayersForMultiColumnLayoutLabel->setText(tr("Minimum player count for multi-column layout:")); zoneViewGroupBox->setTitle(tr("Zone view layout")); zoneViewSortByNameCheckBox->setText(tr("Sort by name")); diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index 859376d62..f7bd1a522 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -14,6 +14,7 @@ class QGroupBox; class QCheckBox; class QLabel; class QCloseEvent; +class QSpinBox; class AbstractSettingsPage : public QWidget { public: @@ -65,10 +66,11 @@ signals: void playerAreaBgChanged(const QString &path); void cardBackPicturePathChanged(const QString &path); private: - QLabel *handBgLabel, *stackBgLabel, *tableBgLabel, *playerAreaBgLabel, *cardBackPicturePathLabel; + QLabel *handBgLabel, *stackBgLabel, *tableBgLabel, *playerAreaBgLabel, *cardBackPicturePathLabel, *minPlayersForMultiColumnLayoutLabel; QLineEdit *handBgEdit, *stackBgEdit, *tableBgEdit, *playerAreaBgEdit, *cardBackPicturePathEdit; QCheckBox *displayCardNamesCheckBox, *horizontalHandCheckBox, *invertVerticalCoordinateCheckBox, *zoneViewSortByNameCheckBox, *zoneViewSortByTypeCheckBox; QGroupBox *zoneBgGroupBox, *cardsGroupBox, *handGroupBox, *tableGroupBox, *zoneViewGroupBox; + QSpinBox *minPlayersForMultiColumnLayoutEdit; public: AppearanceSettingsPage(); void retranslateUi(); diff --git a/cockatrice/src/gamescene.cpp b/cockatrice/src/gamescene.cpp index 8785adcc8..8a8dd17c5 100644 --- a/cockatrice/src/gamescene.cpp +++ b/cockatrice/src/gamescene.cpp @@ -3,6 +3,7 @@ #include "zoneviewwidget.h" #include "zoneviewzone.h" #include "phasestoolbar.h" +#include "settingscache.h" #include #include #include @@ -14,6 +15,7 @@ GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent) { animationTimer = new QBasicTimer; addItem(phasesToolbar); + connect(settingsCache, SIGNAL(minPlayersForMultiColumnLayoutChanged()), this, SLOT(rearrange())); } GameScene::~GameScene() @@ -59,7 +61,7 @@ void GameScene::rearrange() if (firstPlayer == -1) firstPlayer = 0; const int playersCount = playersPlaying.size(); - const int columns = playersCount < 4 ? 1 : 2; + const int columns = playersCount < settingsCache->getMinPlayersForMultiColumnLayout() ? 1 : 2; const int rows = ceil((qreal) playersCount / columns); qreal sceneHeight = 0, sceneWidth = -playerAreaSpacing; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index f7494d767..8c3cee479 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -24,6 +24,7 @@ SettingsCache::SettingsCache() displayCardNames = settings->value("cards/displaycardnames", true).toBool(); horizontalHand = settings->value("hand/horizontal", true).toBool(); invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool(); + minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 5).toInt(); tapAnimation = settings->value("cards/tapanimation", true).toBool(); zoneViewSortByName = settings->value("zoneview/sortbyname", true).toBool(); @@ -143,6 +144,13 @@ void SettingsCache::setInvertVerticalCoordinate(int _invertVerticalCoordinate) emit invertVerticalCoordinateChanged(); } +void SettingsCache::setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout) +{ + minPlayersForMultiColumnLayout = _minPlayersForMultiColumnLayout; + settings->setValue("interface/min_players_multicolumn", minPlayersForMultiColumnLayout); + emit minPlayersForMultiColumnLayoutChanged(); +} + void SettingsCache::setTapAnimation(int _tapAnimation) { tapAnimation = _tapAnimation; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index c834716a6..b3f1ae6c0 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -20,6 +20,7 @@ signals: void displayCardNamesChanged(); void horizontalHandChanged(); void invertVerticalCoordinateChanged(); + void minPlayersForMultiColumnLayoutChanged(); void soundPathChanged(); private: QSettings *settings; @@ -34,6 +35,7 @@ private: bool displayCardNames; bool horizontalHand; bool invertVerticalCoordinate; + int minPlayersForMultiColumnLayout; bool tapAnimation; bool zoneViewSortByName, zoneViewSortByType; bool soundEnabled; @@ -57,6 +59,7 @@ public: bool getDisplayCardNames() const { return displayCardNames; } bool getHorizontalHand() const { return horizontalHand; } bool getInvertVerticalCoordinate() const { return invertVerticalCoordinate; } + int getMinPlayersForMultiColumnLayout() const { return minPlayersForMultiColumnLayout; } bool getTapAnimation() const { return tapAnimation; } bool getZoneViewSortByName() const { return zoneViewSortByName; } bool getZoneViewSortByType() const { return zoneViewSortByType; } @@ -80,6 +83,7 @@ public slots: void setDisplayCardNames(int _displayCardNames); void setHorizontalHand(int _horizontalHand); void setInvertVerticalCoordinate(int _invertVerticalCoordinate); + void setMinPlayersForMultiColumnLayout(int _minPlayersForMultiColumnLayout); void setTapAnimation(int _tapAnimation); void setZoneViewSortByName(int _zoneViewSortByName); void setZoneViewSortByType(int _zoneViewSortByType); From 9f098f2a6d9509b5641ca108874fec75c7760c09 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 28 Jun 2011 00:15:19 +0200 Subject: [PATCH 67/87] translation update --- cockatrice/translations/cockatrice_cs.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_de.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_en.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_es.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_fr.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_ja.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_pl.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_pt-br.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_pt.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_ru.ts | 121 ++++++++++---------- cockatrice/translations/cockatrice_sk.ts | 121 ++++++++++---------- 11 files changed, 693 insertions(+), 638 deletions(-) diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index db45c0b21..a3f47786d 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -37,86 +37,91 @@ AppearanceSettingsPage - + Zone background pictures - + Path to hand background: - + Path to stack background: - + Path to table background: - + Path to player info background: - + Path to picture of card back: - + Card rendering - + Display card names on cards having a picture - + Hand layout - + Display hand horizontally (wastes space) - + Table grid layout - + Invert vertical coordinate - + + Minimum player count for multi-column layout: + + + + Zone view layout - + Sort by name - + Sort by type - - - - - + + + + + Choose path @@ -786,12 +791,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General @@ -1138,59 +1143,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error - + Your card database is invalid. Would you like to go back and set the correct path? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User interface - + Deck editor - + Messages - + &Close @@ -1358,50 +1363,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - + + English - - - + + + Choose path - + Personal settings - + Language: - + Download card pictures on the fly - + Paths - + Decks directory: - + Pictures directory: - + Path to card database: @@ -2225,22 +2230,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Add message - + Message: - + &Add - + &Remove @@ -3170,37 +3175,37 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + &Double-click cards to play them (instead of single-click) - + Animation settings - + &Tap/untap animation - + Enable &sounds - + Path to sounds directory: - + Choose path diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index ce769bacb..6ca4c1849 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -60,66 +60,71 @@ AppearanceSettingsPage - + Zone background pictures Hintergrundbilder für Kartenzonen - + Path to hand background: Hintergrundbild für die Hand: - + Path to stack background: Hintergrundbild für den Stapel: - + Path to table background: Hintergrundbild für das Spielfeld: - + Path to player info background: Hintergrundbild für den Spielerbereich: - + Path to picture of card back: Pfad zum Bild der Kartenrückseite: - + Card rendering Kartendarstellung - + Display card names on cards having a picture Kartennamen darstellen auch bei Karten, die Bilder haben - + Hand layout Kartenhand - + Display hand horizontally (wastes space) Hand horizonal anzeigen (verschwendet Platz) - + Table grid layout Spielfeldraster + + + Minimum player count for multi-column layout: + Mindestspielerzahl für mehrspaltige Anordnung: + Economical layout Platzsparende Anordnung - + Invert vertical coordinate Vertikale Koordinate umkehren @@ -128,17 +133,17 @@ Platzsparende Anordnung - + Zone view layout Aussehen des Zonenbetrachters - + Sort by name nach Namen sortieren - + Sort by type nach Kartentypen sortieren @@ -147,11 +152,11 @@ standardmäßig alphabetisch sortieren - - - - - + + + + + Choose path Pfad auswählen @@ -1199,12 +1204,12 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) Karten&preisfunktionen anschalten (benutzt Daten von blacklotusproject.com) - + General Allgemeines @@ -1612,9 +1617,9 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic DlgSettings - - - + + + Error Fehler @@ -1631,52 +1636,52 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Der Pfad zum Kartenbilderverzeichnis ist ungültig. - + Your card database is invalid. Would you like to go back and set the correct path? Ihre Kartendatenbank ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Der Pfad zu Ihrem Deckordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Der Pfad zu Ihrem Kartenbilderordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? - + Settings Einstellungen - + General Allgemeines - + Appearance Erscheinungsbild - + User interface Bedienung - + Deck editor Deckeditor - + Messages Nachrichten - + &Close S&chließen @@ -2114,50 +2119,50 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic GeneralSettingsPage - - - + + + Choose path Pfad auswählen - + Personal settings Persönliche Einstellungen - + Language: Sprache: - + Download card pictures on the fly Kartenbilder dynamisch herunterladen - + Paths Pfade - + Decks directory: Verzeichnis mit Decklisten: - + Pictures directory: Verzeichnis mit Bilddateien: - + Path to card database: Pfad zur Kartendatenbank: - - + + English Deutsch @@ -3339,12 +3344,12 @@ Lokale Version ist %1, Serverversion ist %2. MessagesSettingsPage - + &Add &Hinzufügen - + &Remove &Entfernen @@ -3357,12 +3362,12 @@ Lokale Version ist %1, Serverversion ist %2. Entfernen - + Add message Nachricht hinzufügen - + Message: Nachricht: @@ -4574,37 +4579,37 @@ Bitte geben Sie einen Namen ein: UserInterfaceSettingsPage - + General interface settings Allgemeine Bedienung - + &Double-click cards to play them (instead of single-click) Karten durch &Doppelklick ausspielen (statt Einzelklick) - + Animation settings Animationseinstellungen - + &Tap/untap animation Animiertes &Tappen/Enttappen - + Enable &sounds &Sound anschalten - + Path to sounds directory: Pfad zum Verzeichnis mit den Sounddateien: - + Choose path Pfad auswählen diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index c0d65f991..3fcd278e0 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -37,86 +37,91 @@ AppearanceSettingsPage - + Zone background pictures - + Path to hand background: - + Path to stack background: - + Path to table background: - + Path to player info background: - + Path to picture of card back: - + Card rendering - + Display card names on cards having a picture - + Hand layout - + Display hand horizontally (wastes space) - + Table grid layout - + Invert vertical coordinate - + + Minimum player count for multi-column layout: + + + + Zone view layout - + Sort by name - + Sort by type - - - - - + + + + + Choose path @@ -786,12 +791,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General @@ -1138,59 +1143,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error - + Your card database is invalid. Would you like to go back and set the correct path? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User interface - + Deck editor - + Messages - + &Close @@ -1358,50 +1363,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - - + + + Choose path - + Personal settings - + Language: - + Download card pictures on the fly - + Paths - + Decks directory: - + Pictures directory: - + Path to card database: - - + + English English @@ -2231,22 +2236,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + &Add - + &Remove - + Add message - + Message: @@ -3176,37 +3181,37 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + &Double-click cards to play them (instead of single-click) - + Animation settings - + &Tap/untap animation - + Enable &sounds - + Path to sounds directory: - + Choose path diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index d39522e99..e5e199b29 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -37,66 +37,71 @@ AppearanceSettingsPage - + Zone background pictures Imagenes de la zona de fondo - + Path to hand background: Ruta a la imagen de fondo de la mano: - + Path to stack background: Ruta a la imagen de fondo de la pila: - + Path to table background: Ruta a la imagen de fondo de la mesa: - + Path to player info background: Ruta a la imagen de fondo de la información del jugador: - + Path to picture of card back: Ruta al reverso de las cartas: - + Card rendering Renderizado de las cartas - + Display card names on cards having a picture Mostrar nombre de las cartas en aquellas que tengan imagen - + Hand layout Disposición de la mano - + Display hand horizontally (wastes space) Mostrar la mano horizontalmente (desperdicia espacio) - + Table grid layout Disposición de la rejilla de la mesa + + + Minimum player count for multi-column layout: + + Economical layout Disposición Económica - + Invert vertical coordinate Invertir coordenada vertical @@ -105,26 +110,26 @@ Disposición económica - + Zone view layout Distribución de la zona de visionado - + Sort by name Ordenar por nombre - + Sort by type Ordenar por tipo - - - - - + + + + + Choose path Elija ruta @@ -1129,12 +1134,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General General @@ -1488,9 +1493,9 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error Error @@ -1507,52 +1512,52 @@ This is only saved for moderators and cannot be seen by the banned person.La ruta a tu directorio de imagenes de las cartas es invalida. - + Your card database is invalid. Would you like to go back and set the correct path? Tu base de datos de cartas es invalida. ¿Deseas volver y seleccionar la ruta correcta? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? La ruta a tu directorio de mazos es invalida. ¿Deseas volver y seleccionar la ruta correcta? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? La ruta a tu directorio de imagenes de las cartas es invalida.¿Deseas volver y seleccionar la ruta correcta? - + Settings Preferencias - + General General - + Appearance Apariencia - + User interface Interfaz de usuario - + Deck editor - + Messages Mensajes - + &Close &Cerrar @@ -1724,50 +1729,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - - + + + Choose path Elija ruta - + Personal settings Preferencias personales - + Language: Idioma: - + Download card pictures on the fly Descargar imagenes de las cartas al vuelo - + Paths Rutas - + Decks directory: Directorio de mazos: - + Pictures directory: Directorio de imagenes: - + Path to card database: Ruta a la base de datos de las cartas: - - + + English Español @@ -2617,22 +2622,22 @@ La versión local es %1, la versión remota es %2. MessagesSettingsPage - + &Add &Añadir - + &Remove &Quitar - + Add message Añadir mensaje - + Message: Mensaje: @@ -3637,37 +3642,37 @@ Por favor, introduzca un nombre: UserInterfaceSettingsPage - + General interface settings Preferencias generales de la interfaz - + &Double-click cards to play them (instead of single-click) &Doble click en las cartas para jugarlas (en lugar de un solo click) - + Animation settings Opciones de animación - + &Tap/untap animation Animación de &girar/enderezar - + Enable &sounds - + Path to sounds directory: - + Choose path Elija ruta diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index ecdd4519b..1aec9f3c5 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -37,86 +37,91 @@ AppearanceSettingsPage - + Zone background pictures Zone images de fond - + Path to hand background: Chemin pour les images de fond de main: - + Path to stack background: Chemin pour les images de fond de pile: - + Path to table background: Chemin pour les images d'arrière-plan: - + Path to player info background: Chemin pour les images de fond d'affichage d'informations: - + Path to picture of card back: Chemin pour les images de dos des cartes: - + Card rendering Rendu des cartes - + Display card names on cards having a picture Afficher le nom des cartes ayant une image - + Hand layout Disposition de la main - + Display hand horizontally (wastes space) Montrer la main horizontalement - + Table grid layout Disposition en forme de grille - + Invert vertical coordinate Inverser la disposition du champ de bataille - + + Minimum player count for multi-column layout: + + + + Zone view layout Voir disposition de la zone - + Sort by name Tri par nom - + Sort by type Tri par type - - - - - + + + + + Choose path Choisir le chemin @@ -991,12 +996,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General Géneral @@ -1350,59 +1355,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error Erreur - + Your card database is invalid. Would you like to go back and set the correct path? Votre base de carte est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Le chemin d'accès pour le répertoire de votre deck est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Le chemin d'accès pour le répertoire de vos images est invalide. Souhaitez-vous redéfinir le chemin d'accès? - + Settings Paramètres - + General Géneral - + Appearance Apparence - + User interface Interface utilisateur - + Deck editor - + Messages Messages - + &Close &Fermer @@ -1575,50 +1580,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - + + English Français - - - + + + Choose path Choisir chemin d'accès - + Personal settings Paramètres personnels - + Language: Langue: - + Download card pictures on the fly Charger les images de cartes à la volée - + Paths Chemins - + Decks directory: Répertoire des decks: - + Pictures directory: Répertoire des images: - + Path to card database: Chemin vers la base de cartes: @@ -2490,22 +2495,22 @@ La version la plus récente est %1, l'ancienne version est %2. MessagesSettingsPage - + Add message Ajouter message - + Message: Message: - + &Add &Ajouter - + &Remove &Enlever @@ -3498,37 +3503,37 @@ Entrez un nom s'il vous plaît: UserInterfaceSettingsPage - + General interface settings Réglages généraux de l'interface - + &Double-click cards to play them (instead of single-click) &Double cliquer sur la carte pour la jouer (au lieu d'un simple clic) - + Animation settings Réglage des animations - + &Tap/untap animation &Animation d'engagement et de dégagement - + Enable &sounds - + Path to sounds directory: - + Choose path diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index 5f63f5619..f6d1b9c07 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -37,58 +37,58 @@ AppearanceSettingsPage - + Zone background pictures 背景画像の設定 - + Path to hand background: 手札の背景画像へのパス: - + Path to stack background: スタックゾーンの背景画像へのパス: - + Path to table background: テーブルの背景画像へのパス: - + Path to player info background: プレイヤー画像へのパス: - + Path to picture of card back: カード背面画像へのパス: - + Card rendering カードレンダリング - + Display card names on cards having a picture やや不明 画像持ちカードのカードネームを表示する - + Hand layout 手札のレイアウト - + Display hand horizontally (wastes space) 手札を横に並べる(スペースを消費します) - + Table grid layout テーブルグリッドのレイアウト @@ -97,31 +97,36 @@ 省スペースレイアウト(カード間間隔を細かくできます) - + Invert vertical coordinate 垂直反転調整 - + + Minimum player count for multi-column layout: + + + + Zone view layout ゾーンビューレイアウト - + Sort by name 名前で整列 - + Sort by type タイプで整列 - - - - - + + + + + Choose path 画像の指定 @@ -834,12 +839,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General 全般 @@ -1186,59 +1191,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error エラー - + Your card database is invalid. Would you like to go back and set the correct path? あなたのカードデータベースは無効です.前に戻って正しいパスを設定してください. - + The path to your deck directory is invalid. Would you like to go back and set the correct path? あなたのデッキディレクトリへのパスは無効です.前に戻って正しいパスを設定してください. - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? あなたのカード画像ディレクトリへのパスは無効です.前に戻って正しいパスを設定してください. - + Settings 設定 - + General 全般 - + Appearance 外観 - + User interface ユーザーインターフェース - + Deck editor - + Messages メッセージ - + &Close @@ -1410,50 +1415,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - - + + + Choose path パスを選択 - + Personal settings 個人設定 - + Language: 言語: - + Download card pictures on the fly - + Paths パス - + Decks directory: デッキディレクトリ: - + Pictures directory: カード画像のディレクトリ: - + Path to card database: カードデータベースのパス: - - + + English Japanese @@ -2278,22 +2283,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + &Add 追加 - + &Remove 削除 - + Add message メッセージを追加する - + Message: メッセージ: @@ -3273,37 +3278,37 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings インターフェース総合設定 - + &Double-click cards to play them (instead of single-click) ダブルクリックでカードをプレイする(シングルクリックの代わり) - + Animation settings アニメーション設定 - + &Tap/untap animation タップ/アンタップアニメーション - + Enable &sounds - + Path to sounds directory: - + Choose path diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 564e6ac25..07fd65103 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -37,86 +37,91 @@ AppearanceSettingsPage - + Zone background pictures - + Path to hand background: - + Path to stack background: - + Path to table background: - + Path to player info background: - + Path to picture of card back: - + Card rendering - + Display card names on cards having a picture - + Hand layout - + Display hand horizontally (wastes space) - + Table grid layout - + Invert vertical coordinate - + + Minimum player count for multi-column layout: + + + + Zone view layout - + Sort by name - + Sort by type - - - - - + + + + + Choose path @@ -786,12 +791,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General @@ -1138,59 +1143,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error - + Your card database is invalid. Would you like to go back and set the correct path? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User interface - + Deck editor - + Messages - + &Close @@ -1358,50 +1363,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - + + English - - - + + + Choose path - + Personal settings - + Language: - + Download card pictures on the fly - + Paths - + Decks directory: - + Pictures directory: - + Path to card database: @@ -2225,22 +2230,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Add message - + Message: - + &Add - + &Remove @@ -3170,37 +3175,37 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + &Double-click cards to play them (instead of single-click) - + Animation settings - + &Tap/untap animation - + Enable &sounds - + Path to sounds directory: - + Choose path diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index e94fc66b5..478d43f94 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -37,57 +37,57 @@ AppearanceSettingsPage - + Zone background pictures Imagens de fundo das zonas - + Path to hand background: Caminho para o fundo da mão: - + Path to stack background: Caminho para o fundo da pilha: - + Path to table background: Caminho para o fundo da mesa: - + Path to player info background: Caminho para o fundo das informações do jogador: - + Path to picture of card back: Caminho para a imagem do verso dos cards: - + Card rendering Renderização do card - + Display card names on cards having a picture Mostrar o nome dos cards nos cards que tem imagem - + Hand layout Layout da mão - + Display hand horizontally (wastes space) Mostrar a mão na horizontal (desperdiça espaço) - + Table grid layout Layout do campo de batalha @@ -96,31 +96,36 @@ Layout econômico - + Invert vertical coordinate Inverter a coordenada vertical - + + Minimum player count for multi-column layout: + + + + Zone view layout Layout de vista da zona - + Sort by name Ordenar por nome - + Sort by type Ordenar por tipo - - - - - + + + + + Choose path Escolher caminho @@ -995,12 +1000,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General Geral @@ -1354,59 +1359,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error Erro - + Your card database is invalid. Would you like to go back and set the correct path? O seu banco de dados de cards é inválido. Você gostaria de voltar e corrigir o caminho? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? O caminho para a sua pasta de decks é inválido. Você gostaria de voltar e corrigir o caminho? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? O caminho para a sua pasta de imagens de cards é inválido. Você gostaria de voltar e corrigir o caminho? - + Settings Configurações - + General Geral - + Appearance Aparência - + User interface Interface do usuário - + Deck editor - + Messages Mensagens - + &Close &Fechar @@ -1578,50 +1583,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - - + + + Choose path Escolher caminho - + Personal settings Configurações pessoais - + Language: Língua: - + Download card pictures on the fly Baixar a imagem dos cards em tempo real - + Paths Caminhos - + Decks directory: Pasta de decks: - + Pictures directory: Pasta de imagens: - + Path to card database: Caminho para o banco de dados dos cards: - - + + English Português do Brasil @@ -2475,22 +2480,22 @@ A versão local é %1 e a versão remota é %2. MessagesSettingsPage - + &Add &Adicionar - + &Remove &Remover - + Add message Adicionar mensagem - + Message: Mensagem: @@ -3479,37 +3484,37 @@ Por favor, entre um nome: UserInterfaceSettingsPage - + General interface settings Configurações gerais de interface - + &Double-click cards to play them (instead of single-click) &Duplo clique nos cards para jogá-los (ao invés de clique simples) - + Animation settings Configurações de animação - + &Tap/untap animation Animação de &virar/desvirar - + Enable &sounds - + Path to sounds directory: - + Choose path Escolher caminho diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index ea4aa9044..676094319 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -37,57 +37,57 @@ AppearanceSettingsPage - + Zone background pictures Zona das imagens de fundo - + Path to hand background: Directório da imagem de fundo da mão: - + Path to stack background: Directório da imagem de fundo da pilha: - + Path to table background: Directório da imagem de fundo do campo de batalha: - + Path to player info background: Directório da imagem de fundo da informação de jogador: - + Path to picture of card back: Directório da imagem do verso da carta: - + Card rendering Rendering da carta - + Display card names on cards having a picture Mostrar o nome em cartas com imagem - + Hand layout Disposição da Mão - + Display hand horizontally (wastes space) Mostrar mão horizontalmente (desperdiça espaço) - + Table grid layout Esquema da mesa @@ -96,31 +96,36 @@ Esquema económico - + Invert vertical coordinate Inverter coordenada vertical - + + Minimum player count for multi-column layout: + + + + Zone view layout Distribuição da zona de vizualização - + Sort by name Ordenar por nome - + Sort by type Ordenar por tipo - - - - - + + + + + Choose path Escolher directório @@ -995,12 +1000,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General Geral @@ -1354,59 +1359,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error Erro - + Your card database is invalid. Would you like to go back and set the correct path? A sua base de dados é inválida. Gostaria de voltar atrás e corrigir o directório? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? O directório do seu deck é inválido. Gostaria de voltar atrás e corrigir o directório? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? O directório das imagens das cartas é inválido. Gostaria de voltar atrás e corrigir o directório? - + Settings Definições - + General Geral - + Appearance Aparência - + User interface Interface do utilizador - + Deck editor - + Messages Mensagens - + &Close &Fechar @@ -1578,50 +1583,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - + + English Português - - - + + + Choose path Escolher directório - + Personal settings Defenições pessoais - + Language: Língua: - + Download card pictures on the fly Baixar a imagem das cartas ao passar - + Paths Directórios - + Decks directory: Directório dos decks: - + Pictures directory: Directório das imagens: - + Path to card database: Directório da base de dados de cartas: @@ -2479,22 +2484,22 @@ Versão local é %1, versão remota é %2. MessagesSettingsPage - + Add message Adicionar mensagem - + Message: Mensagem: - + &Add &Adicionar - + &Remove &Remover @@ -3483,37 +3488,37 @@ Por favor introduza um nome: UserInterfaceSettingsPage - + General interface settings Configurações gerais da interface - + &Double-click cards to play them (instead of single-click) Clicar &duas vezes nas cartas para as jogar (ao invés de clicar apenas uma vez) - + Animation settings Configurações de Animações - + &Tap/untap animation Animação de &virar/desvirar - + Enable &sounds - + Path to sounds directory: - + Choose path Escolher directório diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 94e9d03af..af264167f 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -37,86 +37,91 @@ AppearanceSettingsPage - + Zone background pictures Фоновые изображения - + Path to hand background: Рука: - + Path to stack background: Стек: - + Path to table background: Поле битвы: - + Path to player info background: Панель игрока: - + Path to picture of card back: Рубашки карт: - + Card rendering Отрисовка карт - + Display card names on cards having a picture Отображать название карты поверх изображения - + Hand layout Расположение руки - + Display hand horizontally (wastes space) Отбражать руку горизонтально - + Table grid layout Сетка - + Invert vertical coordinate Инвертировать вертикальные координату - + + Minimum player count for multi-column layout: + + + + Zone view layout Сортировка карт - + Sort by name Сортировать по имени - + Sort by type Сортировать по типу - - - - - + + + + + Choose path Выберите путь @@ -941,12 +946,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General Основные @@ -1293,59 +1298,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error Ошибка - + Your card database is invalid. Would you like to go back and set the correct path? База карт не найдена. Вернуться и задать правильный путь? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? Ваши колоды отсутствуют в указанной папке. Вернуться и задать правильный путь? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? Изображения карт не найдены. Вернуться и задать правильный путь? - + Settings Настройки - + General Основные - + Appearance Внешний вид - + User interface Интерфейс - + Deck editor - + Messages Сообщения - + &Close &Закрыть @@ -1513,50 +1518,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - + + English Русский - - - + + + Choose path Путь - + Personal settings Личные настройки - + Language: Язык: - + Download card pictures on the fly Загружать изображения карт на лету - + Paths Расположение - + Decks directory: Колоды: - + Pictures directory: Изображения карт: - + Path to card database: Путь к базе карт: @@ -2412,22 +2417,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Add message Добавить сообщение - + Message: Сообщение: - + &Add &Добавить - + &Remove &Удалить @@ -3374,37 +3379,37 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings Основные настройки интерфейса - + &Double-click cards to play them (instead of single-click) &Двойной клик чтобы разыграть карту (вместо одинарного) - + Animation settings Настройки анимации - + &Tap/untap animation &Анимировать поворот/разворот карты - + Enable &sounds - + Path to sounds directory: - + Choose path diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 596131a71..63a3c8409 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -37,86 +37,91 @@ AppearanceSettingsPage - + Zone background pictures - + Path to hand background: - + Path to stack background: - + Path to table background: - + Path to player info background: - + Path to picture of card back: - + Card rendering - + Display card names on cards having a picture - + Hand layout - + Display hand horizontally (wastes space) - + Table grid layout - + Invert vertical coordinate - + + Minimum player count for multi-column layout: + + + + Zone view layout - + Sort by name - + Sort by type - - - - - + + + + + Choose path @@ -786,12 +791,12 @@ This is only saved for moderators and cannot be seen by the banned person. DeckEditorSettingsPage - + Enable &price tag feature (using data from blacklotusproject.com) - + General @@ -1138,59 +1143,59 @@ This is only saved for moderators and cannot be seen by the banned person. DlgSettings - - - + + + Error - + Your card database is invalid. Would you like to go back and set the correct path? - + The path to your deck directory is invalid. Would you like to go back and set the correct path? - + The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Settings - + General - + Appearance - + User interface - + Deck editor - + Messages - + &Close @@ -1358,50 +1363,50 @@ This is only saved for moderators and cannot be seen by the banned person. GeneralSettingsPage - - + + English - - - + + + Choose path - + Personal settings - + Language: - + Download card pictures on the fly - + Paths - + Decks directory: - + Pictures directory: - + Path to card database: @@ -2225,22 +2230,22 @@ Local version is %1, remote version is %2. MessagesSettingsPage - + Add message - + Message: - + &Add - + &Remove @@ -3170,37 +3175,37 @@ Please enter a name: UserInterfaceSettingsPage - + General interface settings - + &Double-click cards to play them (instead of single-click) - + Animation settings - + &Tap/untap animation - + Enable &sounds - + Path to sounds directory: - + Choose path From 0120d2a0195ed040d02e2198d282d7a9a5d76289 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 28 Jun 2011 02:37:49 +0200 Subject: [PATCH 68/87] cardInfoPopup fix; chatView fix --- cockatrice/src/abstractcarditem.cpp | 7 ++++++- cockatrice/src/abstractcarditem.h | 3 ++- cockatrice/src/cardinfowidget.cpp | 7 +++---- cockatrice/src/cardinfowidget.h | 5 +---- cockatrice/src/chatview.cpp | 14 ++++++++++---- cockatrice/src/chatview.h | 5 +++-- cockatrice/src/messagelogwidget.cpp | 2 +- cockatrice/src/player.cpp | 2 ++ cockatrice/src/tab.cpp | 8 +++++--- cockatrice/src/tab.h | 2 +- cockatrice/src/tab_game.cpp | 4 ++-- cockatrice/src/tab_message.cpp | 2 +- cockatrice/src/tab_room.cpp | 2 +- 13 files changed, 38 insertions(+), 25 deletions(-) diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index 020b6dfc0..20e7c8e9e 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -26,6 +26,7 @@ AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, QGraphi AbstractCardItem::~AbstractCardItem() { qDebug() << "AbstractCardItem destructor:" << name; + emit deleteCardInfoPopup(name); } QRectF AbstractCardItem::boundingRect() const @@ -157,6 +158,10 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * void AbstractCardItem::setName(const QString &_name) { + if (name == _name) + return; + + emit deleteCardInfoPopup(name); disconnect(info, 0, this, 0); name = _name; info = db->getCard(name); @@ -213,7 +218,7 @@ void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::MidButton) - emit deleteCardInfoPopup(); + emit deleteCardInfoPopup(name); // This function ensures the parent function doesn't mess around with our selection. event->accept(); diff --git a/cockatrice/src/abstractcarditem.h b/cockatrice/src/abstractcarditem.h index c1345564f..e11bdf852 100644 --- a/cockatrice/src/abstractcarditem.h +++ b/cockatrice/src/abstractcarditem.h @@ -30,7 +30,7 @@ private slots: signals: void hovered(AbstractCardItem *card); void showCardInfoPopup(QPoint pos, QString cardName); - void deleteCardInfoPopup(); + void deleteCardInfoPopup(QString cardName); public: enum { Type = typeCard }; int type() const { return Type; } @@ -50,6 +50,7 @@ public: bool getTapped() const { return tapped; } void setTapped(bool _tapped, bool canAnimate = false); void processHoverEvent(); + void deleteCardInfoPopup() { emit deleteCardInfoPopup(name); } protected: QSizeF getTranslatedSize(QPainter *painter) const; void transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle); diff --git a/cockatrice/src/cardinfowidget.cpp b/cockatrice/src/cardinfowidget.cpp index 37b14edfd..1ce584b2f 100644 --- a/cockatrice/src/cardinfowidget.cpp +++ b/cockatrice/src/cardinfowidget.cpp @@ -172,8 +172,7 @@ void CardInfoWidget::resizeEvent(QResizeEvent * /*event*/) } } -void CardInfoWidget::mouseReleaseEvent(QMouseEvent *event) +QString CardInfoWidget::getCardName() const { - if ((event->button() == Qt::MidButton) && (mode == ModePopUp)) - emit mouseReleased(); -} + return nameLabel2->text(); +} \ No newline at end of file diff --git a/cockatrice/src/cardinfowidget.h b/cockatrice/src/cardinfowidget.h index 819f514b0..21ee7ccd6 100644 --- a/cockatrice/src/cardinfowidget.h +++ b/cockatrice/src/cardinfowidget.h @@ -39,6 +39,7 @@ private: public: CardInfoWidget(ResizeMode _mode, QWidget *parent = 0, Qt::WindowFlags f = 0); void retranslateUi(); + QString getCardName() const; public slots: void setCard(CardInfo *card); @@ -50,12 +51,8 @@ private slots: void updatePixmap(); void minimizeClicked(int newMinimized); -signals: - void mouseReleased(); - protected: void resizeEvent(QResizeEvent *event); - void mouseReleaseEvent(QMouseEvent *event); }; #endif diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index 700313ee9..1b5b1e0f3 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -15,7 +15,7 @@ ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *paren connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &))); } -void ChatView::appendMessage(QString sender, QString message) +void ChatView::appendMessage(QString sender, QString message, QColor playerColor, bool playerBold) { QTextCursor cursor(document()->lastBlock()); cursor.movePosition(QTextCursor::End); @@ -35,8 +35,14 @@ void ChatView::appendMessage(QString sender, QString message) if (sender == ownName) { senderFormat.setFontWeight(QFont::Bold); senderFormat.setForeground(Qt::red); - } else - senderFormat.setForeground(QColor(0, 0, 254)); + } else { + if (playerColor == QColor()) + senderFormat.setForeground(QColor(0, 0, 254)); + else + senderFormat.setForeground(playerColor); + if (playerBold) + senderFormat.setFontWeight(QFont::Bold); + } cursor.setCharFormat(senderFormat); if (!sender.isEmpty()) sender.append(": "); @@ -156,7 +162,7 @@ void ChatView::mousePressEvent(QMouseEvent *event) void ChatView::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::MidButton) - emit deleteCardInfoPopup(); + emit deleteCardInfoPopup(QString("_")); QTextBrowser::mouseReleaseEvent(event); } diff --git a/cockatrice/src/chatview.h b/cockatrice/src/chatview.h index c17f2375f..5f9445323 100644 --- a/cockatrice/src/chatview.h +++ b/cockatrice/src/chatview.h @@ -3,6 +3,7 @@ #include #include +#include class QTextTable; class QMouseEvent; @@ -20,7 +21,7 @@ private slots: void openLink(const QUrl &link); public: ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent = 0); - void appendMessage(QString sender, QString message); + void appendMessage(QString sender, QString message, QColor playerColor = QColor(), bool playerBold = false); protected: void enterEvent(QEvent *event); void leaveEvent(QEvent *event); @@ -30,7 +31,7 @@ protected: signals: void cardNameHovered(QString cardName); void showCardInfoPopup(QPoint pos, QString cardName); - void deleteCardInfoPopup(); + void deleteCardInfoPopup(QString cardName); }; #endif \ No newline at end of file diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index fa69419f1..9b5f92bbd 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -139,7 +139,7 @@ void MessageLogWidget::logConnectionStateChanged(Player *player, bool connection void MessageLogWidget::logSay(Player *player, QString message) { - appendMessage(player->getName(), message); + appendMessage(player->getName(), message, QColor(), true); } void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 6dc53152c..fc794bd3f 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -867,6 +867,8 @@ void Player::eventMoveCard(Event_MoveCard *event, GameEventContext *context) CardItem *card = startZone->takeCard(position, event->getCardId(), startZone != targetZone); if (!card) return; + if (startZone != targetZone) + card->deleteCardInfoPopup(); card->setName(event->getCardName()); if (card->getAttachedTo() && (startZone != targetZone)) { diff --git a/cockatrice/src/tab.cpp b/cockatrice/src/tab.cpp index e85d4091c..2eed9b546 100644 --- a/cockatrice/src/tab.cpp +++ b/cockatrice/src/tab.cpp @@ -21,10 +21,12 @@ void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName) infoPopup->show(); } -void Tab::deleteCardInfoPopup() +void Tab::deleteCardInfoPopup(const QString &cardName) { if (infoPopup) { - infoPopup->deleteLater(); - infoPopup = 0; + if ((infoPopup->getCardName() == cardName) || (cardName == "_")) { + infoPopup->deleteLater(); + infoPopup = 0; + } } } diff --git a/cockatrice/src/tab.h b/cockatrice/src/tab.h index ac4b0ea5a..3fefde1a1 100644 --- a/cockatrice/src/tab.h +++ b/cockatrice/src/tab.h @@ -16,7 +16,7 @@ protected: TabSupervisor *tabSupervisor; protected slots: void showCardInfoPopup(const QPoint &pos, const QString &cardName); - void deleteCardInfoPopup(); + void deleteCardInfoPopup(const QString &cardName); private: bool contentsChanged; CardInfoWidget *infoPopup; diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 04c15c50b..2e38baf71 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -179,7 +179,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client messageLog = new MessageLogWidget(_userName); connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString))); connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); - connect(messageLog, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup())); + connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); sayLabel = new QLabel; sayEdit = new QLineEdit; sayLabel->setBuddy(sayEdit); @@ -745,7 +745,7 @@ void TabGame::newCardAdded(AbstractCardItem *card) { connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfo, SLOT(setCard(AbstractCardItem *))); connect(card, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); - connect(card, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup())); + connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); } CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) const diff --git a/cockatrice/src/tab_message.cpp b/cockatrice/src/tab_message.cpp index c79fbfee8..f4efd7f57 100644 --- a/cockatrice/src/tab_message.cpp +++ b/cockatrice/src/tab_message.cpp @@ -13,7 +13,7 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor, AbstractClient *_client, c { chatView = new ChatView(_ownName, true); connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); - connect(chatView, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup())); + connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); sayEdit = new QLineEdit; connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage())); diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index 621b4b085..b1d23c93f 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -139,7 +139,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q chatView = new ChatView(ownName, true); connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); - connect(chatView, SIGNAL(deleteCardInfoPopup()), this, SLOT(deleteCardInfoPopup())); + connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); sayLabel = new QLabel; sayEdit = new QLineEdit; sayLabel->setBuddy(sayEdit); From a86f6ba5b8a8305f491d48c22bb37a4b4e1a6a48 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 2 Jul 2011 02:14:08 +0200 Subject: [PATCH 69/87] minor change --- cockatrice/src/messagelogwidget.cpp | 2 +- common/server_protocolhandler.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 9b5f92bbd..9b452bf84 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -144,7 +144,7 @@ void MessageLogWidget::logSay(Player *player, QString message) void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) { - myAppend(QString("%1: %2").arg(sanitizeHtml(spectatorName)).arg(sanitizeHtml(message))); + appendMessage(spectatorName, message, QColor(), false); } void MessageLogWidget::logShuffle(Player *player, CardZone *zone) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index d1df01775..4ec2a5c1d 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -476,8 +476,8 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm gameTypes.append(gameTypeList[i]->getData()); QString description = cmd->getDescription(); - if (description.size() > 50) - description = description.left(50); + if (description.size() > 60) + description = description.left(60); Server_Game *game = room->createGame(description, cmd->getPassword(), cmd->getMaxPlayers(), gameTypes, cmd->getOnlyBuddies(), cmd->getOnlyRegistered(), cmd->getSpectatorsAllowed(), cmd->getSpectatorsNeedPassword(), cmd->getSpectatorsCanTalk(), cmd->getSpectatorsSeeEverything(), this); Server_Player *creator = game->getPlayers().values().first(); From 438c26e0c16322122a964d00f0cc990cbf239748 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 2 Jul 2011 02:31:05 +0200 Subject: [PATCH 70/87] DlgCreateGame: max length for description edit --- cockatrice/src/dlg_creategame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index b96c93a16..0d5b69f43 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -17,6 +17,7 @@ DlgCreateGame::DlgCreateGame(AbstractClient *_client, int _roomId, const QMapsetBuddy(descriptionEdit); + descriptionEdit->setMaxLength(60); maxPlayersLabel = new QLabel(tr("P&layers:")); maxPlayersEdit = new QSpinBox(); From be12a0b3a9342959b9eb1dfd79d42957f7587411 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 2 Jul 2011 14:36:10 +0200 Subject: [PATCH 71/87] preliminary showGamesOfUser support --- cockatrice/src/userlist.cpp | 7 +- common/protocol.cpp | 7 ++ common/protocol.h | 24 +++-- common/protocol_datastructures.cpp | 3 +- common/protocol_datastructures.h | 2 +- common/protocol_item_ids.h | 161 +++++++++++++++-------------- common/protocol_items.cpp | 6 ++ common/protocol_items.dat | 1 + common/protocol_items.h | 8 ++ common/server_game.cpp | 14 ++- common/server_game.h | 1 + common/server_protocolhandler.cpp | 23 +++++ common/server_protocolhandler.h | 1 + common/server_room.cpp | 14 +++ common/server_room.h | 2 + 15 files changed, 183 insertions(+), 91 deletions(-) diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index 02a04a6e3..419d8b78c 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -219,6 +219,7 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) aUserName->setEnabled(false); QAction *aDetails = new QAction(tr("User &details"), this); QAction *aChat = new QAction(tr("Direct &chat"), this); + QAction *aShowGames = new QAction(tr("Show this user's &games"), this); QAction *aAddToBuddyList = new QAction(tr("Add to &buddy list"), this); QAction *aRemoveFromBuddyList = new QAction(tr("Remove from &buddy list"), this); QAction *aAddToIgnoreList = new QAction(tr("Add to &ignore list"), this); @@ -257,7 +258,11 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) client->sendCommand(new Command_AddToList("buddy", userName)); else if (actionClicked == aRemoveFromBuddyList) client->sendCommand(new Command_RemoveFromList("buddy", userName)); - else if (actionClicked == aAddToIgnoreList) + else if (actionClicked == aShowGames) { + Command *cmd = new Command_GetGamesOfUser(userName); + connect(cmd, SIGNAL(responseReceived(ProtocolResponse *)), this, SLOT(gamesOfUserReceived(ProtocolResponse *))); + client->sendCommand(cmd); + } else if (actionClicked == aAddToIgnoreList) client->sendCommand(new Command_AddToList("ignore", userName)); else if (actionClicked == aRemoveFromIgnoreList) client->sendCommand(new Command_RemoveFromList("ignore", userName)); diff --git a/common/protocol.cpp b/common/protocol.cpp index 1129116e5..205f2b2a4 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -44,6 +44,7 @@ void ProtocolItem::initializeHash() ProtocolResponse::initializeHash(); registerSerializableItem("respjoin_room", Response_JoinRoom::newItem); registerSerializableItem("resplist_users", Response_ListUsers::newItem); + registerSerializableItem("respget_games_of_user", Response_GetGamesOfUser::newItem); registerSerializableItem("respget_user_info", Response_GetUserInfo::newItem); registerSerializableItem("respdeck_list", Response_DeckList::newItem); registerSerializableItem("respdeck_download", Response_DeckDownload::newItem); @@ -296,6 +297,12 @@ Response_DeckList::Response_DeckList(int _cmdId, ResponseCode _responseCode, Dec insertItem(_root); } +Response_GetGamesOfUser::Response_GetGamesOfUser(int _cmdId, ResponseCode _responseCode, const QList &_gameList) +{ + for (int i = 0; i < _gameList.size(); ++i) + itemList.append(_gameList[i]); +} + Response_GetUserInfo::Response_GetUserInfo(int _cmdId, ResponseCode _responseCode, ServerInfo_User *_user) : ProtocolResponse(_cmdId, _responseCode, "get_user_info") { diff --git a/common/protocol.h b/common/protocol.h index 0cb067ee2..1feda02f2 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -42,13 +42,14 @@ enum ItemId { ItemId_Event_Ping = ItemId_Other + 212, ItemId_Event_AddToList = ItemId_Other + 213, ItemId_Response_ListUsers = ItemId_Other + 300, - ItemId_Response_GetUserInfo = ItemId_Other + 301, - ItemId_Response_DeckList = ItemId_Other + 302, - ItemId_Response_DeckDownload = ItemId_Other + 303, - ItemId_Response_DeckUpload = ItemId_Other + 304, - ItemId_Response_DumpZone = ItemId_Other + 305, - ItemId_Response_JoinRoom = ItemId_Other + 306, - ItemId_Response_Login = ItemId_Other + 307, + ItemId_Response_GetGamesOfUser = ItemId_Other + 301, + ItemId_Response_GetUserInfo = ItemId_Other + 302, + ItemId_Response_DeckList = ItemId_Other + 303, + ItemId_Response_DeckDownload = ItemId_Other + 304, + ItemId_Response_DeckUpload = ItemId_Other + 305, + ItemId_Response_DumpZone = ItemId_Other + 306, + ItemId_Response_JoinRoom = ItemId_Other + 307, + ItemId_Response_Login = ItemId_Other + 308, ItemId_Invalid = ItemId_Other + 1000 }; @@ -282,6 +283,15 @@ public: QList getUserList() const { return typecastItemList(); } }; +class Response_GetGamesOfUser : public ProtocolResponse { + Q_OBJECT +public: + Response_GetGamesOfUser(int _cmdId = -1, ResponseCode _responseCode = RespOk, const QList &_gameList = QList()); + int getItemId() const { return ItemId_Response_GetGamesOfUser; } + static SerializableItem *newItem() { return new Response_GetGamesOfUser; } + QList getGameList() const { return typecastItemList(); } +}; + class Response_GetUserInfo : public ProtocolResponse { Q_OBJECT public: diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index aaf164674..3e4564c86 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -40,9 +40,10 @@ ServerInfo_UserList::ServerInfo_UserList(const QString &_itemType, const QList &_gameTypes, ServerInfo_User *_creatorInfo, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) +ServerInfo_Game::ServerInfo_Game(int _roomId, int _gameId, const QString &_description, bool _hasPassword, int _playerCount, int _maxPlayers, const QList &_gameTypes, ServerInfo_User *_creatorInfo, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) : SerializableItem_Map("game") { + insertItem(new SerializableItem_Int("room_id", _roomId)); insertItem(new SerializableItem_Int("game_id", _gameId)); insertItem(new SerializableItem_String("description", _description)); insertItem(new SerializableItem_Bool("has_password", _hasPassword)); diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 02f5336c1..40ab6751d 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -69,7 +69,7 @@ public: class ServerInfo_Game : public SerializableItem_Map { public: - ServerInfo_Game(int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, const QList &_gameTypes = QList(), ServerInfo_User *creatorInfo = 0, bool _onlyBuddies = false, bool _onlyRegistered = false, bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, int _spectatorCount = -1); + ServerInfo_Game(int _roomId = -1, int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, const QList &_gameTypes = QList(), ServerInfo_User *creatorInfo = 0, bool _onlyBuddies = false, bool _onlyRegistered = false, bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, int _spectatorCount = -1); static SerializableItem *newItem() { return new ServerInfo_Game; } int getGameId() const { return static_cast(itemMap.value("game_id"))->getData(); } QString getDescription() const { return static_cast(itemMap.value("description"))->getData(); } diff --git a/common/protocol_item_ids.h b/common/protocol_item_ids.h index cbec3eb02..6d6cb37b1 100644 --- a/common/protocol_item_ids.h +++ b/common/protocol_item_ids.h @@ -3,84 +3,85 @@ ItemId_Command_Ping = 1001, ItemId_Command_Login = 1002, ItemId_Command_Message = 1003, ItemId_Command_ListUsers = 1004, -ItemId_Command_GetUserInfo = 1005, -ItemId_Command_AddToList = 1006, -ItemId_Command_RemoveFromList = 1007, -ItemId_Command_DeckList = 1008, -ItemId_Command_DeckNewDir = 1009, -ItemId_Command_DeckDelDir = 1010, -ItemId_Command_DeckDel = 1011, -ItemId_Command_DeckDownload = 1012, -ItemId_Command_ListRooms = 1013, -ItemId_Command_JoinRoom = 1014, -ItemId_Command_LeaveRoom = 1015, -ItemId_Command_RoomSay = 1016, -ItemId_Command_JoinGame = 1017, -ItemId_Command_KickFromGame = 1018, -ItemId_Command_LeaveGame = 1019, -ItemId_Command_Say = 1020, -ItemId_Command_Shuffle = 1021, -ItemId_Command_Mulligan = 1022, -ItemId_Command_RollDie = 1023, -ItemId_Command_DrawCards = 1024, -ItemId_Command_UndoDraw = 1025, -ItemId_Command_FlipCard = 1026, -ItemId_Command_AttachCard = 1027, -ItemId_Command_CreateToken = 1028, -ItemId_Command_CreateArrow = 1029, -ItemId_Command_DeleteArrow = 1030, -ItemId_Command_SetCardAttr = 1031, -ItemId_Command_SetCardCounter = 1032, -ItemId_Command_IncCardCounter = 1033, -ItemId_Command_ReadyStart = 1034, -ItemId_Command_Concede = 1035, -ItemId_Command_IncCounter = 1036, -ItemId_Command_CreateCounter = 1037, -ItemId_Command_SetCounter = 1038, -ItemId_Command_DelCounter = 1039, -ItemId_Command_NextTurn = 1040, -ItemId_Command_SetActivePhase = 1041, -ItemId_Command_DumpZone = 1042, -ItemId_Command_StopDumpZone = 1043, -ItemId_Command_RevealCards = 1044, -ItemId_Event_ConnectionStateChanged = 1045, -ItemId_Event_Say = 1046, -ItemId_Event_Leave = 1047, -ItemId_Event_GameClosed = 1048, -ItemId_Event_Kicked = 1049, -ItemId_Event_Shuffle = 1050, -ItemId_Event_RollDie = 1051, -ItemId_Event_MoveCard = 1052, -ItemId_Event_FlipCard = 1053, -ItemId_Event_DestroyCard = 1054, -ItemId_Event_AttachCard = 1055, -ItemId_Event_CreateToken = 1056, -ItemId_Event_DeleteArrow = 1057, -ItemId_Event_SetCardAttr = 1058, -ItemId_Event_SetCardCounter = 1059, -ItemId_Event_SetCounter = 1060, -ItemId_Event_DelCounter = 1061, -ItemId_Event_SetActivePlayer = 1062, -ItemId_Event_SetActivePhase = 1063, -ItemId_Event_DumpZone = 1064, -ItemId_Event_StopDumpZone = 1065, -ItemId_Event_RemoveFromList = 1066, -ItemId_Event_ServerMessage = 1067, -ItemId_Event_ServerShutdown = 1068, -ItemId_Event_ConnectionClosed = 1069, -ItemId_Event_Message = 1070, -ItemId_Event_GameJoined = 1071, -ItemId_Event_UserLeft = 1072, -ItemId_Event_LeaveRoom = 1073, -ItemId_Event_RoomSay = 1074, -ItemId_Context_ReadyStart = 1075, -ItemId_Context_Concede = 1076, -ItemId_Context_DeckSelect = 1077, -ItemId_Context_UndoDraw = 1078, -ItemId_Context_MoveCard = 1079, -ItemId_Context_Mulligan = 1080, -ItemId_Command_UpdateServerMessage = 1081, -ItemId_Command_ShutdownServer = 1082, -ItemId_Command_BanFromServer = 1083, -ItemId_Other = 1084 +ItemId_Command_GetGamesOfUser = 1005, +ItemId_Command_GetUserInfo = 1006, +ItemId_Command_AddToList = 1007, +ItemId_Command_RemoveFromList = 1008, +ItemId_Command_DeckList = 1009, +ItemId_Command_DeckNewDir = 1010, +ItemId_Command_DeckDelDir = 1011, +ItemId_Command_DeckDel = 1012, +ItemId_Command_DeckDownload = 1013, +ItemId_Command_ListRooms = 1014, +ItemId_Command_JoinRoom = 1015, +ItemId_Command_LeaveRoom = 1016, +ItemId_Command_RoomSay = 1017, +ItemId_Command_JoinGame = 1018, +ItemId_Command_KickFromGame = 1019, +ItemId_Command_LeaveGame = 1020, +ItemId_Command_Say = 1021, +ItemId_Command_Shuffle = 1022, +ItemId_Command_Mulligan = 1023, +ItemId_Command_RollDie = 1024, +ItemId_Command_DrawCards = 1025, +ItemId_Command_UndoDraw = 1026, +ItemId_Command_FlipCard = 1027, +ItemId_Command_AttachCard = 1028, +ItemId_Command_CreateToken = 1029, +ItemId_Command_CreateArrow = 1030, +ItemId_Command_DeleteArrow = 1031, +ItemId_Command_SetCardAttr = 1032, +ItemId_Command_SetCardCounter = 1033, +ItemId_Command_IncCardCounter = 1034, +ItemId_Command_ReadyStart = 1035, +ItemId_Command_Concede = 1036, +ItemId_Command_IncCounter = 1037, +ItemId_Command_CreateCounter = 1038, +ItemId_Command_SetCounter = 1039, +ItemId_Command_DelCounter = 1040, +ItemId_Command_NextTurn = 1041, +ItemId_Command_SetActivePhase = 1042, +ItemId_Command_DumpZone = 1043, +ItemId_Command_StopDumpZone = 1044, +ItemId_Command_RevealCards = 1045, +ItemId_Event_ConnectionStateChanged = 1046, +ItemId_Event_Say = 1047, +ItemId_Event_Leave = 1048, +ItemId_Event_GameClosed = 1049, +ItemId_Event_Kicked = 1050, +ItemId_Event_Shuffle = 1051, +ItemId_Event_RollDie = 1052, +ItemId_Event_MoveCard = 1053, +ItemId_Event_FlipCard = 1054, +ItemId_Event_DestroyCard = 1055, +ItemId_Event_AttachCard = 1056, +ItemId_Event_CreateToken = 1057, +ItemId_Event_DeleteArrow = 1058, +ItemId_Event_SetCardAttr = 1059, +ItemId_Event_SetCardCounter = 1060, +ItemId_Event_SetCounter = 1061, +ItemId_Event_DelCounter = 1062, +ItemId_Event_SetActivePlayer = 1063, +ItemId_Event_SetActivePhase = 1064, +ItemId_Event_DumpZone = 1065, +ItemId_Event_StopDumpZone = 1066, +ItemId_Event_RemoveFromList = 1067, +ItemId_Event_ServerMessage = 1068, +ItemId_Event_ServerShutdown = 1069, +ItemId_Event_ConnectionClosed = 1070, +ItemId_Event_Message = 1071, +ItemId_Event_GameJoined = 1072, +ItemId_Event_UserLeft = 1073, +ItemId_Event_LeaveRoom = 1074, +ItemId_Event_RoomSay = 1075, +ItemId_Context_ReadyStart = 1076, +ItemId_Context_Concede = 1077, +ItemId_Context_DeckSelect = 1078, +ItemId_Context_UndoDraw = 1079, +ItemId_Context_MoveCard = 1080, +ItemId_Context_Mulligan = 1081, +ItemId_Command_UpdateServerMessage = 1082, +ItemId_Command_ShutdownServer = 1083, +ItemId_Command_BanFromServer = 1084, +ItemId_Other = 1085 }; diff --git a/common/protocol_items.cpp b/common/protocol_items.cpp index 33670ef43..db7ffc1a2 100644 --- a/common/protocol_items.cpp +++ b/common/protocol_items.cpp @@ -21,6 +21,11 @@ Command_ListUsers::Command_ListUsers() : Command("list_users") { } +Command_GetGamesOfUser::Command_GetGamesOfUser(const QString &_userName) + : Command("get_games_of_user") +{ + insertItem(new SerializableItem_String("user_name", _userName)); +} Command_GetUserInfo::Command_GetUserInfo(const QString &_userName) : Command("get_user_info") { @@ -497,6 +502,7 @@ void ProtocolItem::initializeHashAuto() itemNameHash.insert("cmdlogin", Command_Login::newItem); itemNameHash.insert("cmdmessage", Command_Message::newItem); itemNameHash.insert("cmdlist_users", Command_ListUsers::newItem); + itemNameHash.insert("cmdget_games_of_user", Command_GetGamesOfUser::newItem); itemNameHash.insert("cmdget_user_info", Command_GetUserInfo::newItem); itemNameHash.insert("cmdadd_to_list", Command_AddToList::newItem); itemNameHash.insert("cmdremove_from_list", Command_RemoveFromList::newItem); diff --git a/common/protocol_items.dat b/common/protocol_items.dat index 2e0f86031..716959329 100644 --- a/common/protocol_items.dat +++ b/common/protocol_items.dat @@ -2,6 +2,7 @@ 0:login:s,username:s,password 0:message:s,user_name:s,text 0:list_users +0:get_games_of_user:s,user_name 0:get_user_info:s,user_name 0:add_to_list:s,list:s,user_name 0:remove_from_list:s,list:s,user_name diff --git a/common/protocol_items.h b/common/protocol_items.h index efeb7f932..48401ee3b 100644 --- a/common/protocol_items.h +++ b/common/protocol_items.h @@ -35,6 +35,14 @@ public: static SerializableItem *newItem() { return new Command_ListUsers; } int getItemId() const { return ItemId_Command_ListUsers; } }; +class Command_GetGamesOfUser : public Command { + Q_OBJECT +public: + Command_GetGamesOfUser(const QString &_userName = QString()); + QString getUserName() const { return static_cast(itemMap.value("user_name"))->getData(); }; + static SerializableItem *newItem() { return new Command_GetGamesOfUser; } + int getItemId() const { return ItemId_Command_GetGamesOfUser; } +}; class Command_GetUserInfo : public Command { Q_OBJECT public: diff --git a/common/server_game.cpp b/common/server_game.cpp index 85b3a1512..bc14c7e96 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -214,6 +214,17 @@ ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_passw return RespOk; } +bool Server_Game::containsUser(const QString &userName) const +{ + QMutexLocker locker(&gameMutex); + + QMapIterator playerIterator(players); + while (playerIterator.hasNext()) + if (playerIterator.next().value()->getUserInfo()->getName() == userName) + return true; + return false; +} + Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spectator, bool broadcastUpdate) { QMutexLocker locker(&gameMutex); @@ -479,7 +490,7 @@ ServerInfo_Game *Server_Game::getInfo() const if (players.isEmpty()) // Game is closing - return new ServerInfo_Game(getGameId(), QString(), false, 0, getMaxPlayers(), QList(), 0, false, 0); + return new ServerInfo_Game(room->getId(), getGameId(), QString(), false, 0, getMaxPlayers(), QList(), 0, false, 0); else { // Game is open @@ -488,6 +499,7 @@ ServerInfo_Game *Server_Game::getInfo() const gameTypeList.append(new GameTypeId(gameTypes[i])); return new ServerInfo_Game( + room->getId(), getGameId(), getDescription(), !getPassword().isEmpty(), diff --git a/common/server_game.h b/common/server_game.h index b34301d47..f3d761f3e 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -77,6 +77,7 @@ public: bool getSpectatorsCanTalk() const { return spectatorsCanTalk; } bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; } ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator); + bool containsUser(const QString &userName) const; Server_Player *addPlayer(Server_ProtocolHandler *handler, bool spectator, bool broadcastUpdate = true); void removePlayer(Server_Player *player); void removeArrowsToPlayer(Server_Player *player); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index d1df01775..8236cf6e7 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -179,6 +179,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm case ItemId_Command_DeckDel: return cmdDeckDel(static_cast(command), cont); case ItemId_Command_DeckUpload: return cmdDeckUpload(static_cast(command), cont); case ItemId_Command_DeckDownload: return cmdDeckDownload(static_cast(command), cont); + case ItemId_Command_GetGamesOfUser: return cmdGetGamesOfUser(static_cast(command), cont); case ItemId_Command_GetUserInfo: return cmdGetUserInfo(static_cast(command), cont); case ItemId_Command_ListRooms: return cmdListRooms(static_cast(command), cont); case ItemId_Command_JoinRoom: return cmdJoinRoom(static_cast(command), cont); @@ -330,6 +331,28 @@ ResponseCode Server_ProtocolHandler::cmdMessage(Command_Message *cmd, CommandCon return RespOk; } +ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(Command_GetGamesOfUser *cmd, CommandContainer *cont) +{ + if (authState == PasswordWrong) + return RespLoginNeeded; + + server->serverMutex.lock(); + if (!server->getUsers().contains(cmd->getUserName())) + return RespNameNotFound; + + QList gameList; + QMapIterator roomIterator(server->getRooms()); + while (roomIterator.hasNext()) + gameList.append(roomIterator.next().value()->getGamesOfUser(cmd->getUserName())); + server->serverMutex.unlock(); + + ProtocolResponse *resp = new Response_GetGamesOfUser(cont->getCmdId(), RespOk, gameList); + if (getCompressionSupport()) + resp->setCompressed(true); + cont->setResponse(resp); + return RespNothing; +} + ResponseCode Server_ProtocolHandler::cmdGetUserInfo(Command_GetUserInfo *cmd, CommandContainer *cont) { if (authState == PasswordWrong) diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index a73c30080..1902f1d80 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -50,6 +50,7 @@ private: virtual ResponseCode cmdDeckDel(Command_DeckDel *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckUpload(Command_DeckUpload *cmd, CommandContainer *cont) = 0; virtual ResponseCode cmdDeckDownload(Command_DeckDownload *cmd, CommandContainer *cont) = 0; + ResponseCode cmdGetGamesOfUser(Command_GetGamesOfUser *cmd, CommandContainer *cont); ResponseCode cmdGetUserInfo(Command_GetUserInfo *cmd, CommandContainer *cont); ResponseCode cmdListRooms(Command_ListRooms *cmd, CommandContainer *cont); ResponseCode cmdJoinRoom(Command_JoinRoom *cmd, CommandContainer *cont); diff --git a/common/server_room.cpp b/common/server_room.cpp index b954fa81c..77030bff2 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -130,3 +130,17 @@ int Server_Room::getGamesCreatedByUser(const QString &userName) const ++result; return result; } + +QList Server_Room::getGamesOfUser(const QString &userName) const +{ + QMutexLocker locker(&roomMutex); + + QList result; + QMapIterator gamesIterator(games); + while (gamesIterator.hasNext()) { + Server_Game *game = gamesIterator.next().value(); + if (game->containsUser(userName)) + result.append(game->getInfo()); + } + return result; +} diff --git a/common/server_room.h b/common/server_room.h index b99b626f2..96712ac62 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -11,6 +11,7 @@ class Server_ProtocolHandler; class RoomEvent; class ServerInfo_User; class ServerInfo_Room; +class ServerInfo_Game; class Server_Game; class Server; @@ -39,6 +40,7 @@ public: Server *getServer() const; ServerInfo_Room *getInfo(bool complete) const; int getGamesCreatedByUser(const QString &name) const; + QList getGamesOfUser(const QString &name) const; void addClient(Server_ProtocolHandler *client); void removeClient(Server_ProtocolHandler *client); From abd5425796173d0ea554e60f15044569dea3831c Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 2 Jul 2011 16:43:19 +0200 Subject: [PATCH 72/87] finished getGamesOfUser function --- cockatrice/cockatrice.pro | 3 + cockatrice/src/gamesmodel.cpp | 41 +++-- cockatrice/src/gamesmodel.h | 8 +- cockatrice/src/tab_room.cpp | 116 +----------- cockatrice/src/tab_room.h | 32 +--- cockatrice/src/userlist.cpp | 33 +++- cockatrice/src/userlist.h | 2 + cockatrice/translations/cockatrice_cs.ts | 189 +++++++++++--------- cockatrice/translations/cockatrice_de.ts | 173 ++++++++++-------- cockatrice/translations/cockatrice_en.ts | 189 +++++++++++--------- cockatrice/translations/cockatrice_es.ts | 173 ++++++++++-------- cockatrice/translations/cockatrice_fr.ts | 175 ++++++++++-------- cockatrice/translations/cockatrice_ja.ts | 173 ++++++++++-------- cockatrice/translations/cockatrice_pl.ts | 189 +++++++++++--------- cockatrice/translations/cockatrice_pt-br.ts | 173 ++++++++++-------- cockatrice/translations/cockatrice_pt.ts | 175 ++++++++++-------- cockatrice/translations/cockatrice_ru.ts | 175 ++++++++++-------- cockatrice/translations/cockatrice_sk.ts | 189 +++++++++++--------- common/protocol.cpp | 25 ++- common/protocol.h | 10 +- common/protocol_datastructures.h | 3 +- common/server_protocolhandler.cpp | 16 +- common/server_room.cpp | 8 +- common/server_room.h | 2 +- 24 files changed, 1221 insertions(+), 1051 deletions(-) diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index b126f14a0..5902e4184 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -28,6 +28,8 @@ HEADERS += src/abstractcounter.h \ src/handcounter.h \ src/carddatabase.h \ src/gameview.h \ + src/gameselector.h \ + src/gametypemap.h \ src/decklistmodel.h \ src/dlg_load_deck_from_clipboard.h \ src/dlg_load_remote_deck.h \ @@ -114,6 +116,7 @@ SOURCES += src/abstractcounter.cpp \ src/handcounter.cpp \ src/carddatabase.cpp \ src/gameview.cpp \ + src/gameselector.cpp \ src/decklistmodel.cpp \ src/dlg_load_deck_from_clipboard.cpp \ src/dlg_load_remote_deck.cpp \ diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 700877f2f..9aff702b5 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -1,8 +1,8 @@ #include "gamesmodel.h" #include "protocol_datastructures.h" -GamesModel::GamesModel(const QMap &_gameTypes, QObject *parent) - : QAbstractTableModel(parent), gameTypes(_gameTypes) +GamesModel::GamesModel(const QMap &_rooms, const QMap &_gameTypes, QObject *parent) + : QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes) { } @@ -30,17 +30,19 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const ServerInfo_Game *g = gameList[index.row()]; switch (index.column()) { - case 0: return g->getDescription(); - case 1: return g->getCreatorInfo()->getName(); - case 2: { + case 0: return rooms.value(g->getRoomId()); + case 1: return g->getDescription(); + case 2: return g->getCreatorInfo()->getName(); + case 3: { QStringList result; QList gameTypeList = g->getGameTypes(); + GameTypeMap gameTypeMap = gameTypes.value(g->getRoomId()); for (int i = 0; i < gameTypeList.size(); ++i) - result.append(gameTypes.value(gameTypeList[i]->getData())); + result.append(gameTypeMap.value(gameTypeList[i]->getData())); return result.join(", "); } - case 3: return g->getHasPassword() ? (g->getSpectatorsNeedPassword() ? tr("yes") : tr("yes, free for spectators")) : tr("no"); - case 4: { + case 4: return g->getHasPassword() ? (g->getSpectatorsNeedPassword() ? tr("yes") : tr("yes, free for spectators")) : tr("no"); + case 5: { QStringList result; if (g->getOnlyBuddies()) result.append(tr("buddies only")); @@ -48,8 +50,8 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const result.append(tr("reg. users only")); return result.join(", "); } - case 5: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers()); - case 6: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorCount()) : QVariant(tr("not allowed")); + case 6: return QString("%1/%2").arg(g->getPlayerCount()).arg(g->getMaxPlayers()); + case 7: return g->getSpectatorsAllowed() ? QVariant(g->getSpectatorCount()) : QVariant(tr("not allowed")); default: return QVariant(); } } @@ -59,13 +61,14 @@ QVariant GamesModel::headerData(int section, Qt::Orientation orientation, int ro if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal)) return QVariant(); switch (section) { - case 0: return tr("Description"); - case 1: return tr("Creator"); - case 2: return tr("Game type"); - case 3: return tr("Password"); - case 4: return tr("Restrictions"); - case 5: return tr("Players"); - case 6: return tr("Spectators"); + case 0: return tr("Room"); + case 1: return tr("Description"); + case 2: return tr("Creator"); + case 3: return tr("Game type"); + case 4: return tr("Password"); + case 5: return tr("Restrictions"); + case 6: return tr("Players"); + case 7: return tr("Spectators"); default: return QVariant(); } } @@ -82,7 +85,7 @@ void GamesModel::updateGameList(ServerInfo_Game *_game) for (int i = 0; i < oldGameTypeList.size(); ++i) gameTypeList.append(new GameTypeId(oldGameTypeList[i]->getData())); - ServerInfo_Game *game = new ServerInfo_Game(_game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getOnlyBuddies(), _game->getOnlyRegistered(), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount()); + ServerInfo_Game *game = new ServerInfo_Game(_game->getRoomId(), _game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getOnlyBuddies(), _game->getOnlyRegistered(), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount()); for (int i = 0; i < gameList.size(); i++) if (gameList[i]->getGameId() == game->getGameId()) { if (game->getPlayerCount() == 0) { @@ -92,7 +95,7 @@ void GamesModel::updateGameList(ServerInfo_Game *_game) } else { delete gameList[i]; gameList[i] = game; - emit dataChanged(index(i, 0), index(i, 4)); + emit dataChanged(index(i, 0), index(i, 7)); } return; } diff --git a/cockatrice/src/gamesmodel.h b/cockatrice/src/gamesmodel.h index a7f4fe68d..6be0d1406 100644 --- a/cockatrice/src/gamesmodel.h +++ b/cockatrice/src/gamesmodel.h @@ -4,6 +4,7 @@ #include #include #include +#include "gametypemap.h" class ServerInfo_Game; @@ -11,12 +12,13 @@ class GamesModel : public QAbstractTableModel { Q_OBJECT private: QList gameList; - QMap gameTypes; + QMap rooms; + QMap gameTypes; public: - GamesModel(const QMap &_gameTypes, QObject *parent = 0); + GamesModel(const QMap &_rooms, const QMap &_gameTypes, QObject *parent = 0); ~GamesModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const { return parent.isValid() ? 0 : gameList.size(); } - int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 7; } + int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 8; } QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; diff --git a/cockatrice/src/tab_room.cpp b/cockatrice/src/tab_room.cpp index b1d23c93f..7fbce5a7a 100644 --- a/cockatrice/src/tab_room.cpp +++ b/cockatrice/src/tab_room.cpp @@ -4,127 +4,17 @@ #include #include #include -#include #include #include -#include #include #include -#include "dlg_creategame.h" #include "tab_supervisor.h" #include "tab_room.h" #include "userlist.h" #include "abstractclient.h" #include "protocol_items.h" -#include "gamesmodel.h" #include "chatview.h" - -GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, QWidget *parent) - : QGroupBox(parent), client(_client), room(_room) -{ - gameListView = new QTreeView; - gameListModel = new GamesModel(room->getGameTypes(), this); - gameListProxyModel = new GamesProxyModel(this); - gameListProxyModel->setSourceModel(gameListModel); - gameListProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - gameListView->setModel(gameListProxyModel); - gameListView->header()->setResizeMode(0, QHeaderView::ResizeToContents); - gameListView->setSortingEnabled(true); - - showFullGamesCheckBox = new QCheckBox; - createButton = new QPushButton; - joinButton = new QPushButton; - spectateButton = new QPushButton; - QHBoxLayout *buttonLayout = new QHBoxLayout; - buttonLayout->addWidget(showFullGamesCheckBox); - buttonLayout->addStretch(); - buttonLayout->addWidget(createButton); - buttonLayout->addWidget(joinButton); - buttonLayout->addWidget(spectateButton); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(gameListView); - mainLayout->addLayout(buttonLayout); - - retranslateUi(); - setLayout(mainLayout); - - setMinimumWidth((qreal) (gameListView->columnWidth(0) * gameListModel->columnCount()) / 1.5); - setMinimumHeight(200); - - connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int))); - connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); - connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); - connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); -} - -void GameSelector::showFullGamesChanged(int state) -{ - gameListProxyModel->setFullGamesVisible(state); -} - -void GameSelector::actCreate() -{ - DlgCreateGame dlg(client, room->getRoomId(), room->getGameTypes(), this); - dlg.exec(); -} - -void GameSelector::checkResponse(ResponseCode response) -{ - createButton->setEnabled(true); - joinButton->setEnabled(true); - spectateButton->setEnabled(true); - - switch (response) { - case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Wrong password.")); break; - case RespSpectatorsNotAllowed: QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game.")); break; - case RespGameFull: QMessageBox::critical(this, tr("Error"), tr("The game is already full.")); break; - case RespNameNotFound: QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more.")); break; - case RespUserLevelTooLow: QMessageBox::critical(this, tr("Error"), tr("This game is only open to registered users.")); break; - case RespOnlyBuddies: QMessageBox::critical(this, tr("Error"), tr("This game is only open to its creator's buddies.")); break; - case RespInIgnoreList: QMessageBox::critical(this, tr("Error"), tr("You are being ignored by the creator of this game.")); break; - default: ; - } -} - -void GameSelector::actJoin() -{ - bool spectator = sender() == spectateButton; - - QModelIndex ind = gameListView->currentIndex(); - if (!ind.isValid()) - return; - ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt()); - QString password; - if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) { - bool ok; - password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok); - if (!ok) - return; - } - - Command_JoinGame *commandJoinGame = new Command_JoinGame(room->getRoomId(), game->getGameId(), password, spectator); - connect(commandJoinGame, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode))); - client->sendCommand(commandJoinGame); - - createButton->setEnabled(false); - joinButton->setEnabled(false); - spectateButton->setEnabled(false); -} - -void GameSelector::retranslateUi() -{ - setTitle(tr("Games")); - showFullGamesCheckBox->setText(tr("Show &full games")); - createButton->setText(tr("C&reate")); - joinButton->setText(tr("&Join")); - spectateButton->setText(tr("J&oin as spectator")); -} - -void GameSelector::processGameInfo(ServerInfo_Game *info) -{ - gameListModel->updateGameList(info); -} +#include "gameselector.h" TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const QString &_ownName, ServerInfo_Room *info) : Tab(_tabSupervisor), client(_client), roomId(info->getRoomId()), roomName(info->getName()), ownName(_ownName) @@ -133,7 +23,9 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q for (int i = 0; i < gameTypeList.size(); ++i) gameTypes.insert(gameTypeList[i]->getGameTypeId(), gameTypeList[i]->getDescription()); - gameSelector = new GameSelector(client, this); + QMap tempMap; + tempMap.insert(info->getRoomId(), gameTypes); + gameSelector = new GameSelector(client, this, QMap(), tempMap); userList = new UserList(tabSupervisor, client, UserList::RoomList); connect(userList, SIGNAL(openMessageDialog(const QString &, bool)), this, SIGNAL(openMessageDialog(const QString &, bool))); diff --git a/cockatrice/src/tab_room.h b/cockatrice/src/tab_room.h index 9c19542f3..37e6a3d14 100644 --- a/cockatrice/src/tab_room.h +++ b/cockatrice/src/tab_room.h @@ -2,20 +2,16 @@ #define TAB_ROOM_H #include "tab.h" -#include "protocol_datastructures.h" #include +#include class AbstractClient; class UserList; class QLabel; class ChatView; class QLineEdit; -class QTreeView; class QPushButton; class QTextTable; -class QCheckBox; -class GamesModel; -class GamesProxyModel; class RoomEvent; class ServerInfo_Room; class ServerInfo_Game; @@ -24,31 +20,7 @@ class Event_JoinRoom; class Event_LeaveRoom; class Event_RoomSay; class ProtocolResponse; -class TabRoom; - -class GameSelector : public QGroupBox { - Q_OBJECT -private slots: - void showFullGamesChanged(int state); - void actCreate(); - void actJoin(); - void checkResponse(ResponseCode response); -signals: - void gameJoined(int gameId); -private: - AbstractClient *client; - TabRoom *room; - - QTreeView *gameListView; - GamesModel *gameListModel; - GamesProxyModel *gameListProxyModel; - QPushButton *createButton, *joinButton, *spectateButton; - QCheckBox *showFullGamesCheckBox; -public: - GameSelector(AbstractClient *_client, TabRoom *_room, QWidget *parent = 0); - void retranslateUi(); - void processGameInfo(ServerInfo_Game *info); -}; +class GameSelector; class TabRoom : public Tab { Q_OBJECT diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index 419d8b78c..20b60992d 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -5,6 +5,7 @@ #include "pixmapgenerator.h" #include "userinfobox.h" #include "protocol_items.h" +#include "gameselector.h" #include #include #include @@ -210,6 +211,35 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/) emit openMessageDialog(item->data(2, Qt::UserRole).toString(), true); } +void UserList::gamesOfUserReceived(ProtocolResponse *resp) +{ + Command_GetGamesOfUser *command = static_cast(sender()); + Response_GetGamesOfUser *response = qobject_cast(resp); + if (!response) + return; + + QMap gameTypeMap; + QMap roomMap; + const QList roomList = response->getRoomList(); + for (int i = 0; i < roomList.size(); ++i) { + roomMap.insert(roomList[i]->getRoomId(), roomList[i]->getName()); + const QList gameTypeList = roomList[i]->getGameTypeList(); + GameTypeMap tempMap; + for (int j = 0; j < gameTypeList.size(); ++j) + tempMap.insert(gameTypeList[j]->getGameTypeId(), gameTypeList[j]->getDescription()); + gameTypeMap.insert(roomList[i]->getRoomId(), tempMap); + } + + GameSelector *selector = new GameSelector(client, 0, roomMap, gameTypeMap); + const QList gameList = response->getGameList(); + for (int i = 0; i < gameList.size(); ++i) + selector->processGameInfo(gameList[i]); + + selector->setWindowTitle(tr("%1's games").arg(command->getUserName())); + selector->setAttribute(Qt::WA_DeleteOnClose); + selector->show(); +} + void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) { const QString &userName = index.sibling(index.row(), 2).data(Qt::UserRole).toString(); @@ -230,6 +260,7 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) menu->addAction(aUserName); menu->addSeparator(); menu->addAction(aDetails); + menu->addAction(aShowGames); menu->addAction(aChat); if ((userLevel & ServerInfo_User::IsRegistered) && (tabSupervisor->getUserLevel() & ServerInfo_User::IsRegistered)) { menu->addSeparator(); @@ -260,7 +291,7 @@ void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) client->sendCommand(new Command_RemoveFromList("buddy", userName)); else if (actionClicked == aShowGames) { Command *cmd = new Command_GetGamesOfUser(userName); - connect(cmd, SIGNAL(responseReceived(ProtocolResponse *)), this, SLOT(gamesOfUserReceived(ProtocolResponse *))); + connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(gamesOfUserReceived(ProtocolResponse *))); client->sendCommand(cmd); } else if (actionClicked == aAddToIgnoreList) client->sendCommand(new Command_AddToList("ignore", userName)); diff --git a/cockatrice/src/userlist.h b/cockatrice/src/userlist.h index a40fca0f9..c71ddc31e 100644 --- a/cockatrice/src/userlist.h +++ b/cockatrice/src/userlist.h @@ -12,6 +12,7 @@ class AbstractClient; class TabSupervisor; class QSpinBox; class QPlainTextEdit; +class ProtocolResponse; class BanDialog : public QDialog { Q_OBJECT @@ -52,6 +53,7 @@ private: void setUserOnline(QTreeWidgetItem *user, bool online); private slots: void userClicked(QTreeWidgetItem *item, int column); + void gamesOfUserReceived(ProtocolResponse *resp); signals: void openMessageDialog(const QString &userName, bool focus); void addBuddy(const QString &userName); diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index a3f47786d..0b328cc06 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -129,29 +129,29 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK - + &Cancel - + Ban user from server @@ -926,82 +926,82 @@ This is only saved for moderators and cannot be seen by the banned person. - + P&layers: - + Game type - + &Password: - + Only &buddies can join - + Only &registered users can join - + Joining restrictions - + &Spectators allowed - + Spectators &need a password to join - + Spectators can &chat - + Spectators see &everything - + Spectators - + &OK - + &Cancel - + Create game - + Error - + Server error. @@ -1203,83 +1203,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - + + + + + + + + Error - + + Please join the appropriate room first. + + + + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + C&reate - + &Join - + J&oin as spectator @@ -1295,67 +1301,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes - + yes, free for spectators - + no - + buddies only - + reg. users only - + not allowed - - - Description - - - - - Creator - - - Game type + Room - Password + Description - Restrictions + Creator - Players + Game type + Password + + + + + Restrictions + + + + + Players + + + + Spectators @@ -2581,7 +2592,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2606,27 +2617,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -3083,27 +3094,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3213,57 +3224,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + + %1's games + + + + User &details - + Direct &chat - + + Show this user's &games + + + + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 6ca4c1849..735b3c3be 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -164,7 +164,7 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. Bitte geben Sie die Dauer des Banns ein (in Minuten). @@ -175,24 +175,24 @@ Geben Sie 0 ein für einen unbefristeten Bann. Bitte geben Sie den Grund für den Bann ein. Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nicht gesehen werden. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. Bitte geben Sie den Grund für den Bann ein. Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nicht gesehen werden. - + &OK &OK - + &Cancel &Abbrechen - + Ban user from server Benutzer vom Server bannen @@ -1361,42 +1361,42 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Beschreibung: - + &Password: &Passwort: - + P&layers: &Spieler: - + Game type Spieltyp - + Only &buddies can join Nur &Freunde können teilnehmen - + Only &registered users can join Nur &registrierte Benutzer können teilnehmen - + Joining restrictions Teilnahmebedingungen - + &Spectators allowed &Zuschauer zugelassen - + Spectators &need a password to join Zuschauer brauchen &auch ein Passwort @@ -1405,37 +1405,37 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Zuschauer können sp&rechen - + Spectators can &chat Zuschauer können s&chreiben - + Spectators see &everything Zuschauer sehen &alles - + Spectators Zuschauer - + &OK &OK - + &Cancel &Abbruch - + Create game Spiel erstellen - + Error Fehler @@ -1444,7 +1444,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Ungültige Anzahl an Spielern. - + Server error. Serverfehler. @@ -1947,23 +1947,24 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic GameSelector - + C&reate Spiel e&rstellen - + &Join &Teilnehmen - - - - - - - + + + + + + + + Error Fehler @@ -1972,57 +1973,62 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic XXX - + + Please join the appropriate room first. + Bitte betreten Sie erst den entsprechenden Raum. + + + Wrong password. Falsches Passwort. - + Spectators are not allowed in this game. In diesem Spiel sind keine Zuschauer zugelassen. - + The game is already full. Das Spiel ist bereits voll. - + The game does not exist any more. Dieses Spiel gibt es nicht mehr. - + This game is only open to registered users. Dieses Spiel kann nur von registrierten Benutzern betreten werden. - + This game is only open to its creator's buddies. Dieses Spiel kann nur von Freunden des Erstellers betreten werden. - + You are being ignored by the creator of this game. Der Ersteller dieses Spiels ignoriert Sie. - + Join game Spiel beitreten - + Password: Passwort: - + Games Spiele - + Show &full games &Volle Spiele anzeigen @@ -2031,7 +2037,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Volle Spiele anzeigen - + J&oin as spectator &Zuschauen @@ -2047,12 +2053,12 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic GamesModel - + yes ja - + no nein @@ -2061,57 +2067,62 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Spiel ID - + Creator Ersteller - + Description Beschreibung - + yes, free for spectators ja, außer für Zuschauer - + buddies only nur Freunde - + reg. users only nur reg. Benutzer - + not allowed nicht erlaubt + Room + Raum + + + Game type Spieltyp - + Password Passwort - + Restrictions Bedingungen - + Players Spieler - + Spectators Zuschauer @@ -3843,7 +3854,7 @@ Lokale Version ist %1, Serverversion ist %2. - + Number: Anzahl: @@ -3858,27 +3869,27 @@ Lokale Version ist %1, Serverversion ist %2. Oberste Karten ins Exil schicken - + Set power/toughness Kampfwerte setzen - + Please enter the new PT: Bitte die neuen Kampfwerte eingeben: - + Set annotation Hinweis setzen - + Please enter the new annotation: Bitte den Hinweis eingeben: - + Set counters Setze Zählmarken @@ -4460,27 +4471,27 @@ Bitte geben Sie einen Namen ein: TabRoom - + &Say: &Sagen: - + Chat Unterhaltung - + &Room &Raum - + &Leave room Raum ver&lassen - + You are flooding the chat. Please wait a couple of seconds. Sie überfluten den Chatraum. Bitte warten Sie ein paar Sekunden. @@ -4617,57 +4628,67 @@ Bitte geben Sie einen Namen ein: UserList - + Users online: %1 Benutzer online: %1 - + Users in this room: %1 Benutzer in diesem Raum: %1 - + Buddies online: %1 / %2 Freunde online: %1 / %2 - + Ignored users online: %1 / %2 Ignorierte Benutzer online: %1 / %2 - + + %1's games + %1s Spiele + + + User &details Benutzer&details - + Direct &chat &Persönliches Gespräch - + + Show this user's &games + Spiele dieses &Benutzers anzeigen + + + Add to &buddy list Zur &Freundesliste hinzufügen - + Remove from &buddy list Von &Freundesliste entfernen - + Add to &ignore list &Ignorieren - + Remove from &ignore list Nicht mehr &ignorieren - + Ban from &server Vom &Server bannen diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 3fcd278e0..87989e2c9 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -129,29 +129,29 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK - + &Cancel - + Ban user from server @@ -926,82 +926,82 @@ This is only saved for moderators and cannot be seen by the banned person. - + &Password: - + P&layers: - + Game type - + Only &buddies can join - + Only &registered users can join - + Joining restrictions - + &Spectators allowed - + Spectators &need a password to join - + Spectators can &chat - + Spectators see &everything - + Spectators - + &OK - + &Cancel - + Create game - + Error - + Server error. @@ -1203,83 +1203,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate - + &Join - - - - - - - + + + + + + + + Error - + + Please join the appropriate room first. + + + + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + J&oin as spectator @@ -1295,67 +1301,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes - + no - + Creator - + Description - + yes, free for spectators - + buddies only - + reg. users only - + not allowed - Game type - - - - - Password - - - - - Restrictions + Room - Players + Game type + Password + + + + + Restrictions + + + + + Players + + + + Spectators @@ -2587,7 +2598,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2612,27 +2623,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -3089,27 +3100,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3219,57 +3230,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + + %1's games + + + + User &details - + Direct &chat - + + Show this user's &games + + + + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index e5e199b29..877347b7e 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -137,30 +137,30 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. Por favor, introduce la duración del ban (en minutos) Indica 0 para un ban indefinido. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK &Aceptar - + &Cancel &Cancelar - + Ban user from server @@ -1276,82 +1276,82 @@ This is only saved for moderators and cannot be seen by the banned person.&Descripción: - + &Password: &Contraseña: - + P&layers: &Jugadores: - + Game type Tipo de partida - + Only &buddies can join Sólo los &amigos pueden participar - + Only &registered users can join Sólo los usuarios &registrados pueden participar - + Joining restrictions Restricciones de participación - + &Spectators allowed Permitir e&spectadores - + Spectators &need a password to join Los espectadores &necesitan contraseña para unirse - + Spectators can &chat Los espectadores pueden &chatear - + Spectators see &everything Los espectadores pueden verlo &todo - + Spectators Espectadores - + &OK &Aceptar - + &Cancel &Cancelar - + Create game Crear partida - + Error Error - + Server error. Error del servidor. @@ -1565,78 +1565,84 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate C&rear - + &Join E&ntrar - - - - - - - + + + + + + + + Error Error - + + Please join the appropriate room first. + + + + Wrong password. Contraseña incorrecta. - + Spectators are not allowed in this game. No se permiten espectadores en esta partida. - + The game is already full. La partida no tiene plazas libres. - + The game does not exist any more. La partida ya no existe. - + This game is only open to registered users. Esta partida está abierta sólo a usuarios registrados. - + This game is only open to its creator's buddies. Esta partida está abierta sólo a los amigos del creador. - + You are being ignored by the creator of this game. Estas siendo ignorado por el creador de la partida. - + Join game Entrar en la partida - + Password: Contraseña: - + Games Partidas - + Show &full games Ver partidas &sin plazas libres @@ -1645,7 +1651,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Ver partidas sin plazas libres - + J&oin as spectator Entrar como e&spectador @@ -1661,67 +1667,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes - + no no - + Creator Creador - + Description Descripción - + yes, free for spectators sí, libre para espectadores - + buddies only solo amigos - + reg. users only solo usuarios registrados - + not allowed no permitido + Room + Sala + + + Game type Tipo de partida - + Password Contraseña - + Restrictions Restricciones - + Players Jugadores - + Spectators Espectadores @@ -2981,7 +2992,7 @@ La versión local es %1, la versión remota es %2. - + Number: Número: @@ -3006,27 +3017,27 @@ La versión local es %1, la versión remota es %2. Número de caras: - + Set power/toughness Establecer fuerza/resistencia - + Please enter the new PT: Por favor, introduzca la nueva F/R: - + Set annotation Escribir anotación - + Please enter the new annotation: Por favor, introduza la nueva anotación: - + Set counters Establecer contadores @@ -3538,27 +3549,27 @@ Por favor, introduzca un nombre: TabRoom - + &Say: &Decir: - + Chat Chat - + &Room &Sala - + &Leave room &Dejar sala - + You are flooding the chat. Please wait a couple of seconds. Estás floodeando el chat. Por favor, espera unos segundos. @@ -3680,57 +3691,67 @@ Por favor, introduzca un nombre: UserList - + Users online: %1 Usuarios online: %1 - + Users in this room: %1 Usuarios en esta sala: %1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Usuarios ignorados online: %1 / %2 - + + %1's games + + + + User &details &Detalles del usuario - + Direct &chat &Chat privado - + + Show this user's &games + + + + Add to &buddy list Añadir a la lista de &amigos - + Remove from &buddy list Quitar de la lista de &amigos - + Add to &ignore list Añadir a la lista de &ignorados - + Remove from &ignore list Quitar de la lista de &ignorados - + Ban from &server Banear del &servidor diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 1aec9f3c5..2df8edd40 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -129,30 +129,30 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. Entrez la durée de temps du ban (en minutes). Entrez 0 pour une durée illimitée du ban. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK &OK - + &Cancel &Annuler - + Ban user from server @@ -1138,82 +1138,82 @@ This is only saved for moderators and cannot be seen by the banned person.&Description: - + &Password: Mot de &Passe: - + P&layers: &Joueurs: - + Game type Type de partie - + Only &buddies can join Seuls les &amis peuvent rejoindre - + Only &registered users can join Seules les personnes en&registrées peuvent rejoindre - + Joining restrictions Conditions pour rejoindre - + &Spectators allowed &Spectateurs autorisés - + Spectators &need a password to join Les spectateurs ont besoin d'un &mot de passe pour rejoindre - + Spectators can &chat Les spectateurs peuvent dis&cuter - + Spectators see &everything Les spectateurs p&euvent tout voir - + Spectators Spectateurs - + &OK &OK - + &Cancel &Annuler - + Create game Créer partie - + Error Erreur - + Server error. Erreur serveur. @@ -1415,68 +1415,74 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - + + + + + + + + Error Erreur - + + Please join the appropriate room first. + + + + Wrong password. Mot de passe erroné. - + Spectators are not allowed in this game. Les spectateurs ne sont pas autorisés dans cette partie. - + The game is already full. Cette partie est déjà pleine. - + The game does not exist any more. La partie n'existe plus. - + This game is only open to registered users. Cette partie n'est accessible qu'aux joueurs enregistrés. - + This game is only open to its creator's buddies. Cette partie n'est accessible qu'aux amis. - + You are being ignored by the creator of this game. Vous avez été ignoré par le créateur de la partie. - + Join game Rejoindre partie - + Password: Mot de passe: - + Games Parties - + Show &full games Montrer &toutes les parties @@ -1486,17 +1492,17 @@ This is only saved for moderators and cannot be seen by the banned person.&Montrer toutes les parties - + C&reate C&réer - + &Join Re&joindre - + J&oin as spectator Rej&oindre en tant que spectateur @@ -1512,67 +1518,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes oui - + yes, free for spectators oui, libre pour les spectateurs - + no non - + buddies only invités uniquement - + reg. users only joueurs enregistrés uniquement - + not allowed non autorisé - + + Room + Salon + + + Description Description - + Creator Créateur - + Game type Type de jeu - + Password Mot de passe - + Restrictions Restrictions - + Players Joueurs - + Spectators Spectateurs @@ -2846,7 +2857,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + Number: Nombre: @@ -2871,28 +2882,28 @@ La version la plus récente est %1, l'ancienne version est %2.Nombre de faces: - + Set power/toughness Fixer force/endurance - + Please enter the new PT: maybe better with / Entrer la nouvelle F/E: - + Set annotation Mettre une note - + Please enter the new annotation: Entrez la nouvelle note: - + Set counters Mettre des marqueurs @@ -3398,27 +3409,27 @@ Entrez un nom s'il vous plaît: TabRoom - + &Say: &Dire: - + Chat Chat - + &Room &Salon - + &Leave room &Quitter le salon - + You are flooding the chat. Please wait a couple of seconds. Vous floodez le chat. Veuillez patienter quelques secondes. @@ -3541,57 +3552,67 @@ Entrez un nom s'il vous plaît: UserList - + Users online: %1 Utilisateurs en ligne:%1 - + Users in this room: %1 Utilisateurs dans ce salon: %1 - + Buddies online: %1 / %2 Amis connectés; %1 / %2 - + Ignored users online: %1 / %2 Personnes sur liste noire connectés: %1 / %2 - + + %1's games + + + + User &details &Détails utilisateur - + Direct &chat &Chat direct - + + Show this user's &games + + + + Add to &buddy list Ajouter à la liste d'&amis - + Remove from &buddy list Retirer de la liste d'&amis - + Add to &ignore list Ajouter à la liste &noire - + Remove from &ignore list Retirer de la liste &noire - + Ban from &server Bannir du &serveur diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index f6d1b9c07..c9f0a6e9a 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -134,29 +134,29 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. バンする期間を入力してください(分単位).0でバンを解除します. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK - + &Cancel - + Ban user from server @@ -974,82 +974,82 @@ This is only saved for moderators and cannot be seen by the banned person.説明: - + &Password: パスワード: - + P&layers: プレイヤー人数: - + Game type ゲームタイプ - + Only &buddies can join フレンドのみ参加可能 - + Only &registered users can join 登録済みプレイヤーのみ参加可能 - + Joining restrictions 参加制限 - + &Spectators allowed 観戦者を許可する - + Spectators &need a password to join 観戦者は参加にパスワードが必要 - + Spectators can &chat 観戦者はチャットに参加できる - + Spectators see &everything 観戦者は全て見れる - + Spectators 観戦者 - + &OK - + &Cancel - + Create game 部屋を作る - + Error エラー - + Server error. サーバーエラー. @@ -1251,78 +1251,84 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate 部屋を作る - + &Join 参加する - - - - - - - + + + + + + + + Error エラー - + + Please join the appropriate room first. + + + + Wrong password. パスワードが間違っています. - + Spectators are not allowed in this game. この試合は観戦者は許可されていません. - + The game is already full. このゲームはすでに満員です. - + The game does not exist any more. このゲームはもう存在しません. - + This game is only open to registered users. このゲームは登録済みプレイヤーにのみ公開されています. - + This game is only open to its creator's buddies. このゲームは作成者のフレンドのみに公開されています. - + You are being ignored by the creator of this game. あなたはこのゲームの作成者によって拒否されています. - + Join game 参加 - + Password: パスワード: - + Games ゲーム - + Show &full games 全てのゲームを見る @@ -1331,7 +1337,7 @@ This is only saved for moderators and cannot be seen by the banned person.全てのゲームを見る - + J&oin as spectator 観戦者として参加 @@ -1347,67 +1353,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes あり - + no なし - + Creator 作成者 - + Description 説明 - + yes, free for spectators あり,観戦は自由 - + buddies only フレンドのみ - + reg. users only 登録済みユーザーのみ - + not allowed 不許可 + Room + 部屋 + + + Game type ゲームタイプ - + Password パスワード - + Restrictions 制限 - + Players プレイヤー - + Spectators 観戦者 @@ -2634,7 +2645,7 @@ Local version is %1, remote version is %2. - + Number: 枚数 @@ -2659,27 +2670,27 @@ Local version is %1, remote version is %2. 面の数: - + Set power/toughness パワーとタフネスを設定する - + Please enter the new PT: 新しいP/Tを入力してください - + Set annotation 補足を付ける - + Please enter the new annotation: 新しい補足を付けてください - + Set counters カウンターを設定する @@ -3174,27 +3185,27 @@ Please enter a name: TabRoom - + &Say: 発言する - + Chat チャット - + &Room 部屋 - + &Leave room 部屋から出る - + You are flooding the chat. Please wait a couple of seconds. あなたはチャットルームから弾かれました.少々お待ちください. @@ -3316,57 +3327,67 @@ Please enter a name: UserList - + Users online: %1 ユーザー オンライン: %1 - + Users in this room: %1 部屋のユーザー数: %1 - + Buddies online: %1 / %2 フレンドオンライン: %1 / %2 - + Ignored users online: %1 / %2 無視ユーザーオンライン: %1 / %2 - + + %1's games + + + + User &details ユーザー補足 - + Direct &chat 個人チャット - + + Show this user's &games + + + + Add to &buddy list フレンドリストに追加 - + Remove from &buddy list フレンドリストから削除 - + Add to &ignore list 無視リストに追加 - + Remove from &ignore list 無視リストから削除 - + Ban from &server サーバーからバンする diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 07fd65103..492dbed27 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -129,29 +129,29 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK - + &Cancel - + Ban user from server @@ -926,82 +926,82 @@ This is only saved for moderators and cannot be seen by the banned person. - + P&layers: - + Game type - + &Password: - + Only &buddies can join - + Only &registered users can join - + Joining restrictions - + &Spectators allowed - + Spectators &need a password to join - + Spectators can &chat - + Spectators see &everything - + Spectators - + &OK - + &Cancel - + Create game - + Error - + Server error. @@ -1203,83 +1203,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - + + + + + + + + Error - + + Please join the appropriate room first. + + + + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + C&reate - + &Join - + J&oin as spectator @@ -1295,67 +1301,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes - + yes, free for spectators - + no - + buddies only - + reg. users only - + not allowed - - - Description - - - - - Creator - - - Game type + Room - Password + Description - Restrictions + Creator - Players + Game type + Password + + + + + Restrictions + + + + + Players + + + + Spectators @@ -2581,7 +2592,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2606,27 +2617,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -3083,27 +3094,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3213,57 +3224,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + + %1's games + + + + User &details - + Direct &chat - + + Show this user's &games + + + + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 478d43f94..0404d46d5 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -133,30 +133,30 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. Por favor, digite a duração do banimento (em minutos). Digite 0 para banir indefinidamente. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK &OK - + &Cancel &Cancelar - + Ban user from server @@ -1142,82 +1142,82 @@ This is only saved for moderators and cannot be seen by the banned person.&Descrição: - + &Password: S&enha: - + P&layers: &Jogadores: - + Game type Tipo de jogo - + Only &buddies can join Apenas ami&gos podem entrar - + Only &registered users can join Apenas usuários re&gistrados podem entrar - + Joining restrictions Restrições para entrar - + &Spectators allowed &Permitir visitantes - + Spectators &need a password to join Visitantes &precisam de senha para entrar - + Spectators can &chat Visitantes podem c&onversar - + Spectators see &everything Visitantes podem ver &tudo - + Spectators Visitantes - + &OK &OK - + &Cancel &Cancelar - + Create game Criar jogo - + Error Erro - + Server error. Erro do servidor. @@ -1419,78 +1419,84 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate &Criar - + &Join &Entrar - - - - - - - + + + + + + + + Error Erro - + + Please join the appropriate room first. + + + + Wrong password. Senha incorreta. - + Spectators are not allowed in this game. Não são permitidos visitantes neste jogo. - + The game is already full. O jogo está cheio. - + The game does not exist any more. O jogo não existe mais. - + This game is only open to registered users. Este jogo é aberto apenas para usuários registrados. - + This game is only open to its creator's buddies. Este jogo é aberto apenas para os amigos de quem criou o jogo. - + You are being ignored by the creator of this game. Você está sendo ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Senha: - + Games Jogos - + Show &full games &Mostrar os jogos cheios @@ -1499,7 +1505,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Mostrar os jogos cheios - + J&oin as spectator E&ntrar como visitante @@ -1515,67 +1521,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes sim - + no não - + Creator Criador - + Description Descrição - + yes, free for spectators sim, livre para visitantes - + buddies only apenas amigos - + reg. users only usuários reg. apenas - + not allowed não permitidos + Room + Sala + + + Game type Tipo de jogo - + Password Senha - + Restrictions Restrições - + Players Jogadores - + Spectators Visitantes @@ -2831,7 +2842,7 @@ A versão local é %1 e a versão remota é %2. - + Number: Número: @@ -2856,27 +2867,27 @@ A versão local é %1 e a versão remota é %2. Número de lados: - + Set power/toughness Alterar poder/resistência - + Please enter the new PT: Por favor, entre com o novo P/R: - + Set annotation Alterar nota - + Please enter the new annotation: Por favor, entre com a nova nota: - + Set counters Alterar marcadores @@ -3380,27 +3391,27 @@ Por favor, entre um nome: TabRoom - + &Say: &Falar: - + Chat Chat - + &Room &Sala - + &Leave room S&air da sala - + You are flooding the chat. Please wait a couple of seconds. Você está flodando o chat. Por favor, espere alguns segundos. @@ -3522,57 +3533,67 @@ Por favor, entre um nome: UserList - + Users online: %1 Usuários online: %1 - + Users in this room: %1 Usuários nesta sala: %1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Usuários ignorados online: %1 / %2 - + + %1's games + + + + User &details &Detalhes do usuário - + Direct &chat &Chat direto - + + Show this user's &games + + + + Add to &buddy list Adicionar à &lista de amigos - + Remove from &buddy list Remover da li&sta de amigos - + Add to &ignore list Adicionar à li&sta dos ignorados - + Remove from &ignore list Remover da lista dos i&gnorados - + Ban from &server Ban&ir do servidor diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 676094319..351b8b981 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -133,30 +133,30 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. Por favor introduza a duração do banimento (em minutos). Introduza 0 para um banimento indefinido. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK - + &Cancel &Cancelar - + Ban user from server @@ -1142,82 +1142,82 @@ This is only saved for moderators and cannot be seen by the banned person.&Descrição: - + &Password: &Password: - + P&layers: &Jogadores: - + Game type Tipo de jogo - + Only &buddies can join Apenas &amigos podem entrar - + Only &registered users can join Apenas utilizadores &registados podem entrar - + Joining restrictions Restrições para ligar - + &Spectators allowed &Espectadores permitidos - + Spectators &need a password to join Espectadores &necessitam de password para aceder - + Spectators can &chat Espectadores podem c&onversar - + Spectators see &everything Espectadores podem ver &tudo - + Spectators Espectadores - + &OK O&K - + &Cancel &Cancelar - + Create game Criar jogo - + Error Erro - + Server error. Erro do servidor. @@ -1419,68 +1419,74 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - + + + + + + + + Error Erro - + + Please join the appropriate room first. + + + + Wrong password. Password incorrecta. - + Spectators are not allowed in this game. Não são permitidos espectadores neste jogo. - + The game is already full. O jogo já se encontra cheio. - + The game does not exist any more. O jogo já não existe. - + This game is only open to registered users. Este jogo só está aberto a utilizadores registados. - + This game is only open to its creator's buddies. Este jogo só está aberto aos amigos do seu criador. - + You are being ignored by the creator of this game. Você está a ser ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Password: - + Games Jogos - + Show &full games &Mostrar jogos cheios @@ -1489,17 +1495,17 @@ This is only saved for moderators and cannot be seen by the banned person.&Mostrar jogos cheios - + C&reate &Criar - + &Join &Entrar - + J&oin as spectator Entrar como &espectador @@ -1515,67 +1521,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes sim - + yes, free for spectators sim, livre para espectadores - + no não - + buddies only amigos apenas - + reg. users only utilizadores registados apenas - + not allowed não permitidos - + + Room + Sala + + + Description Descrição - + Creator Criador - + Game type Tipo de jogo - + Password Password - + Restrictions Restrições - + Players Jogadores - + Spectators Espectadores @@ -2835,7 +2846,7 @@ Versão local é %1, versão remota é %2. - + Number: Número: @@ -2860,27 +2871,27 @@ Versão local é %1, versão remota é %2. Número de faces: - + Set power/toughness Definir poder/resistência - + Please enter the new PT: Por favor introduza o novo P/R: - + Set annotation Colocar nota - + Please enter the new annotation: Por favor introduza a nova nota: - + Set counters Definir marcadores @@ -3384,27 +3395,27 @@ Por favor introduza um nome: TabRoom - + &Say: &Dizer: - + Chat - + &Room &Sala - + &Leave room &Abandonar a sala - + You are flooding the chat. Please wait a couple of seconds. Estás a inundar o chat .Por favor aguarde alguns segundos. @@ -3526,57 +3537,67 @@ Por favor introduza um nome: UserList - + Users online: %1 Utilizadores online: %1 - + Users in this room: %1 Utilizadores nesta sala:%1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Utilizadores ignorados online %1 / %2 - + + %1's games + + + + User &details Detalhes do &utilizador - + Direct &chat Conversação &directa - + + Show this user's &games + + + + Add to &buddy list Adicionar a lista de &amigos - + Remove from &buddy list Remover da lista de &amigos - + Add to &ignore list Adicionar a lista a &ignorar - + Remove from &ignore list Remover da lista a &ignorar - + Ban from &server Banir do &servidor diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index af264167f..8f875c2a9 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -129,30 +129,30 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. Введите продолжительность бана (в минутах). Введите 0 чтобы забанить пожизненно. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK &Ок - + &Cancel &Отмена - + Ban user from server @@ -1081,82 +1081,82 @@ This is only saved for moderators and cannot be seen by the banned person.&Подпись: - + &Password: &Пароль: - + P&layers: &Количество игроков: - + Game type Формат игры - + Only &buddies can join Только для &своих - + Only &registered users can join Только для &зарег. пользователей - + Joining restrictions Ограничения - + &Spectators allowed &Разрешить зрителей - + Spectators &need a password to join Требовать &пароль у зрителей - + Spectators can &chat Позволить зрителям &комментировать - + Spectators see &everything Показывать зрителям &все - + Spectators Зрители - + &OK &Ок - + &Cancel &Отмена - + Create game Создать игру - + Error Ошибка - + Server error. Ошибка сервера. @@ -1358,83 +1358,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - + + + + + + + + Error Ошибка - + + Please join the appropriate room first. + + + + Wrong password. Неверный пароль. - + Spectators are not allowed in this game. В эту игру не пускают зрителей. - + The game is already full. Все места заняты! =Ь - + The game does not exist any more. Эта игра была удалена. - + This game is only open to registered users. Доступно только для зарегистрированных. - + This game is only open to its creator's buddies. Доступно только для друзей. - + You are being ignored by the creator of this game. Вы добавлены в игнор-лист данного игрока. - + Join game Присоединиться - + Password: Пароль: - + Games Игры - + Show &full games Показывать &текущие - + C&reate С&оздать - + &Join &Присоединиться - + J&oin as spectator П&рисоединиться как зритель @@ -1450,67 +1456,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes да - + yes, free for spectators да, свободно для зрителей - + no нет - + buddies only только свои - + reg. users only только зарег. - + not allowed Не допускаются - + + Room + Комната + + + Description Подпись - + Creator Создал - + Game type Формат игры - + Password Пароль - + Restrictions Ограничения - + Players Количество игроков - + Spectators Зрители @@ -2768,7 +2779,7 @@ Local version is %1, remote version is %2. - + Number: Количество: @@ -2793,27 +2804,27 @@ Local version is %1, remote version is %2. Количество граней: - + Set power/toughness Установить Силу/Защиту - + Please enter the new PT: Введите новые Силу/Защиту: - + Set annotation Пометка - + Please enter the new annotation: Введите текст: - + Set counters Установить жетоны @@ -3283,27 +3294,27 @@ Please enter a name: TabRoom - + &Say: &Сказать: - + Chat Чат - + &Room &Комната - + &Leave room &Покинуть комнату - + You are flooding the chat. Please wait a couple of seconds. Кажется, Вы нафлудили. Пожалуйста, подождите пару секунд. @@ -3417,57 +3428,67 @@ Please enter a name: UserList - + Users online: %1 Пользователей онлайн: %1 - + Users in this room: %1 Пользователей в этой комнате: %1 - + Buddies online: %1 / %2 Друзей онлайн: %1 / %2 - + Ignored users online: %1 / %2 Игнорируемых пользователей онлайн: %1 / %2 - + + %1's games + + + + User &details Данные о &пользователе - + Direct &chat Обратиться &лично - + + Show this user's &games + + + + Add to &buddy list Добавить в список &друзей - + Remove from &buddy list &Удалить из друзей - + Add to &ignore list Добавить в &игнор-лист - + Remove from &ignore list Удалить и&з игнор-листа - + Ban from &server За&банить на сервере diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 63a3c8409..dddb74650 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -129,29 +129,29 @@ BanDialog - + Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - + Please enter the reason for the ban. This is only saved for moderators and cannot be seen by the banned person. - + &OK - + &Cancel - + Ban user from server @@ -926,82 +926,82 @@ This is only saved for moderators and cannot be seen by the banned person. - + P&layers: - + Game type - + &Password: - + Only &buddies can join - + Only &registered users can join - + Joining restrictions - + &Spectators allowed - + Spectators &need a password to join - + Spectators can &chat - + Spectators see &everything - + Spectators - + &OK - + &Cancel - + Create game - + Error - + Server error. @@ -1203,83 +1203,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - + + + + + + + + Error - + + Please join the appropriate room first. + + + + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + C&reate - + &Join - + J&oin as spectator @@ -1295,67 +1301,72 @@ This is only saved for moderators and cannot be seen by the banned person. GamesModel - + yes - + yes, free for spectators - + no - + buddies only - + reg. users only - + not allowed - - - Description - - - - - Creator - - - Game type + Room - Password + Description - Restrictions + Creator - Players + Game type + Password + + + + + Restrictions + + + + + Players + + + + Spectators @@ -2581,7 +2592,7 @@ Local version is %1, remote version is %2. - + Number: @@ -2606,27 +2617,27 @@ Local version is %1, remote version is %2. - + Set power/toughness - + Please enter the new PT: - + Set annotation - + Please enter the new annotation: - + Set counters @@ -3083,27 +3094,27 @@ Please enter a name: TabRoom - + &Say: - + Chat - + &Room - + &Leave room - + You are flooding the chat. Please wait a couple of seconds. @@ -3213,57 +3224,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + + %1's games + + + + User &details - + Direct &chat - + + Show this user's &games + + + + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/common/protocol.cpp b/common/protocol.cpp index 205f2b2a4..85c581d0f 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -257,6 +257,7 @@ void ProtocolResponse::initializeHash() { responseHash.insert(QString(), RespNothing); responseHash.insert("ok", RespOk); + responseHash.insert("not_in_room", RespNotInRoom); responseHash.insert("internal_error", RespInternalError); responseHash.insert("invalid_command", RespInvalidCommand); responseHash.insert("name_not_found", RespNameNotFound); @@ -297,12 +298,34 @@ Response_DeckList::Response_DeckList(int _cmdId, ResponseCode _responseCode, Dec insertItem(_root); } -Response_GetGamesOfUser::Response_GetGamesOfUser(int _cmdId, ResponseCode _responseCode, const QList &_gameList) +Response_GetGamesOfUser::Response_GetGamesOfUser(int _cmdId, ResponseCode _responseCode, const QList &_roomList, const QList &_gameList) + : ProtocolResponse(_cmdId, _responseCode, "get_games_of_user") { + roomList = _roomList; + for (int i = 0; i < _roomList.size(); ++i) + itemList.append(_roomList[i]); + + gameList = _gameList; for (int i = 0; i < _gameList.size(); ++i) itemList.append(_gameList[i]); } +void Response_GetGamesOfUser::extractData() +{ + for (int i = 0; i < itemList.size(); ++i) { + ServerInfo_Room *room = dynamic_cast(itemList[i]); + if (room) { + roomList.append(room); + continue; + } + ServerInfo_Game *game = dynamic_cast(itemList[i]); + if (game) { + gameList.append(game); + continue; + } + } +} + Response_GetUserInfo::Response_GetUserInfo(int _cmdId, ResponseCode _responseCode, ServerInfo_User *_user) : ProtocolResponse(_cmdId, _responseCode, "get_user_info") { diff --git a/common/protocol.h b/common/protocol.h index 1feda02f2..beb09d496 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -285,11 +285,17 @@ public: class Response_GetGamesOfUser : public ProtocolResponse { Q_OBJECT +private: + QList gameList; + QList roomList; +protected: + void extractData(); public: - Response_GetGamesOfUser(int _cmdId = -1, ResponseCode _responseCode = RespOk, const QList &_gameList = QList()); + Response_GetGamesOfUser(int _cmdId = -1, ResponseCode _responseCode = RespOk, const QList &_roomList = QList(), const QList &_gameList = QList()); int getItemId() const { return ItemId_Response_GetGamesOfUser; } static SerializableItem *newItem() { return new Response_GetGamesOfUser; } - QList getGameList() const { return typecastItemList(); } + QList getRoomList() const { return roomList; } + QList getGameList() const { return gameList; } }; class Response_GetUserInfo : public ProtocolResponse { diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 40ab6751d..6ad7cd095 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -8,7 +8,7 @@ class DeckList; -enum ResponseCode { RespNothing, RespOk, RespInternalError, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed, RespOnlyBuddies, RespUserLevelTooLow, RespInIgnoreList, RespWouldOverwriteOldSession, RespChatFlood }; +enum ResponseCode { RespNothing, RespOk, RespNotInRoom, RespInternalError, RespInvalidCommand, RespInvalidData, RespNameNotFound, RespLoginNeeded, RespFunctionNotAllowed, RespGameNotStarted, RespGameFull, RespContextError, RespWrongPassword, RespSpectatorsNotAllowed, RespOnlyBuddies, RespUserLevelTooLow, RespInIgnoreList, RespWouldOverwriteOldSession, RespChatFlood }; // PrivateZone: Contents of the zone are always visible to the owner, // but not to anyone else. @@ -71,6 +71,7 @@ class ServerInfo_Game : public SerializableItem_Map { public: ServerInfo_Game(int _roomId = -1, int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, const QList &_gameTypes = QList(), ServerInfo_User *creatorInfo = 0, bool _onlyBuddies = false, bool _onlyRegistered = false, bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, int _spectatorCount = -1); static SerializableItem *newItem() { return new ServerInfo_Game; } + int getRoomId() const { return static_cast(itemMap.value("room_id"))->getData(); } int getGameId() const { return static_cast(itemMap.value("game_id"))->getData(); } QString getDescription() const { return static_cast(itemMap.value("description"))->getData(); } bool getHasPassword() const { return static_cast(itemMap.value("has_password"))->getData(); } diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index e6cadb582..974869e75 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -80,7 +80,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm Server_Room *room = rooms.value(roomCommand->getRoomId(), 0); if (!room) - return RespNameNotFound; + return RespNotInRoom; QMutexLocker locker(&room->roomMutex); @@ -101,7 +101,7 @@ ResponseCode Server_ProtocolHandler::processCommandHelper(Command *command, Comm gameListMutex.lock(); if (!games.contains(gameCommand->getGameId())) { qDebug() << "invalid game"; - return RespNameNotFound; + return RespNotInRoom; } QPair gamePair = games.value(gameCommand->getGameId()); Server_Game *game = gamePair.first; @@ -340,13 +340,19 @@ ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(Command_GetGamesOfUser *c if (!server->getUsers().contains(cmd->getUserName())) return RespNameNotFound; + QList roomList; QList gameList; QMapIterator roomIterator(server->getRooms()); - while (roomIterator.hasNext()) - gameList.append(roomIterator.next().value()->getGamesOfUser(cmd->getUserName())); + while (roomIterator.hasNext()) { + Server_Room *room = roomIterator.next().value(); + room->roomMutex.lock(); + roomList.append(room->getInfo(false, true)); + gameList.append(room->getGamesOfUser(cmd->getUserName())); + room->roomMutex.unlock(); + } server->serverMutex.unlock(); - ProtocolResponse *resp = new Response_GetGamesOfUser(cont->getCmdId(), RespOk, gameList); + ProtocolResponse *resp = new Response_GetGamesOfUser(cont->getCmdId(), RespOk, roomList, gameList); if (getCompressionSupport()) resp->setCompressed(true); cont->setResponse(resp); diff --git a/common/server_room.cpp b/common/server_room.cpp index 77030bff2..9e9aa571c 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -26,7 +26,7 @@ Server *Server_Room::getServer() const return static_cast(parent()); } -ServerInfo_Room *Server_Room::getInfo(bool complete) const +ServerInfo_Room *Server_Room::getInfo(bool complete, bool showGameTypes) const { QMutexLocker locker(&roomMutex); @@ -40,10 +40,10 @@ ServerInfo_Room *Server_Room::getInfo(bool complete) const for (int i = 0; i < size(); ++i) userList.append(new ServerInfo_User(at(i)->getUserInfo(), false)); - + } + if (complete || showGameTypes) for (int i = 0; i < gameTypes.size(); ++i) gameTypeList.append(new ServerInfo_GameType(i, gameTypes[i])); - } return new ServerInfo_Room(id, name, description, games.size(), size(), autoJoin, gameList, userList, gameTypeList); } @@ -133,8 +133,6 @@ int Server_Room::getGamesCreatedByUser(const QString &userName) const QList Server_Room::getGamesOfUser(const QString &userName) const { - QMutexLocker locker(&roomMutex); - QList result; QMapIterator gamesIterator(games); while (gamesIterator.hasNext()) { diff --git a/common/server_room.h b/common/server_room.h index 96712ac62..663c9cee3 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -38,7 +38,7 @@ public: QString getJoinMessage() const { return joinMessage; } const QMap &getGames() const { return games; } Server *getServer() const; - ServerInfo_Room *getInfo(bool complete) const; + ServerInfo_Room *getInfo(bool complete, bool showGameTypes = false) const; int getGamesCreatedByUser(const QString &name) const; QList getGamesOfUser(const QString &name) const; From 9727a389560306873eeff8989e44479f4474ee8c Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 2 Jul 2011 16:44:12 +0200 Subject: [PATCH 73/87] added missing files --- cockatrice/src/gameselector.cpp | 131 ++++++++++++++++++++++++++++++++ cockatrice/src/gameselector.h | 41 ++++++++++ cockatrice/src/gametypemap.h | 8 ++ sounds/cuckoo.raw | Bin 0 -> 43296 bytes 4 files changed, 180 insertions(+) create mode 100644 cockatrice/src/gameselector.cpp create mode 100644 cockatrice/src/gameselector.h create mode 100644 cockatrice/src/gametypemap.h create mode 100644 sounds/cuckoo.raw diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp new file mode 100644 index 000000000..9ca8a7e3e --- /dev/null +++ b/cockatrice/src/gameselector.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "dlg_creategame.h" +#include "abstractclient.h" +#include "protocol_items.h" +#include "gameselector.h" +#include "gamesmodel.h" + +GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent) + : QGroupBox(parent), client(_client), room(_room) +{ + gameListView = new QTreeView; + gameListModel = new GamesModel(_rooms, _gameTypes, this); + gameListProxyModel = new GamesProxyModel(this); + gameListProxyModel->setSourceModel(gameListModel); + gameListProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + gameListView->setModel(gameListProxyModel); + gameListView->setSortingEnabled(true); + if (_room) + gameListView->header()->hideSection(0); + gameListView->header()->setResizeMode(1, QHeaderView::ResizeToContents); + + showFullGamesCheckBox = new QCheckBox; + if (room) + createButton = new QPushButton; + else + createButton = 0; + joinButton = new QPushButton; + spectateButton = new QPushButton; + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addWidget(showFullGamesCheckBox); + buttonLayout->addStretch(); + if (room) + buttonLayout->addWidget(createButton); + buttonLayout->addWidget(joinButton); + buttonLayout->addWidget(spectateButton); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(gameListView); + mainLayout->addLayout(buttonLayout); + + retranslateUi(); + setLayout(mainLayout); + + setMinimumWidth((qreal) (gameListView->columnWidth(0) * gameListModel->columnCount()) / 1.5); + setMinimumHeight(200); + + connect(showFullGamesCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showFullGamesChanged(int))); + connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); + connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); + connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); +} + +void GameSelector::showFullGamesChanged(int state) +{ + gameListProxyModel->setFullGamesVisible(state); +} + +void GameSelector::actCreate() +{ + DlgCreateGame dlg(client, room->getRoomId(), room->getGameTypes(), this); + dlg.exec(); +} + +void GameSelector::checkResponse(ResponseCode response) +{ + if (createButton) + createButton->setEnabled(true); + joinButton->setEnabled(true); + spectateButton->setEnabled(true); + + switch (response) { + case RespNotInRoom: QMessageBox::critical(this, tr("Error"), tr("Please join the appropriate room first.")); break; + case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Wrong password.")); break; + case RespSpectatorsNotAllowed: QMessageBox::critical(this, tr("Error"), tr("Spectators are not allowed in this game.")); break; + case RespGameFull: QMessageBox::critical(this, tr("Error"), tr("The game is already full.")); break; + case RespNameNotFound: QMessageBox::critical(this, tr("Error"), tr("The game does not exist any more.")); break; + case RespUserLevelTooLow: QMessageBox::critical(this, tr("Error"), tr("This game is only open to registered users.")); break; + case RespOnlyBuddies: QMessageBox::critical(this, tr("Error"), tr("This game is only open to its creator's buddies.")); break; + case RespInIgnoreList: QMessageBox::critical(this, tr("Error"), tr("You are being ignored by the creator of this game.")); break; + default: ; + } +} + +void GameSelector::actJoin() +{ + bool spectator = sender() == spectateButton; + + QModelIndex ind = gameListView->currentIndex(); + if (!ind.isValid()) + return; + ServerInfo_Game *game = gameListModel->getGame(ind.data(Qt::UserRole).toInt()); + QString password; + if (game->getHasPassword() && !(spectator && !game->getSpectatorsNeedPassword())) { + bool ok; + password = QInputDialog::getText(this, tr("Join game"), tr("Password:"), QLineEdit::Password, QString(), &ok); + if (!ok) + return; + } + + Command_JoinGame *commandJoinGame = new Command_JoinGame(game->getRoomId(), game->getGameId(), password, spectator); + connect(commandJoinGame, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode))); + client->sendCommand(commandJoinGame); + + if (createButton) + createButton->setEnabled(false); + joinButton->setEnabled(false); + spectateButton->setEnabled(false); +} + +void GameSelector::retranslateUi() +{ + setTitle(tr("Games")); + showFullGamesCheckBox->setText(tr("Show &full games")); + if (createButton) + createButton->setText(tr("C&reate")); + joinButton->setText(tr("&Join")); + spectateButton->setText(tr("J&oin as spectator")); +} + +void GameSelector::processGameInfo(ServerInfo_Game *info) +{ + gameListModel->updateGameList(info); +} + diff --git a/cockatrice/src/gameselector.h b/cockatrice/src/gameselector.h new file mode 100644 index 000000000..4a178bc3b --- /dev/null +++ b/cockatrice/src/gameselector.h @@ -0,0 +1,41 @@ +#ifndef GAMESELECTOR_H +#define GAMESELECTOR_H + +#include +#include "protocol_datastructures.h" +#include "tab_room.h" +#include "gametypemap.h" + +class QTreeView; +class GamesModel; +class GamesProxyModel; +class QPushButton; +class QCheckBox; +class AbstractClient; +class TabRoom; + +class GameSelector : public QGroupBox { + Q_OBJECT +private slots: + void showFullGamesChanged(int state); + void actCreate(); + void actJoin(); + void checkResponse(ResponseCode response); +signals: + void gameJoined(int gameId); +private: + AbstractClient *client; + TabRoom *room; + + QTreeView *gameListView; + GamesModel *gameListModel; + GamesProxyModel *gameListProxyModel; + QPushButton *createButton, *joinButton, *spectateButton; + QCheckBox *showFullGamesCheckBox; +public: + GameSelector(AbstractClient *_client, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent = 0); + void retranslateUi(); + void processGameInfo(ServerInfo_Game *info); +}; + +#endif \ No newline at end of file diff --git a/cockatrice/src/gametypemap.h b/cockatrice/src/gametypemap.h new file mode 100644 index 000000000..fce161752 --- /dev/null +++ b/cockatrice/src/gametypemap.h @@ -0,0 +1,8 @@ +#ifndef GAMETYPEMAP_H +#define GAMETYPEMAP_H + +#include + +typedef QMap GameTypeMap; + +#endif \ No newline at end of file diff --git a/sounds/cuckoo.raw b/sounds/cuckoo.raw new file mode 100644 index 0000000000000000000000000000000000000000..52f0cbb60b4d0a924d31b6e985777779021ac760 GIT binary patch literal 43296 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 BTwDME literal 0 HcmV?d00001 From 898623f1ba8b87b7e38495bd2e46efef59c7279a Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 3 Jul 2011 16:45:52 +0200 Subject: [PATCH 74/87] filter running games; minor server code cleanup --- cockatrice/src/gameselector.cpp | 24 ++++++++-- cockatrice/src/gameselector.h | 3 +- cockatrice/src/gamesmodel.cpp | 15 ++++-- cockatrice/src/gamesmodel.h | 2 + cockatrice/translations/cockatrice_cs.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_de.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_en.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_es.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_fr.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_ja.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_pl.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_pt-br.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_pt.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_ru.ts | 51 +++++++++++---------- cockatrice/translations/cockatrice_sk.ts | 51 +++++++++++---------- common/protocol_datastructures.cpp | 3 +- common/protocol_datastructures.h | 3 +- common/server_card.cpp | 4 +- common/server_card.h | 2 +- common/server_cardzone.cpp | 12 ++--- common/server_cardzone.h | 2 +- common/server_game.cpp | 5 +- common/server_player.cpp | 6 +-- common/server_protocolhandler.cpp | 16 +++---- 24 files changed, 369 insertions(+), 289 deletions(-) diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 9ca8a7e3e..9c165d269 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -27,23 +27,34 @@ GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, const QMapheader()->setResizeMode(1, QHeaderView::ResizeToContents); showFullGamesCheckBox = new QCheckBox; + showRunningGamesCheckBox = new QCheckBox; + + QVBoxLayout *filterLayout = new QVBoxLayout; + filterLayout->addWidget(showFullGamesCheckBox); + filterLayout->addWidget(showRunningGamesCheckBox); + if (room) createButton = new QPushButton; else createButton = 0; joinButton = new QPushButton; spectateButton = new QPushButton; + QHBoxLayout *buttonLayout = new QHBoxLayout; - buttonLayout->addWidget(showFullGamesCheckBox); - buttonLayout->addStretch(); if (room) buttonLayout->addWidget(createButton); buttonLayout->addWidget(joinButton); buttonLayout->addWidget(spectateButton); + buttonLayout->setAlignment(Qt::AlignTop); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->addLayout(filterLayout); + hbox->addStretch(); + hbox->addLayout(buttonLayout); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(gameListView); - mainLayout->addLayout(buttonLayout); + mainLayout->addLayout(hbox); retranslateUi(); setLayout(mainLayout); @@ -52,6 +63,7 @@ GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, const QMapsetFullGamesVisible(state); } +void GameSelector::showRunningGamesChanged(int state) +{ + gameListProxyModel->setRunningGamesVisible(state); +} + void GameSelector::actCreate() { DlgCreateGame dlg(client, room->getRoomId(), room->getGameTypes(), this); @@ -118,6 +135,7 @@ void GameSelector::retranslateUi() { setTitle(tr("Games")); showFullGamesCheckBox->setText(tr("Show &full games")); + showRunningGamesCheckBox->setText(tr("Show &running games")); if (createButton) createButton->setText(tr("C&reate")); joinButton->setText(tr("&Join")); diff --git a/cockatrice/src/gameselector.h b/cockatrice/src/gameselector.h index 4a178bc3b..cf603b336 100644 --- a/cockatrice/src/gameselector.h +++ b/cockatrice/src/gameselector.h @@ -18,6 +18,7 @@ class GameSelector : public QGroupBox { Q_OBJECT private slots: void showFullGamesChanged(int state); + void showRunningGamesChanged(int state); void actCreate(); void actJoin(); void checkResponse(ResponseCode response); @@ -31,7 +32,7 @@ private: GamesModel *gameListModel; GamesProxyModel *gameListProxyModel; QPushButton *createButton, *joinButton, *spectateButton; - QCheckBox *showFullGamesCheckBox; + QCheckBox *showFullGamesCheckBox, *showRunningGamesCheckBox; public: GameSelector(AbstractClient *_client, TabRoom *_room, const QMap &_rooms, const QMap &_gameTypes, QWidget *parent = 0); void retranslateUi(); diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 9aff702b5..fc8e7d555 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -85,7 +85,7 @@ void GamesModel::updateGameList(ServerInfo_Game *_game) for (int i = 0; i < oldGameTypeList.size(); ++i) gameTypeList.append(new GameTypeId(oldGameTypeList[i]->getData())); - ServerInfo_Game *game = new ServerInfo_Game(_game->getRoomId(), _game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getOnlyBuddies(), _game->getOnlyRegistered(), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount()); + ServerInfo_Game *game = new ServerInfo_Game(_game->getRoomId(), _game->getGameId(), _game->getDescription(), _game->getHasPassword(), _game->getPlayerCount(), _game->getMaxPlayers(), _game->getStarted(), gameTypeList, new ServerInfo_User(_game->getCreatorInfo()), _game->getOnlyBuddies(), _game->getOnlyRegistered(), _game->getSpectatorsAllowed(), _game->getSpectatorsNeedPassword(), _game->getSpectatorCount()); for (int i = 0; i < gameList.size(); i++) if (gameList[i]->getGameId() == game->getGameId()) { if (game->getPlayerCount() == 0) { @@ -118,17 +118,22 @@ void GamesProxyModel::setFullGamesVisible(bool _fullGamesVisible) invalidateFilter(); } +void GamesProxyModel::setRunningGamesVisible(bool _runningGamesVisible) +{ + runningGamesVisible = _runningGamesVisible; + invalidateFilter(); +} + bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &/*sourceParent*/) const { - if (fullGamesVisible) - return true; - GamesModel *model = qobject_cast(sourceModel()); if (!model) return false; ServerInfo_Game *game = model->getGame(sourceRow); - if (game->getPlayerCount() == game->getMaxPlayers()) + if ((game->getPlayerCount() == game->getMaxPlayers()) && !fullGamesVisible) + return false; + if (game->getStarted() && !runningGamesVisible) return false; return true; diff --git a/cockatrice/src/gamesmodel.h b/cockatrice/src/gamesmodel.h index 6be0d1406..8461faf66 100644 --- a/cockatrice/src/gamesmodel.h +++ b/cockatrice/src/gamesmodel.h @@ -30,9 +30,11 @@ class GamesProxyModel : public QSortFilterProxyModel { Q_OBJECT private: bool fullGamesVisible; + bool runningGamesVisible; public: GamesProxyModel(QObject *parent = 0); void setFullGamesVisible(bool _fullGamesVisible); + void setRunningGamesVisible(bool _runningGamesVisible); protected: bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; }; diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index 0b328cc06..a5a99653b 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -1203,89 +1203,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - - + + + + + + + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + + Show &running games + + + + C&reate - + &Join - + J&oin as spectator diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 735b3c3be..c423fa687 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -1947,24 +1947,24 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic GameSelector - + C&reate Spiel e&rstellen - + &Join &Teilnehmen - - - - - - - - + + + + + + + + Error Fehler @@ -1973,71 +1973,76 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic XXX - + Please join the appropriate room first. Bitte betreten Sie erst den entsprechenden Raum. - + Wrong password. Falsches Passwort. - + Spectators are not allowed in this game. In diesem Spiel sind keine Zuschauer zugelassen. - + The game is already full. Das Spiel ist bereits voll. - + The game does not exist any more. Dieses Spiel gibt es nicht mehr. - + This game is only open to registered users. Dieses Spiel kann nur von registrierten Benutzern betreten werden. - + This game is only open to its creator's buddies. Dieses Spiel kann nur von Freunden des Erstellers betreten werden. - + You are being ignored by the creator of this game. Der Ersteller dieses Spiels ignoriert Sie. - + Join game Spiel beitreten - + Password: Passwort: - + Games Spiele - + Show &full games &Volle Spiele anzeigen + + + Show &running games + &Laufende Spiele anzeigen + &Show full games &Volle Spiele anzeigen - + J&oin as spectator &Zuschauen diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 87989e2c9..5693f33d1 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -1203,89 +1203,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate - + &Join - - - - - - - - + + + + + + + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + + Show &running games + + + + J&oin as spectator diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 877347b7e..1e091cca1 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -1565,93 +1565,98 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate C&rear - + &Join E&ntrar - - - - - - - - + + + + + + + + Error Error - + Please join the appropriate room first. - + Wrong password. Contraseña incorrecta. - + Spectators are not allowed in this game. No se permiten espectadores en esta partida. - + The game is already full. La partida no tiene plazas libres. - + The game does not exist any more. La partida ya no existe. - + This game is only open to registered users. Esta partida está abierta sólo a usuarios registrados. - + This game is only open to its creator's buddies. Esta partida está abierta sólo a los amigos del creador. - + You are being ignored by the creator of this game. Estas siendo ignorado por el creador de la partida. - + Join game Entrar en la partida - + Password: Contraseña: - + Games Partidas - + Show &full games Ver partidas &sin plazas libres + + + Show &running games + + &Show full games &Ver partidas sin plazas libres - + J&oin as spectator Entrar como e&spectador diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 2df8edd40..a6c656f4c 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -1415,94 +1415,99 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - - + + + + + + + + Error Erreur - + Please join the appropriate room first. - + Wrong password. Mot de passe erroné. - + Spectators are not allowed in this game. Les spectateurs ne sont pas autorisés dans cette partie. - + The game is already full. Cette partie est déjà pleine. - + The game does not exist any more. La partie n'existe plus. - + This game is only open to registered users. Cette partie n'est accessible qu'aux joueurs enregistrés. - + This game is only open to its creator's buddies. Cette partie n'est accessible qu'aux amis. - + You are being ignored by the creator of this game. Vous avez été ignoré par le créateur de la partie. - + Join game Rejoindre partie - + Password: Mot de passe: - + Games Parties - + Show &full games Montrer &toutes les parties + + + Show &running games + + &Show full games toutes ou complèetes? &Montrer toutes les parties - + C&reate C&réer - + &Join Re&joindre - + J&oin as spectator Rej&oindre en tant que spectateur diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index c9f0a6e9a..6d4c3aa93 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -1251,93 +1251,98 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate 部屋を作る - + &Join 参加する - - - - - - - - + + + + + + + + Error エラー - + Please join the appropriate room first. - + Wrong password. パスワードが間違っています. - + Spectators are not allowed in this game. この試合は観戦者は許可されていません. - + The game is already full. このゲームはすでに満員です. - + The game does not exist any more. このゲームはもう存在しません. - + This game is only open to registered users. このゲームは登録済みプレイヤーにのみ公開されています. - + This game is only open to its creator's buddies. このゲームは作成者のフレンドのみに公開されています. - + You are being ignored by the creator of this game. あなたはこのゲームの作成者によって拒否されています. - + Join game 参加 - + Password: パスワード: - + Games ゲーム - + Show &full games 全てのゲームを見る + + + Show &running games + + &Show full games 全てのゲームを見る - + J&oin as spectator 観戦者として参加 diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 492dbed27..3ba27c1e7 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -1203,89 +1203,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - - + + + + + + + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + + Show &running games + + + + C&reate - + &Join - + J&oin as spectator diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 0404d46d5..4f3707934 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -1419,93 +1419,98 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate &Criar - + &Join &Entrar - - - - - - - - + + + + + + + + Error Erro - + Please join the appropriate room first. - + Wrong password. Senha incorreta. - + Spectators are not allowed in this game. Não são permitidos visitantes neste jogo. - + The game is already full. O jogo está cheio. - + The game does not exist any more. O jogo não existe mais. - + This game is only open to registered users. Este jogo é aberto apenas para usuários registrados. - + This game is only open to its creator's buddies. Este jogo é aberto apenas para os amigos de quem criou o jogo. - + You are being ignored by the creator of this game. Você está sendo ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Senha: - + Games Jogos - + Show &full games &Mostrar os jogos cheios + + + Show &running games + + &Show full games &Mostrar os jogos cheios - + J&oin as spectator E&ntrar como visitante diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 351b8b981..a985f0b9d 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -1419,93 +1419,98 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - - + + + + + + + + Error Erro - + Please join the appropriate room first. - + Wrong password. Password incorrecta. - + Spectators are not allowed in this game. Não são permitidos espectadores neste jogo. - + The game is already full. O jogo já se encontra cheio. - + The game does not exist any more. O jogo já não existe. - + This game is only open to registered users. Este jogo só está aberto a utilizadores registados. - + This game is only open to its creator's buddies. Este jogo só está aberto aos amigos do seu criador. - + You are being ignored by the creator of this game. Você está a ser ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Password: - + Games Jogos - + Show &full games &Mostrar jogos cheios + + + Show &running games + + &Show full games &Mostrar jogos cheios - + C&reate &Criar - + &Join &Entrar - + J&oin as spectator Entrar como &espectador diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 8f875c2a9..ff02c2a11 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -1358,89 +1358,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - - + + + + + + + + Error Ошибка - + Please join the appropriate room first. - + Wrong password. Неверный пароль. - + Spectators are not allowed in this game. В эту игру не пускают зрителей. - + The game is already full. Все места заняты! =Ь - + The game does not exist any more. Эта игра была удалена. - + This game is only open to registered users. Доступно только для зарегистрированных. - + This game is only open to its creator's buddies. Доступно только для друзей. - + You are being ignored by the creator of this game. Вы добавлены в игнор-лист данного игрока. - + Join game Присоединиться - + Password: Пароль: - + Games Игры - + Show &full games Показывать &текущие - + + Show &running games + + + + C&reate С&оздать - + &Join &Присоединиться - + J&oin as spectator П&рисоединиться как зритель diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index dddb74650..1a1beeac1 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -1203,89 +1203,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - - - - - - - + + + + + + + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + + Show &running games + + + + C&reate - + &Join - + J&oin as spectator diff --git a/common/protocol_datastructures.cpp b/common/protocol_datastructures.cpp index 3e4564c86..7d68434af 100644 --- a/common/protocol_datastructures.cpp +++ b/common/protocol_datastructures.cpp @@ -40,7 +40,7 @@ ServerInfo_UserList::ServerInfo_UserList(const QString &_itemType, const QList &_gameTypes, ServerInfo_User *_creatorInfo, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) +ServerInfo_Game::ServerInfo_Game(int _roomId, int _gameId, const QString &_description, bool _hasPassword, int _playerCount, int _maxPlayers, bool _started, const QList &_gameTypes, ServerInfo_User *_creatorInfo, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, int _spectatorCount) : SerializableItem_Map("game") { insertItem(new SerializableItem_Int("room_id", _roomId)); @@ -49,6 +49,7 @@ ServerInfo_Game::ServerInfo_Game(int _roomId, int _gameId, const QString &_descr insertItem(new SerializableItem_Bool("has_password", _hasPassword)); insertItem(new SerializableItem_Int("player_count", _playerCount)); insertItem(new SerializableItem_Int("max_players", _maxPlayers)); + insertItem(new SerializableItem_Bool("started", _started)); if (!_creatorInfo) _creatorInfo = new ServerInfo_User; insertItem(_creatorInfo); diff --git a/common/protocol_datastructures.h b/common/protocol_datastructures.h index 6ad7cd095..a3843a3d7 100644 --- a/common/protocol_datastructures.h +++ b/common/protocol_datastructures.h @@ -69,7 +69,7 @@ public: class ServerInfo_Game : public SerializableItem_Map { public: - ServerInfo_Game(int _roomId = -1, int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, const QList &_gameTypes = QList(), ServerInfo_User *creatorInfo = 0, bool _onlyBuddies = false, bool _onlyRegistered = false, bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, int _spectatorCount = -1); + ServerInfo_Game(int _roomId = -1, int _gameId = -1, const QString &_description = QString(), bool _hasPassword = false, int _playerCount = -1, int _maxPlayers = -1, bool _started = false, const QList &_gameTypes = QList(), ServerInfo_User *creatorInfo = 0, bool _onlyBuddies = false, bool _onlyRegistered = false, bool _spectatorsAllowed = false, bool _spectatorsNeedPassword = false, int _spectatorCount = -1); static SerializableItem *newItem() { return new ServerInfo_Game; } int getRoomId() const { return static_cast(itemMap.value("room_id"))->getData(); } int getGameId() const { return static_cast(itemMap.value("game_id"))->getData(); } @@ -77,6 +77,7 @@ public: bool getHasPassword() const { return static_cast(itemMap.value("has_password"))->getData(); } int getPlayerCount() const { return static_cast(itemMap.value("player_count"))->getData(); } int getMaxPlayers() const { return static_cast(itemMap.value("max_players"))->getData(); } + bool getStarted() const { return static_cast(itemMap.value("started"))->getData(); } QList getGameTypes() const { return typecastItemList(); } ServerInfo_User *getCreatorInfo() const { return static_cast(itemMap.value("user")); } bool getOnlyBuddies() const { return static_cast(itemMap.value("only_buddies"))->getData(); } diff --git a/common/server_card.cpp b/common/server_card.cpp index 3d34ac530..6cafdd903 100644 --- a/common/server_card.cpp +++ b/common/server_card.cpp @@ -19,8 +19,8 @@ ***************************************************************************/ #include "server_card.h" -Server_Card::Server_Card(QString _name, int _id, int _coord_x, int _coord_y) - : id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), tapped(false), attacking(false), facedown(false), color(QString()), power(-1), toughness(-1), annotation(QString()), destroyOnZoneChange(false), doesntUntap(false), parentCard(0) +Server_Card::Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone) + : zone(_zone), id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), tapped(false), attacking(false), facedown(false), color(QString()), power(-1), toughness(-1), annotation(QString()), destroyOnZoneChange(false), doesntUntap(false), parentCard(0) { } diff --git a/common/server_card.h b/common/server_card.h index de84d21ce..a908befaf 100644 --- a/common/server_card.h +++ b/common/server_card.h @@ -46,7 +46,7 @@ private: Server_Card *parentCard; QList attachedCards; public: - Server_Card(QString _name, int _id, int _coord_x, int _coord_y); + Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone = 0); ~Server_Card(); Server_CardZone *getZone() const { return zone; } diff --git a/common/server_cardzone.cpp b/common/server_cardzone.cpp index 8738afab9..dd1db3eee 100644 --- a/common/server_cardzone.cpp +++ b/common/server_cardzone.cpp @@ -52,10 +52,12 @@ int Server_CardZone::removeCard(Server_Card *card) int index = cards.indexOf(card); cards.removeAt(index); + card->setZone(0); + return index; } -Server_Card *Server_CardZone::getCard(int id, bool remove, int *position) +Server_Card *Server_CardZone::getCard(int id, int *position) { QMutexLocker locker(&player->getGame()->gameMutex); @@ -65,10 +67,6 @@ Server_Card *Server_CardZone::getCard(int id, bool remove, int *position) while (CardIterator.hasNext()) { Server_Card *tmp = CardIterator.next(); if (tmp->getId() == id) { - if (remove) { - cards.removeAt(i); - tmp->setZone(0); - } if (position) *position = i; return tmp; @@ -80,10 +78,6 @@ Server_Card *Server_CardZone::getCard(int id, bool remove, int *position) if ((id >= cards.size()) || (id < 0)) return NULL; Server_Card *tmp = cards[id]; - if (remove) { - cards.removeAt(id); - tmp->setZone(0); - } if (position) *position = id; return tmp; diff --git a/common/server_cardzone.h b/common/server_cardzone.h index 62a129a1d..898e89c78 100644 --- a/common/server_cardzone.h +++ b/common/server_cardzone.h @@ -41,7 +41,7 @@ public: ~Server_CardZone(); int removeCard(Server_Card *card); - Server_Card *getCard(int id, bool remove, int *position = NULL); + Server_Card *getCard(int id, int *position = NULL); int getCardsBeingLookedAt() const { return cardsBeingLookedAt; } void setCardsBeingLookedAt(int _cardsBeingLookedAt) { cardsBeingLookedAt = _cardsBeingLookedAt; } diff --git a/common/server_game.cpp b/common/server_game.cpp index bc14c7e96..5838e3f97 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -160,6 +160,8 @@ void Server_Game::doStartGameIfReady() */ activePlayer = -1; nextTurn(); + + room->broadcastGameListUpdate(this); } void Server_Game::startGameIfReady() @@ -490,7 +492,7 @@ ServerInfo_Game *Server_Game::getInfo() const if (players.isEmpty()) // Game is closing - return new ServerInfo_Game(room->getId(), getGameId(), QString(), false, 0, getMaxPlayers(), QList(), 0, false, 0); + return new ServerInfo_Game(room->getId(), getGameId(), QString(), false, 0, getMaxPlayers(), false, QList(), 0, false, 0); else { // Game is open @@ -505,6 +507,7 @@ ServerInfo_Game *Server_Game::getInfo() const !getPassword().isEmpty(), getPlayerCount(), getMaxPlayers(), + gameStarted, gameTypeList, new ServerInfo_User(getCreatorInfo(), false), onlyBuddies, diff --git a/common/server_player.cpp b/common/server_player.cpp index e56953803..3a9899a97 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -127,7 +127,7 @@ void Server_Player::setupZones() if (!currentCard) continue; for (int k = 0; k < currentCard->getNumber(); ++k) - z->cards.append(new Server_Card(currentCard->getName(), nextCardId++, 0, 0)); + z->cards.append(new Server_Card(currentCard->getName(), nextCardId++, 0, 0, z)); } } @@ -334,7 +334,7 @@ ResponseCode Server_Player::moveCard(CommandContainer *cont, Server_CardZone *st QMap cardProperties; for (int i = 0; i < _cards.size(); ++i) { int position; - Server_Card *card = startzone->getCard(_cards[i]->getCardId(), false, &position); + Server_Card *card = startzone->getCard(_cards[i]->getCardId(), &position); if (!card) return RespNameNotFound; if (!card->getAttachedCards().isEmpty() && !targetzone->isColumnEmpty(x, y)) @@ -510,7 +510,7 @@ ResponseCode Server_Player::setCardAttrHelper(CommandContainer *cont, const QStr return RespInvalidCommand; } } else { - Server_Card *card = zone->getCard(cardId, false); + Server_Card *card = zone->getCard(cardId); if (!card) return RespNameNotFound; result = card->setAttribute(attrName, attrValue, false); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 974869e75..2db831263 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -768,7 +768,7 @@ ResponseCode Server_ProtocolHandler::cmdFlipCard(Command_FlipCard *cmd, CommandC if (!zone->hasCoords()) return RespContextError; - Server_Card *card = zone->getCard(cmd->getCardId(), false); + Server_Card *card = zone->getCard(cmd->getCardId()); if (!card) return RespNameNotFound; @@ -797,7 +797,7 @@ ResponseCode Server_ProtocolHandler::cmdAttachCard(Command_AttachCard *cmd, Comm if (!startzone) return RespNameNotFound; - Server_Card *card = startzone->getCard(cmd->getCardId(), false); + Server_Card *card = startzone->getCard(cmd->getCardId()); if (!card) return RespNameNotFound; @@ -819,7 +819,7 @@ ResponseCode Server_ProtocolHandler::cmdAttachCard(Command_AttachCard *cmd, Comm // Possibly a flag will have to be introduced for this sometime. if (!targetzone->hasCoords()) return RespContextError; - targetCard = targetzone->getCard(cmd->getTargetCardId(), false); + targetCard = targetzone->getCard(cmd->getTargetCardId()); if (targetCard) if (targetCard->getParentCard()) return RespContextError; @@ -929,14 +929,14 @@ ResponseCode Server_ProtocolHandler::cmdCreateArrow(Command_CreateArrow *cmd, Co return RespNameNotFound; if (startZone->getType() != PublicZone) return RespContextError; - Server_Card *startCard = startZone->getCard(cmd->getStartCardId(), false); + Server_Card *startCard = startZone->getCard(cmd->getStartCardId()); if (!startCard) return RespNameNotFound; Server_Card *targetCard = 0; if (!playerTarget) { if (targetZone->getType() != PublicZone) return RespContextError; - targetCard = targetZone->getCard(cmd->getTargetCardId(), false); + targetCard = targetZone->getCard(cmd->getTargetCardId()); } Server_ArrowTarget *targetItem; @@ -1015,7 +1015,7 @@ ResponseCode Server_ProtocolHandler::cmdSetCardCounter(Command_SetCardCounter *c if (!zone->hasCoords()) return RespContextError; - Server_Card *card = zone->getCard(cmd->getCardId(), false); + Server_Card *card = zone->getCard(cmd->getCardId()); if (!card) return RespNameNotFound; @@ -1042,7 +1042,7 @@ ResponseCode Server_ProtocolHandler::cmdIncCardCounter(Command_IncCardCounter *c if (!zone->hasCoords()) return RespContextError; - Server_Card *card = zone->getCard(cmd->getCardId(), false); + Server_Card *card = zone->getCard(cmd->getCardId()); if (!card) return RespNameNotFound; @@ -1255,7 +1255,7 @@ ResponseCode Server_ProtocolHandler::cmdRevealCards(Command_RevealCards *cmd, Co return RespContextError; cardsToReveal.append(zone->cards.at(rng->getNumber(0, zone->cards.size() - 1))); } else { - Server_Card *card = zone->getCard(cmd->getCardId(), false); + Server_Card *card = zone->getCard(cmd->getCardId()); if (!card) return RespNameNotFound; cardsToReveal.append(card); From fd171fa260359aeff2f59fb37d9dbd3a6d0e4ef6 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 3 Jul 2011 17:10:24 +0200 Subject: [PATCH 75/87] servatrice Qt 4.4 compile fix --- common/server_protocolhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 2db831263..9c752e8ab 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -347,7 +347,7 @@ ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(Command_GetGamesOfUser *c Server_Room *room = roomIterator.next().value(); room->roomMutex.lock(); roomList.append(room->getInfo(false, true)); - gameList.append(room->getGamesOfUser(cmd->getUserName())); + gameList << room->getGamesOfUser(cmd->getUserName()); room->roomMutex.unlock(); } server->serverMutex.unlock(); From 83e2e3666a296ec3766fd92980fae4a74edecb89 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 4 Jul 2011 17:14:48 +0200 Subject: [PATCH 76/87] server memory leak fixed --- common/server_protocolhandler.cpp | 1 + servatrice/src/main.cpp | 5 +++-- servatrice/src/servatrice.cpp | 11 +++++++---- servatrice/src/serversocketinterface.cpp | 1 + 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 9c752e8ab..5e4ba7751 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -405,6 +405,7 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC if (!r) return RespNameNotFound; + QMutexLocker serverLocker(&server->serverMutex); QMutexLocker roomLocker(&r->roomMutex); r->addClient(this); rooms.insert(r->getId(), r); diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index 6c16c965a..247111be8 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -129,8 +129,8 @@ int main(int argc, char *argv[]) if (testRandom) testRNG(); - Servatrice server(settings); - QObject::connect(&server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection); + Servatrice *server = new Servatrice(settings); + QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection); std::cerr << "-------------------------" << std::endl; std::cerr << "Server initialized." << std::endl; @@ -142,6 +142,7 @@ int main(int argc, char *argv[]) delete rng; delete settings; + delete loggerThread; return retval; } diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 1bb126e53..a19475c14 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -66,7 +66,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) } bool threaded = settings->value("server/threaded", false).toInt(); - tcpServer = new Servatrice_TcpServer(this, threaded); + tcpServer = new Servatrice_TcpServer(this, threaded, this); int port = settings->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << port; if (tcpServer->listen(QHostAddress::Any, port)) @@ -364,17 +364,20 @@ void Servatrice::updateLoginMessage() void Servatrice::statusUpdate() { - QMutexLocker locker(&dbMutex); + const int uc = getUsersCount(); // for correct mutex locking order + const int gc = getGamesCount(); + uptime += statusUpdateClock->interval() / 1000; + QMutexLocker locker(&dbMutex); checkSql(); QSqlQuery query; query.prepare("insert into " + dbPrefix + "_uptime (id_server, timest, uptime, users_count, games_count) values(:id, NOW(), :uptime, :users_count, :games_count)"); query.bindValue(":id", serverId); query.bindValue(":uptime", uptime); - query.bindValue(":users_count", getUsersCount()); - query.bindValue(":games_count", getGamesCount()); + query.bindValue(":users_count", uc); + query.bindValue(":games_count", gc); execSqlQuery(query); } diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 895fcee2b..1e83693e1 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -69,6 +69,7 @@ ServerSocketInterface::~ServerSocketInterface() delete xmlReader; delete socket; socket = 0; + delete topLevelItem; } void ServerSocketInterface::processProtocolItem(ProtocolItem *item) From c4a2229ae4511ef54d088573d84fa381271f52f9 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 5 Jul 2011 01:49:15 +0200 Subject: [PATCH 77/87] added debug stuff --- common/server.cpp | 4 +++- common/server_protocolhandler.cpp | 1 + servatrice/src/servatrice.cpp | 2 +- servatrice/src/serversocketinterface.cpp | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common/server.cpp b/common/server.cpp index 07f7c7cfe..704510181 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -74,6 +74,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString session->setUserInfo(data); users.insert(name, session); + qDebug() << "Server::loginUser: name=" << name; Event_UserJoined *event = new Event_UserJoined(new ServerInfo_User(data, false)); for (int i = 0; i < clients.size(); ++i) @@ -103,8 +104,9 @@ void Server::removeClient(Server_ProtocolHandler *client) delete event; users.remove(data->getName()); + qDebug() << "Server::removeClient: name=" << data->getName(); } - qDebug() << "Server::removeClient: " << clients.size() << "clients; " << users.size() << "users left"; + qDebug() << "Server::removeClient:" << clients.size() << "clients; " << users.size() << "users left"; } void Server::broadcastRoomUpdate() diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 9c752e8ab..58d027407 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -321,6 +321,7 @@ ResponseCode Server_ProtocolHandler::cmdMessage(Command_Message *cmd, CommandCon QString receiver = cmd->getUserName(); Server_ProtocolHandler *userHandler = server->getUsers().value(receiver); + qDebug() << "cmdMessage: recv=" << receiver << (userHandler == 0 ? "not found" : "found"); if (!userHandler) return RespNameNotFound; if (userHandler->getIgnoreList().contains(userInfo->getName())) diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 1bb126e53..e5f7afa6d 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -186,7 +186,7 @@ AuthenticationResult Servatrice::checkUserPassword(Server_ProtocolHandler *handl checkSql(); QSqlQuery query; - query.prepare("select a.password, timediff(now(), date_add(b.time_from, interval b.minutes minute)) < 0, b.minutes <=> 0 from " + dbPrefix + "_users a left join " + dbPrefix + "_bans b on b.id_user = a.id and b.time_from = (select max(c.time_from) from " + dbPrefix + "_bans c where c.id_user = a.id) where a.name = :name and a.active = 1"); + query.prepare("select a.password, time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))) < 0, b.minutes <=> 0 from " + dbPrefix + "_users a left join " + dbPrefix + "_bans b on b.id_user = a.id and b.time_from = (select max(c.time_from) from " + dbPrefix + "_bans c where c.id_user = a.id) where a.name = :name and a.active = 1"); query.bindValue(":name", user); if (!execSqlQuery(query)) return PasswordWrong; diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 895fcee2b..4fe5bb3ab 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -494,7 +494,7 @@ ResponseCode ServerSocketInterface::cmdBanFromServer(Command_BanFromServer *cmd, query.bindValue(":id_user", getUserIdInDB(userName)); query.bindValue(":id_admin", getUserIdInDB(userInfo->getName())); query.bindValue(":minutes", minutes); - query.bindValue(":reason", cmd->getReason()); + query.bindValue(":reason", cmd->getReason() + "\n"); servatrice->execSqlQuery(query); } else { // Unregistered users must be banned by IP address. From ef42c7518a13f9b17a6ebda43925078d53357a1b Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 5 Jul 2011 12:44:39 +0200 Subject: [PATCH 78/87] added argentina to countries --- cockatrice/cockatrice.qrc | 1 + cockatrice/resources/countries/ar.svg | 109 ++++++++++++++++++++++++++ cockatrice/src/localserver.h | 1 + common/server.h | 1 + servatrice/src/servatrice.cpp | 2 +- servatrice/src/servatrice.h | 2 + 6 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 cockatrice/resources/countries/ar.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 553561306..3a75a53d8 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -55,6 +55,7 @@ translations/cockatrice_pl.qm translations/cockatrice_sk.qm + resources/countries/ar.svg resources/countries/at.svg resources/countries/au.svg resources/countries/be.svg diff --git a/cockatrice/resources/countries/ar.svg b/cockatrice/resources/countries/ar.svg new file mode 100644 index 000000000..543196fc3 --- /dev/null +++ b/cockatrice/resources/countries/ar.svg @@ -0,0 +1,109 @@ + + + + + \ No newline at end of file diff --git a/cockatrice/src/localserver.h b/cockatrice/src/localserver.h index 406b3bff8..cf24b4385 100644 --- a/cockatrice/src/localserver.h +++ b/cockatrice/src/localserver.h @@ -16,6 +16,7 @@ public: bool getGameShouldPing() const { return false; } int getMaxGameInactivityTime() const { return 9999999; } int getMaxPlayerInactivityTime() const { return 9999999; } + bool getThreaded() const { return false; } LocalServerInterface *newConnection(); protected: diff --git a/common/server.h b/common/server.h index d2f15e76f..de8dd2a5f 100644 --- a/common/server.h +++ b/common/server.h @@ -40,6 +40,7 @@ public: virtual int getMaxMessageCountPerInterval() const { return 0; } virtual int getMaxMessageSizePerInterval() const { return 0; } virtual int getMaxGamesPerUser() const { return 0; } + virtual bool getThreaded() const = 0; virtual QMap getBuddyList(const QString &name) = 0; virtual QMap getIgnoreList(const QString &name) = 0; diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index a19475c14..48134b5f4 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -65,7 +65,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) statusUpdateClock->start(statusUpdateTime); } - bool threaded = settings->value("server/threaded", false).toInt(); + threaded = settings->value("server/threaded", false).toInt(); tcpServer = new Servatrice_TcpServer(this, threaded, this); int port = settings->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << port; diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 5a2fb1b89..8dae2c91f 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -68,6 +68,7 @@ public: int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; } int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; } int getMaxGamesPerUser() const { return maxGamesPerUser; } + bool getThreaded() const { return threaded; } QString getDbPrefix() const { return dbPrefix; } void updateLoginMessage(); ServerInfo_User *getUserData(const QString &name); @@ -86,6 +87,7 @@ private: QString dbPrefix; QSettings *settings; int serverId; + bool threaded; int uptime; QList > addressBanList; int maxGameInactivityTime, maxPlayerInactivityTime; From add47315d52b78af40f39199c64d5ed1586f3c44 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 5 Jul 2011 21:02:24 +0200 Subject: [PATCH 79/87] added drawArrow context menu item --- cockatrice/src/carditem.cpp | 56 ++++--- cockatrice/src/carditem.h | 5 +- cockatrice/translations/cockatrice_cs.ts | 157 ++++++++++---------- cockatrice/translations/cockatrice_de.ts | 119 ++++++++------- cockatrice/translations/cockatrice_en.ts | 157 ++++++++++---------- cockatrice/translations/cockatrice_es.ts | 119 ++++++++------- cockatrice/translations/cockatrice_fr.ts | 119 ++++++++------- cockatrice/translations/cockatrice_ja.ts | 119 ++++++++------- cockatrice/translations/cockatrice_pl.ts | 157 ++++++++++---------- cockatrice/translations/cockatrice_pt-br.ts | 119 ++++++++------- cockatrice/translations/cockatrice_pt.ts | 119 ++++++++------- cockatrice/translations/cockatrice_ru.ts | 119 ++++++++------- cockatrice/translations/cockatrice_sk.ts | 157 ++++++++++---------- 13 files changed, 799 insertions(+), 723 deletions(-) diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index 861943907..afc15e8c0 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -34,6 +34,8 @@ CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, bool _reve connect(aAttach, SIGNAL(triggered()), this, SLOT(actAttach())); aUnattach = new QAction(this); connect(aUnattach, SIGNAL(triggered()), this, SLOT(actUnattach())); + aDrawArrow = new QAction(this); + connect(aDrawArrow, SIGNAL(triggered()), this, SLOT(actDrawArrow())); aIncP = new QAction(this); connect(aIncP, SIGNAL(triggered()), this, SLOT(actIncP())); aDecP = new QAction(this); @@ -172,6 +174,7 @@ void CardItem::updateCardMenu() cardMenu->addAction(aAttach); if (attachedTo) cardMenu->addAction(aUnattach); + cardMenu->addAction(aDrawArrow); cardMenu->addSeparator(); cardMenu->addMenu(ptMenu); cardMenu->addAction(aSetAnnotation); @@ -186,6 +189,9 @@ void CardItem::updateCardMenu() cardMenu->addAction(aSetCounter[i]); } cardMenu->addSeparator(); + } else if (zone->getName() == "stack") { + cardMenu->addAction(aDrawArrow); + cardMenu->addMenu(moveMenu); } else { cardMenu->addAction(aPlay); cardMenu->addMenu(moveMenu); @@ -209,6 +215,7 @@ void CardItem::retranslateUi() aAttach->setText(tr("&Attach to card...")); aAttach->setShortcut(tr("Ctrl+A")); aUnattach->setText(tr("Unattac&h")); + aDrawArrow->setText(tr("&Draw arrow...")); ptMenu->setTitle(tr("&Power / toughness")); aIncP->setText(tr("&Increase power")); aIncP->setShortcut(tr("Ctrl++")); @@ -399,13 +406,35 @@ void CardItem::deleteDragItem() dragItem = NULL; } +void CardItem::drawArrow(const QColor &arrowColor) +{ + if (static_cast(owner->parent())->getSpectator()) + return; + + Player *arrowOwner = static_cast(owner->parent())->getActiveLocalPlayer(); + ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor); + scene()->addItem(arrow); + arrow->grabMouse(); + + QListIterator itemIterator(scene()->selectedItems()); + while (itemIterator.hasNext()) { + CardItem *c = qgraphicsitem_cast(itemIterator.next()); + if (!c || (c == this)) + continue; + if (c->getZone() != zone) + continue; + + ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor); + scene()->addItem(childArrow); + arrow->addChildArrow(childArrow); + } +} + void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons().testFlag(Qt::RightButton)) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance()) return; - if (static_cast(owner->parent())->getSpectator()) - return; QColor arrowColor = Qt::red; if (event->modifiers().testFlag(Qt::ControlModifier)) @@ -415,23 +444,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) else if (event->modifiers().testFlag(Qt::ShiftModifier)) arrowColor = Qt::green; - Player *arrowOwner = static_cast(owner->parent())->getActiveLocalPlayer(); - ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor); - scene()->addItem(arrow); - arrow->grabMouse(); - - QListIterator itemIterator(scene()->selectedItems()); - while (itemIterator.hasNext()) { - CardItem *c = qgraphicsitem_cast(itemIterator.next()); - if (!c || (c == this)) - continue; - if (c->getZone() != zone) - continue; - - ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor); - scene()->addItem(childArrow); - arrow->addChildArrow(childArrow); - } + drawArrow(arrowColor); } else if (event->buttons().testFlag(Qt::LeftButton)) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance()) return; @@ -547,6 +560,11 @@ void CardItem::actUnattach() owner->actUnattach(static_cast(sender())); } +void CardItem::actDrawArrow() +{ + drawArrow(Qt::red); +} + void CardItem::actIncP() { owner->actIncPT(1, 0); diff --git a/cockatrice/src/carditem.h b/cockatrice/src/carditem.h index 88b19d6f3..6c02a4bbe 100644 --- a/cockatrice/src/carditem.h +++ b/cockatrice/src/carditem.h @@ -9,6 +9,7 @@ class CardZone; class ServerInfo_Card; class Player; class QAction; +class QColor; const int MAX_COUNTERS_ON_CARD = 999; @@ -33,17 +34,19 @@ private: QList aAddCounter, aSetCounter, aRemoveCounter; QAction *aPlay, *aHide, - *aTap, *aUntap, *aDoesntUntap, *aAttach, *aUnattach, *aSetPT, *aIncP, *aDecP, *aIncT, *aDecT, *aIncPT, *aDecPT, *aSetAnnotation, *aFlip, *aClone, + *aTap, *aUntap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aIncP, *aDecP, *aIncT, *aDecT, *aIncPT, *aDecPT, *aSetAnnotation, *aFlip, *aClone, *aMoveToTopLibrary, *aMoveToBottomLibrary, *aMoveToGraveyard, *aMoveToExile; QMenu *cardMenu, *ptMenu, *moveMenu; void playCard(bool faceDown); + void drawArrow(const QColor &arrowColor); void prepareDelete(); private slots: void cardMenuAction(); void actCardCounterTrigger(); void actAttach(); void actUnattach(); + void actDrawArrow(); void actSetPT(); void actIncP(); void actDecP(); diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index a5a99653b..9a24bb029 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -230,197 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - - - &Power / toughness - - - - - &Increase power - - - - - Ctrl++ - - - &Decrease power + &Draw arrow... - Ctrl+- + &Power / toughness - I&ncrease toughness + &Increase power - Alt++ + Ctrl++ - D&ecrease toughness + &Decrease power - Alt+- + Ctrl+- - In&crease power and toughness + I&ncrease toughness - Ctrl+Alt++ + Alt++ - Dec&rease power and toughness + D&ecrease toughness - Ctrl+Alt+- + Alt+- - Set &power and toughness... + In&crease power and toughness - Ctrl+P + Ctrl+Alt++ - &Set annotation... + Dec&rease power and toughness + + + + + Ctrl+Alt+- - red + Set &power and toughness... - yellow + Ctrl+P - green + &Set annotation... - &Add counter (%1) + red + + + + + yellow - &Remove counter (%1) + green - &Set counters (%1)... - - - - - &top of library + &Add counter (%1) - &bottom of library - - - - - &graveyard + &Remove counter (%1) - Ctrl+Del + &Set counters (%1)... - &exile + &top of library + + + + + &bottom of library + &graveyard + + + + + Ctrl+Del + + + + + &exile + + + + &Move to @@ -1203,94 +1208,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + C&reate - + &Join - + J&oin as spectator diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index c423fa687..0b07c46f6 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -279,57 +279,57 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic CardItem - + &Play &Ausspielen - + &Hide &Verstecken - + &Tap &Tappen - + &Untap E&nttappen - + Toggle &normal untapping N&ormales Enttappen umschalten - + &Flip &Umdrehen - + &Clone &Kopieren - + Ctrl+H Ctrl+H - + &Attach to card... &An Karte anlegen... - + Ctrl+A Ctrl+A - + Unattac&h &Von Karte lösen @@ -338,142 +338,147 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Kampfwerte setzen... - + + &Draw arrow... + &Pfeil zeichnen... + + + &Power / toughness &Kampfwerte - + &Increase power &Stärke erhöhen - + Ctrl++ Ctrl++ - + &Decrease power S&tärke senken - + Ctrl+- Ctrl+- - + I&ncrease toughness &Widerstandskraft erhöhen - + Alt++ Alt++ - + D&ecrease toughness W&iderstandskraft senken - + Alt+- Alt+- - + In&crease power and toughness Stärke und Widerstandskraft &erhöhen - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Stärke und Widerstandskraft s&enken - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... &Kampfwerte setzen... - + Ctrl+P Ctrl+P - + &Set annotation... &Hinweis setzen... - + red rot - + yellow gelb - + green grün - + &Add counter (%1) Zählmarke &hinzufügen (%1) - + &Remove counter (%1) Zählmarke &entfernen (%1) - + &Set counters (%1)... Zählmarken &setzen (%1)... - + &top of library &auf die Bibliothek - + &bottom of library &unter die Bibliothek - + &graveyard in den &Friedhof - + Ctrl+Del Ctrl+Del - + &exile ins &Exil - + &Move to &Verschieben @@ -1947,24 +1952,24 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic GameSelector - + C&reate Spiel e&rstellen - + &Join &Teilnehmen - - + + Error Fehler @@ -1973,67 +1978,67 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic XXX - + Please join the appropriate room first. Bitte betreten Sie erst den entsprechenden Raum. - + Wrong password. Falsches Passwort. - + Spectators are not allowed in this game. In diesem Spiel sind keine Zuschauer zugelassen. - + The game is already full. Das Spiel ist bereits voll. - + The game does not exist any more. Dieses Spiel gibt es nicht mehr. - + This game is only open to registered users. Dieses Spiel kann nur von registrierten Benutzern betreten werden. - + This game is only open to its creator's buddies. Dieses Spiel kann nur von Freunden des Erstellers betreten werden. - + You are being ignored by the creator of this game. Der Ersteller dieses Spiels ignoriert Sie. - + Join game Spiel beitreten - + Password: Passwort: - + Games Spiele - + Show &full games &Volle Spiele anzeigen - + Show &running games &Laufende Spiele anzeigen @@ -2042,7 +2047,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Volle Spiele anzeigen - + J&oin as spectator &Zuschauen diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index 5693f33d1..e6cc82937 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -230,197 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - - - &Power / toughness - - - - - &Increase power - - - - - Ctrl++ - - - &Decrease power + &Draw arrow... - Ctrl+- + &Power / toughness - I&ncrease toughness + &Increase power - Alt++ + Ctrl++ - D&ecrease toughness + &Decrease power - Alt+- + Ctrl+- - In&crease power and toughness + I&ncrease toughness - Ctrl+Alt++ + Alt++ - Dec&rease power and toughness + D&ecrease toughness - Ctrl+Alt+- + Alt+- - Set &power and toughness... + In&crease power and toughness - Ctrl+P + Ctrl+Alt++ - &Set annotation... + Dec&rease power and toughness + + + + + Ctrl+Alt+- - red + Set &power and toughness... - yellow + Ctrl+P - green + &Set annotation... - &Add counter (%1) + red + + + + + yellow - &Remove counter (%1) + green - &Set counters (%1)... - - - - - &top of library + &Add counter (%1) - &bottom of library - - - - - &graveyard + &Remove counter (%1) - Ctrl+Del + &Set counters (%1)... - &exile + &top of library + + + + + &bottom of library + &graveyard + + + + + Ctrl+Del + + + + + &exile + + + + &Move to @@ -1203,94 +1208,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate - + &Join - - + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + J&oin as spectator diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 1e091cca1..100047e44 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -239,57 +239,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jugar - + &Hide &Ocultar - + &Tap &Girar - + &Untap &Enderezar - + Toggle &normal untapping Alternar enderezamiento &normal - + &Flip &Voltear - + &Clone &Clonar - + Ctrl+H Ctrl+H - + &Attach to card... Ane&xar a una carta... - + Ctrl+A Ctrl+A - + Unattac&h Desane&xar @@ -298,142 +298,147 @@ This is only saved for moderators and cannot be seen by the banned person.Establecer &F/R... - + + &Draw arrow... + + + + &Power / toughness &Fuerza / resistencia - + &Increase power &Incrementar fuerza - + Ctrl++ Ctrl++ - + &Decrease power &Decrementar fuerza - + Ctrl+- Ctrl+- - + I&ncrease toughness I&ncrementar resistencia - + Alt++ Alt++ - + D&ecrease toughness D&ecrementar resistencia - + Alt+- Alt+- - + In&crease power and toughness In&crementar fuerza y resistencia - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Dec&rementar fuerza y resistencia - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Establecer &fuerza y resistencia... - + Ctrl+P Ctrl+P - + &Set annotation... E&scribir anotación... - + red rojo - + yellow amarillo - + green verde - + &Add counter (%1) &Añadir contador (%1) - + &Remove counter (%1) &Quitar contador (%1) - + &Set counters (%1)... E&stablecer contadores (%1)... - + &top of library &parte superior de la biblioteca - + &bottom of library &fondo de la biblioteca - + &graveyard &cementerio - + Ctrl+Del Ctrl+Del - + &exile &exilio - + &Move to &Mover a @@ -1565,89 +1570,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate C&rear - + &Join E&ntrar - - + + Error Error - + Please join the appropriate room first. - + Wrong password. Contraseña incorrecta. - + Spectators are not allowed in this game. No se permiten espectadores en esta partida. - + The game is already full. La partida no tiene plazas libres. - + The game does not exist any more. La partida ya no existe. - + This game is only open to registered users. Esta partida está abierta sólo a usuarios registrados. - + This game is only open to its creator's buddies. Esta partida está abierta sólo a los amigos del creador. - + You are being ignored by the creator of this game. Estas siendo ignorado por el creador de la partida. - + Join game Entrar en la partida - + Password: Contraseña: - + Games Partidas - + Show &full games Ver partidas &sin plazas libres - + Show &running games @@ -1656,7 +1661,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Ver partidas sin plazas libres - + J&oin as spectator Entrar como e&spectador diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index a6c656f4c..3c10129ca 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -231,57 +231,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jouer - + &Hide &Cacher - + &Tap &Engager - + &Untap &Dégager - + Toggle &normal untapping Activer/ Désactiver le dégagement &normal - + &Flip &Retourner la carte - + &Clone &Copier une carte - + Ctrl+H - + &Attach to card... &Attacher à la carte... - + Ctrl+A Ctrl+A - + Unattac&h Détac&her @@ -290,142 +290,147 @@ This is only saved for moderators and cannot be seen by the banned person.Fixer &F/E... - + + &Draw arrow... + + + + &Power / toughness F&orce / Endurance - + &Increase power &Augmenter force - + Ctrl++ Ctrl++ - + &Decrease power &Diminuer force - + Ctrl+- Ctrl+- - + I&ncrease toughness A&ugmenter endurance - + Alt++ Alt++ - + D&ecrease toughness D&iminuer endurance - + Alt+- Alt+- - + In&crease power and toughness Au&gmenter la force et l'endurance - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Di&minuer la force et l'endurance - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Fi&xer la force et l'endurance... - + Ctrl+P Ctrl+P - + &Set annotation... A&jouter note... - + red rouge - + yellow jaune - + green vert - + &Add counter (%1) &Ajouter compteur (%1) - + &Remove counter (%1) &Retirer compteur (%1) - + &Set counters (%1)... &Fixer marqueurs (%1)... - + &top of library dessus de la &Bibliothèque - + &bottom of library &dessous de la bibliothèque - + &graveyard &cimetière - + Ctrl+Del Ctrl+Del - + &exile &exiler - + &Move to &Aller @@ -1415,79 +1420,79 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - + + Error Erreur - + Please join the appropriate room first. - + Wrong password. Mot de passe erroné. - + Spectators are not allowed in this game. Les spectateurs ne sont pas autorisés dans cette partie. - + The game is already full. Cette partie est déjà pleine. - + The game does not exist any more. La partie n'existe plus. - + This game is only open to registered users. Cette partie n'est accessible qu'aux joueurs enregistrés. - + This game is only open to its creator's buddies. Cette partie n'est accessible qu'aux amis. - + You are being ignored by the creator of this game. Vous avez été ignoré par le créateur de la partie. - + Join game Rejoindre partie - + Password: Mot de passe: - + Games Parties - + Show &full games Montrer &toutes les parties - + Show &running games @@ -1497,17 +1502,17 @@ This is only saved for moderators and cannot be seen by the banned person.&Montrer toutes les parties - + C&reate C&réer - + &Join Re&joindre - + J&oin as spectator Rej&oindre en tant que spectateur diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index 6d4c3aa93..5bd20b46a 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -235,58 +235,58 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play プレイ - + &Hide テスト版のため確認取れず再度チェック 裏にしてプレイ - + &Tap タップ - + &Untap アンタップ - + Toggle &normal untapping 通常のアンタップをしない - + &Flip 裏にする - + &Clone 複製する - + Ctrl+H - + &Attach to card... カードに付ける... - + Ctrl+A - + Unattac&h 取り外す @@ -295,142 +295,147 @@ This is only saved for moderators and cannot be seen by the banned person.P/Tを決める... - + + &Draw arrow... + + + + &Power / toughness パワー / タフネス - + &Increase power パワーを上げる - + Ctrl++ - + &Decrease power パワーを下げる - + Ctrl+- - + I&ncrease toughness タフネスを上げる - + Alt++ - + D&ecrease toughness タフネスを下げる - + Alt+- - + In&crease power and toughness パワーとタフネスを上げる - + Ctrl+Alt++ - + Dec&rease power and toughness パワーとタフネスを下げる - + Ctrl+Alt+- - + Set &power and toughness... パワーとタフネスを設定する... - + Ctrl+P - + &Set annotation... 注釈を付ける... - + red - + yellow - + green - + &Add counter (%1) カウンターを乗せる (%1) - + &Remove counter (%1) カウンターを取り除く (%1) - + &Set counters (%1)... カウンターの数を決める (%1)... - + &top of library ライブラリーの一番上へ - + &bottom of library ライブラリーの一番下へ - + &graveyard 墓地へ - + Ctrl+Del - + &exile 追放領域へ - + &Move to 移動させる @@ -1251,89 +1256,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate 部屋を作る - + &Join 参加する - - + + Error エラー - + Please join the appropriate room first. - + Wrong password. パスワードが間違っています. - + Spectators are not allowed in this game. この試合は観戦者は許可されていません. - + The game is already full. このゲームはすでに満員です. - + The game does not exist any more. このゲームはもう存在しません. - + This game is only open to registered users. このゲームは登録済みプレイヤーにのみ公開されています. - + This game is only open to its creator's buddies. このゲームは作成者のフレンドのみに公開されています. - + You are being ignored by the creator of this game. あなたはこのゲームの作成者によって拒否されています. - + Join game 参加 - + Password: パスワード: - + Games ゲーム - + Show &full games 全てのゲームを見る - + Show &running games @@ -1342,7 +1347,7 @@ This is only saved for moderators and cannot be seen by the banned person.全てのゲームを見る - + J&oin as spectator 観戦者として参加 diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 3ba27c1e7..2994392ac 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -230,197 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - - - &Power / toughness - - - - - &Increase power - - - - - Ctrl++ - - - &Decrease power + &Draw arrow... - Ctrl+- + &Power / toughness - I&ncrease toughness + &Increase power - Alt++ + Ctrl++ - D&ecrease toughness + &Decrease power - Alt+- + Ctrl+- - In&crease power and toughness + I&ncrease toughness - Ctrl+Alt++ + Alt++ - Dec&rease power and toughness + D&ecrease toughness - Ctrl+Alt+- + Alt+- - Set &power and toughness... + In&crease power and toughness - Ctrl+P + Ctrl+Alt++ - &Set annotation... + Dec&rease power and toughness + + + + + Ctrl+Alt+- - red + Set &power and toughness... - yellow + Ctrl+P - green + &Set annotation... - &Add counter (%1) + red + + + + + yellow - &Remove counter (%1) + green - &Set counters (%1)... - - - - - &top of library + &Add counter (%1) - &bottom of library - - - - - &graveyard + &Remove counter (%1) - Ctrl+Del + &Set counters (%1)... - &exile + &top of library + + + + + &bottom of library + &graveyard + + + + + Ctrl+Del + + + + + &exile + + + + &Move to @@ -1203,94 +1208,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + C&reate - + &Join - + J&oin as spectator diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 4f3707934..7f4c14cb9 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -235,57 +235,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jogar - + &Hide &Ocultar - + &Tap &Virar - + &Untap &Desvirar - + Toggle &normal untapping &Trocar o modo de desvirar - + &Flip Virar a &face - + &Clone Clo&nar - + Ctrl+H Ctrl+H - + &Attach to card... Ane&xar ao card... - + Ctrl+A Ctrl+A - + Unattac&h De&sanexar @@ -294,142 +294,147 @@ This is only saved for moderators and cannot be seen by the banned person.Alterar &P/R... - + + &Draw arrow... + + + + &Power / toughness Po&der / resistência - + &Increase power Au&mentar poder - + Ctrl++ Ctrl++ - + &Decrease power Dimi&nuir poder - + Ctrl+- Ctrl+- - + I&ncrease toughness A&umentar resistência - + Alt++ Alt++ - + D&ecrease toughness D&iminuir resistência - + Alt+- Alt+- - + In&crease power and toughness Aumen&tar poder e resistência - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Diminuir p&oder e resistência - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Alterar poder e resis&tência... - + Ctrl+P Ctrl+P - + &Set annotation... Alterar &nota... - + red vermelho - + yellow amarelo - + green verde - + &Add counter (%1) Adicionar &marcador (%1) - + &Remove counter (%1) &Remover marcador (%1) - + &Set counters (%1)... &Alterar marcadores (%1)... - + &top of library topo do &grimório - + &bottom of library &fundo do grimório - + &graveyard &cemitério - + Ctrl+Del Ctrl+Del - + &exile &exílio - + &Move to Mo&ver para @@ -1419,89 +1424,89 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate &Criar - + &Join &Entrar - - + + Error Erro - + Please join the appropriate room first. - + Wrong password. Senha incorreta. - + Spectators are not allowed in this game. Não são permitidos visitantes neste jogo. - + The game is already full. O jogo está cheio. - + The game does not exist any more. O jogo não existe mais. - + This game is only open to registered users. Este jogo é aberto apenas para usuários registrados. - + This game is only open to its creator's buddies. Este jogo é aberto apenas para os amigos de quem criou o jogo. - + You are being ignored by the creator of this game. Você está sendo ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Senha: - + Games Jogos - + Show &full games &Mostrar os jogos cheios - + Show &running games @@ -1510,7 +1515,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Mostrar os jogos cheios - + J&oin as spectator E&ntrar como visitante diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index a985f0b9d..d42405415 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -235,57 +235,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jogar - + &Hide Esco&nder - + &Tap &Virar - + &Untap Desv&irar - + Toggle &normal untapping A&lterar desvirar normalmente - + &Flip Vol&tar - + &Clone Copi&ar - + Ctrl+H Ctrl+H - + &Attach to card... Ane&xar a carta... - + Ctrl+A Ctrl+A - + Unattac&h De&sanexar @@ -294,142 +294,147 @@ This is only saved for moderators and cannot be seen by the banned person.Definir &P/R... - + + &Draw arrow... + + + + &Power / toughness &Poder / resistência - + &Increase power &Aumentar poder - + Ctrl++ Ctrl++ - + &Decrease power &Diminuir poder - + Ctrl+- Ctrl+- - + I&ncrease toughness A&umentar resistência - + Alt++ Alt++ - + D&ecrease toughness Di&minuir resistência - + Alt+- Alt+- - + In&crease power and toughness Aumen&tar poder e resistência - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Dimin&uir poder e resistência - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Definir &poder e resistência... - + Ctrl+P Ctrl+P - + &Set annotation... Colocar &nota... - + red vermelho - + yellow amarelo - + green verde - + &Add counter (%1) Adicionar &marcador (%1) - + &Remove counter (%1) &Remover marcador (%1) - + &Set counters (%1)... &Denifir marcadores (%1)... - + &top of library Topo do &grimório - + &bottom of library &Fundo do grimório - + &graveyard &Cemitério - + Ctrl+Del Ctrl+Del - + &exile &Exílio - + &Move to M&over para @@ -1419,79 +1424,79 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - + + Error Erro - + Please join the appropriate room first. - + Wrong password. Password incorrecta. - + Spectators are not allowed in this game. Não são permitidos espectadores neste jogo. - + The game is already full. O jogo já se encontra cheio. - + The game does not exist any more. O jogo já não existe. - + This game is only open to registered users. Este jogo só está aberto a utilizadores registados. - + This game is only open to its creator's buddies. Este jogo só está aberto aos amigos do seu criador. - + You are being ignored by the creator of this game. Você está a ser ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Password: - + Games Jogos - + Show &full games &Mostrar jogos cheios - + Show &running games @@ -1500,17 +1505,17 @@ This is only saved for moderators and cannot be seen by the banned person.&Mostrar jogos cheios - + C&reate &Criar - + &Join &Entrar - + J&oin as spectator Entrar como &espectador diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index ff02c2a11..b467a4e0c 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -231,57 +231,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Разыграть - + &Hide &Cкрыть - + &Tap &Повернуть - + &Untap &Развернуть - + Toggle &normal untapping (Не) &Разворачивать как обычно - + &Flip &Рубашкой вверх (вниз) - + &Clone &Клонировать - + Ctrl+H Ctrl+H - + &Attach to card... &Прикрепить к... - + Ctrl+A - + Unattac&h &Открепить @@ -290,142 +290,147 @@ This is only saved for moderators and cannot be seen by the banned person.Установить &Силу/Защиту... - + + &Draw arrow... + + + + &Power / toughness &Сила / защита - + &Increase power &Увеличить силу - + Ctrl++ - + &Decrease power У&меньшить силу - + Ctrl+- - + I&ncrease toughness У&величить защиту - + Alt++ - + D&ecrease toughness Уменьшить &защиту - + Alt+- - + In&crease power and toughness Увеличить силу &и защиту - + Ctrl+Alt++ - + Dec&rease power and toughness Уменьшить силу и за&щиту - + Ctrl+Alt+- - + Set &power and toughness... Уст&ановить силу / защиту... - + Ctrl+P - + &Set annotation... &Пометить... - + red Красный - + yellow Желтый - + green Зеленый - + &Add counter (%1) &Добавить жетон (%1) - + &Remove counter (%1) &Убрать жетон (%1) - + &Set counters (%1)... &Установить жетоны (%1)... - + &top of library &Наверх библиотеки - + &bottom of library &Вниз библиотеки - + &graveyard &На кладбище - + Ctrl+Del - + &exile &Изгнать - + &Move to &Переместить... @@ -1358,94 +1363,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - + + Error Ошибка - + Please join the appropriate room first. - + Wrong password. Неверный пароль. - + Spectators are not allowed in this game. В эту игру не пускают зрителей. - + The game is already full. Все места заняты! =Ь - + The game does not exist any more. Эта игра была удалена. - + This game is only open to registered users. Доступно только для зарегистрированных. - + This game is only open to its creator's buddies. Доступно только для друзей. - + You are being ignored by the creator of this game. Вы добавлены в игнор-лист данного игрока. - + Join game Присоединиться - + Password: Пароль: - + Games Игры - + Show &full games Показывать &текущие - + Show &running games - + C&reate С&оздать - + &Join &Присоединиться - + J&oin as spectator П&рисоединиться как зритель diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 1a1beeac1..59267fe5b 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -230,197 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - - - &Power / toughness - - - - - &Increase power - - - - - Ctrl++ - - - &Decrease power + &Draw arrow... - Ctrl+- + &Power / toughness - I&ncrease toughness + &Increase power - Alt++ + Ctrl++ - D&ecrease toughness + &Decrease power - Alt+- + Ctrl+- - In&crease power and toughness + I&ncrease toughness - Ctrl+Alt++ + Alt++ - Dec&rease power and toughness + D&ecrease toughness - Ctrl+Alt+- + Alt+- - Set &power and toughness... + In&crease power and toughness - Ctrl+P + Ctrl+Alt++ - &Set annotation... + Dec&rease power and toughness + + + + + Ctrl+Alt+- - red + Set &power and toughness... - yellow + Ctrl+P - green + &Set annotation... - &Add counter (%1) + red + + + + + yellow - &Remove counter (%1) + green - &Set counters (%1)... - - - - - &top of library + &Add counter (%1) - &bottom of library - - - - - &graveyard + &Remove counter (%1) - Ctrl+Del + &Set counters (%1)... - &exile + &top of library + + + + + &bottom of library + &graveyard + + + + + Ctrl+Del + + + + + &exile + + + + &Move to @@ -1203,94 +1208,94 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - - + + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + C&reate - + &Join - + J&oin as spectator From fccc91818d675a6f754764692c7146fd49d6521d Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 5 Jul 2011 21:33:03 +0200 Subject: [PATCH 80/87] chatview improvement --- cockatrice/src/chatview.cpp | 20 ++++- cockatrice/src/chatview.h | 5 +- cockatrice/src/messagelogwidget.cpp | 126 ++++++++++++---------------- cockatrice/src/messagelogwidget.h | 1 - 4 files changed, 76 insertions(+), 76 deletions(-) diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index 1b5b1e0f3..fba78601e 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -1,13 +1,12 @@ #include #include -#include #include #include #include #include "chatview.h" ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent) - : QTextBrowser(parent), ownName(_ownName), showTimestamps(_showTimestamps) + : QTextBrowser(parent), evenNumber(false), ownName(_ownName), showTimestamps(_showTimestamps) { setReadOnly(true); setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); @@ -15,15 +14,30 @@ ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *paren connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &))); } -void ChatView::appendMessage(QString sender, QString message, QColor playerColor, bool playerBold) +QTextCursor ChatView::prepareBlock() { QTextCursor cursor(document()->lastBlock()); cursor.movePosition(QTextCursor::End); QTextBlockFormat blockFormat; + if ((evenNumber = !evenNumber)) + blockFormat.setBackground(palette().alternateBase()); blockFormat.setBottomMargin(2); cursor.insertBlock(blockFormat); + return cursor; +} + +void ChatView::appendHtml(const QString &html) +{ + prepareBlock().insertHtml(html); + verticalScrollBar()->setValue(verticalScrollBar()->maximum()); +} + +void ChatView::appendMessage(QString sender, QString message, QColor playerColor, bool playerBold) +{ + QTextCursor cursor = prepareBlock(); + if (showTimestamps) { QTextCharFormat timeFormat; timeFormat.setForeground(Qt::black); diff --git a/cockatrice/src/chatview.h b/cockatrice/src/chatview.h index 5f9445323..1be076212 100644 --- a/cockatrice/src/chatview.h +++ b/cockatrice/src/chatview.h @@ -3,6 +3,7 @@ #include #include +#include #include class QTextTable; @@ -11,16 +12,18 @@ class QMouseEvent; class ChatView : public QTextBrowser { Q_OBJECT; private: - QTextTable *table; + bool evenNumber; QString ownName; bool showTimestamps; QTextFragment getFragmentUnderMouse(const QPoint &pos) const; QString getCardNameUnderMouse(QTextFragment frag) const; QString getCardNameUnderMouse(const QPoint &pos) const; + QTextCursor prepareBlock(); private slots: void openLink(const QUrl &link); public: ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent = 0); + void appendHtml(const QString &html); void appendMessage(QString sender, QString message, QColor playerColor = QColor(), bool playerBold = false); protected: void enterEvent(QEvent *event); diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 9b452bf84..8f18cdc84 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -13,20 +13,6 @@ QString MessageLogWidget::sanitizeHtml(QString dirty) const .replace(">", ">"); } -void MessageLogWidget::myAppend(const QString &message) -{ - QTextCursor cursor(document()->lastBlock()); - cursor.movePosition(QTextCursor::End); - - QTextBlockFormat blockFormat; - blockFormat.setBottomMargin(2); - cursor.insertBlock(blockFormat); - - cursor.insertHtml(message); - - verticalScrollBar()->setValue(verticalScrollBar()->maximum()); -} - bool MessageLogWidget::isFemale(Player *player) const { return player->getUserInfo()->getGender() == ServerInfo_User::Female; @@ -34,107 +20,107 @@ bool MessageLogWidget::isFemale(Player *player) const void MessageLogWidget::logConnecting(QString hostname) { - myAppend(tr("Connecting to %1...").arg(sanitizeHtml(hostname))); + appendHtml(tr("Connecting to %1...").arg(sanitizeHtml(hostname))); } void MessageLogWidget::logConnected() { - myAppend(tr("Connected.")); + appendHtml(tr("Connected.")); } void MessageLogWidget::logDisconnected() { - myAppend(tr("Disconnected from server.")); + appendHtml(tr("Disconnected from server.")); } void MessageLogWidget::logSocketError(const QString &errorString) { - myAppend(sanitizeHtml(errorString)); + appendHtml(sanitizeHtml(errorString)); } void MessageLogWidget::logServerError(ResponseCode response) { switch (response) { - case RespWrongPassword: myAppend(tr("Invalid password.")); break; + case RespWrongPassword: appendHtml(tr("Invalid password.")); break; default: ; } } void MessageLogWidget::logProtocolVersionMismatch(int clientVersion, int serverVersion) { - myAppend(tr("Protocol version mismatch. Client: %1, Server: %2").arg(clientVersion).arg(serverVersion)); + appendHtml(tr("Protocol version mismatch. Client: %1, Server: %2").arg(clientVersion).arg(serverVersion)); } void MessageLogWidget::logProtocolError() { - myAppend(tr("Protocol error.")); + appendHtml(tr("Protocol error.")); } void MessageLogWidget::logGameJoined(int gameId) { - myAppend(tr("You have joined game #%1.").arg(gameId)); + appendHtml(tr("You have joined game #%1.").arg(gameId)); } void MessageLogWidget::logJoin(Player *player) { soundEngine->cuckoo(); - myAppend(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logLeave(Player *player) { - myAppend(tr("%1 has left the game.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 has left the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logGameClosed() { - myAppend(tr("The game has been closed.")); + appendHtml(tr("The game has been closed.")); } void MessageLogWidget::logJoinSpectator(QString name) { - myAppend(tr("%1 is now watching the game.").arg(sanitizeHtml(name))); + appendHtml(tr("%1 is now watching the game.").arg(sanitizeHtml(name))); } void MessageLogWidget::logLeaveSpectator(QString name) { - myAppend(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name))); + appendHtml(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name))); } void MessageLogWidget::logDeckSelect(Player *player, int deckId) { if (deckId == -1) - myAppend(tr("%1 has loaded a local deck.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 has loaded a local deck.").arg(sanitizeHtml(player->getName()))); else - myAppend(tr("%1 has loaded deck #%2.").arg(sanitizeHtml(player->getName())).arg(deckId)); + appendHtml(tr("%1 has loaded deck #%2.").arg(sanitizeHtml(player->getName())).arg(deckId)); } void MessageLogWidget::logReadyStart(Player *player) { - myAppend(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logNotReadyStart(Player *player) { - myAppend(tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logConcede(Player *player) { - myAppend(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logGameStart() { - myAppend(tr("The game has started.")); + appendHtml(tr("The game has started.")); } void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState) { if (connectionState) - myAppend(tr("%1 has restored connection to the game.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 has restored connection to the game.").arg(sanitizeHtml(player->getName()))); else - myAppend(tr("%1 has lost connection to the game.").arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 has lost connection to the game.").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logSay(Player *player, QString message) @@ -151,12 +137,12 @@ void MessageLogWidget::logShuffle(Player *player, CardZone *zone) { soundEngine->shuffle(); if (currentContext != MessageContext_Mulligan) - myAppend(tr("%1 shuffles %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + appendHtml(tr("%1 shuffles %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); } void MessageLogWidget::logRollDie(Player *player, int sides, int roll) { - myAppend(tr("%1 rolls a %2 with a %3-sided die.").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides)); + appendHtml(tr("%1 rolls a %2 with a %3-sided die.").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides)); } void MessageLogWidget::logDrawCards(Player *player, int number) @@ -165,16 +151,16 @@ void MessageLogWidget::logDrawCards(Player *player, int number) mulliganPlayer = player; else { soundEngine->draw(); - myAppend(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); } } void MessageLogWidget::logUndoDraw(Player *player, QString cardName) { if (cardName.isEmpty()) - myAppend((isFemale(player) ? tr("%1 undoes her last draw.") : tr("%1 undoes his last draw.")).arg(sanitizeHtml(player->getName()))); + appendHtml((isFemale(player) ? tr("%1 undoes her last draw.") : tr("%1 undoes his last draw.")).arg(sanitizeHtml(player->getName()))); else - myAppend((isFemale(player) ? tr("%1 undoes her last draw (%2).") : tr("%1 undoes his last draw (%2).")).arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + appendHtml((isFemale(player) ? tr("%1 undoes her last draw (%2).") : tr("%1 undoes his last draw (%2).")).arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } QPair MessageLogWidget::getFromStr(CardZone *zone, QString cardName, int position) const @@ -239,7 +225,7 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes) cardStr = QString("%1").arg(sanitizeHtml(cardName)); if (attributes.startZone->getPlayer() != attributes.targetZone->getPlayer()) { - myAppend(tr("%1 gives %2 control over %3.").arg(sanitizeHtml(attributes.player->getName())).arg(sanitizeHtml(attributes.targetZone->getPlayer()->getName())).arg(cardStr)); + appendHtml(tr("%1 gives %2 control over %3.").arg(sanitizeHtml(attributes.player->getName())).arg(sanitizeHtml(attributes.targetZone->getPlayer()->getName())).arg(cardStr)); return; } @@ -272,7 +258,7 @@ void MessageLogWidget::doMoveCard(LogMoveCard &attributes) finalStr = tr("%1 plays %2%3."); } - myAppend(finalStr.arg(sanitizeHtml(attributes.player->getName())).arg(cardStr).arg(fromStr).arg(attributes.newX)); + appendHtml(finalStr.arg(sanitizeHtml(attributes.player->getName())).arg(cardStr).arg(fromStr).arg(attributes.newX)); } void MessageLogWidget::logMoveCard(Player *player, CardItem *card, CardZone *startZone, int oldX, CardZone *targetZone, int newX) @@ -292,50 +278,50 @@ void MessageLogWidget::logMulligan(Player *player, int number) return; if (number > -1) - myAppend(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); + appendHtml(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); else - myAppend((isFemale(player) ? tr("%1 draws her initial hand.") : tr("%1 draws his initial hand.")).arg(sanitizeHtml(player->getName()))); + appendHtml((isFemale(player) ? tr("%1 draws her initial hand.") : tr("%1 draws his initial hand.")).arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown) { if (faceDown) - myAppend(tr("%1 flips %2 face-down.").arg(sanitizeHtml(player->getName())).arg(cardName)); + appendHtml(tr("%1 flips %2 face-down.").arg(sanitizeHtml(player->getName())).arg(cardName)); else - myAppend(tr("%1 flips %2 face-up.").arg(sanitizeHtml(player->getName())).arg(cardName)); + appendHtml(tr("%1 flips %2 face-up.").arg(sanitizeHtml(player->getName())).arg(cardName)); } void MessageLogWidget::logDestroyCard(Player *player, QString cardName) { - myAppend(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + appendHtml(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName) { - myAppend(tr("%1 attaches %2 to %3's %4.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("%1").arg(sanitizeHtml(targetCardName)))); + appendHtml(tr("%1 attaches %2 to %3's %4.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("%1").arg(sanitizeHtml(targetCardName)))); } void MessageLogWidget::logUnattachCard(Player *player, QString cardName) { - myAppend(tr("%1 unattaches %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + appendHtml(tr("%1 unattaches %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt) { - myAppend(tr("%1 creates token: %2%3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); + appendHtml(tr("%1 creates token: %2%3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); } void MessageLogWidget::logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard, bool playerTarget) { if (playerTarget) - myAppend(tr("%1 points from %2's %3 to %4.") + appendHtml(tr("%1 points from %2's %3 to %4.") .arg(sanitizeHtml(player->getName())) .arg(sanitizeHtml(startPlayer->getName())) .arg(sanitizeHtml(startCard)) .arg(sanitizeHtml(targetPlayer->getName())) ); else - myAppend(tr("%1 points from %2's %3 to %4's %5.") + appendHtml(tr("%1 points from %2's %3 to %4's %5.") .arg(sanitizeHtml(player->getName())) .arg(sanitizeHtml(startPlayer->getName())) .arg(sanitizeHtml(startCard)) @@ -361,7 +347,7 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c default: ; } - myAppend(finalStr.arg(sanitizeHtml(player->getName())).arg(colorStr).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(value)); + appendHtml(finalStr.arg(sanitizeHtml(player->getName())).arg(colorStr).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(value)); } void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) @@ -379,13 +365,13 @@ void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) cardStr = isFemale(player) ? tr("her permanents") : tr("his permanents"); else cardStr = QString("%1").arg(sanitizeHtml(card->getName())); - myAppend(tr("%1 %2 %3.").arg(sanitizeHtml(player->getName())).arg(tapped ? tr("taps") : tr("untaps")).arg(cardStr)); + appendHtml(tr("%1 %2 %3.").arg(sanitizeHtml(player->getName())).arg(tapped ? tr("taps") : tr("untaps")).arg(cardStr)); } } void MessageLogWidget::logSetCounter(Player *player, QString counterName, int value, int oldValue) { - myAppend(tr("%1 sets counter %2 to %3 (%4%5).").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(counterName))).arg(QString("%1").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue)); + appendHtml(tr("%1 sets counter %2 to %3 (%4%5).").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(counterName))).arg(QString("%1").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue)); } void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap) @@ -395,7 +381,7 @@ void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool do finalStr = tr("%1 sets %2 to not untap normally."); else finalStr = tr("%1 sets %2 to untap normally."); - myAppend(finalStr.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName())))); + appendHtml(finalStr.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName())))); } void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT) @@ -403,26 +389,26 @@ void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT) if (currentContext == MessageContext_MoveCard) moveCardPT.insert(card, newPT); else - myAppend(tr("%1 sets PT of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newPT)))); + appendHtml(tr("%1 sets PT of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newPT)))); } void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString newAnnotation) { - myAppend(tr("%1 sets annotation of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newAnnotation)))); + appendHtml(tr("%1 sets annotation of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newAnnotation)))); } void MessageLogWidget::logDumpZone(Player *player, CardZone *zone, int numberCards) { if (numberCards != -1) - myAppend(tr("%1 is looking at the top %2 cards %3.").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive))); + appendHtml(tr("%1 is looking at the top %2 cards %3.").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive))); else - myAppend(tr("%1 is looking at %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative))); + appendHtml(tr("%1 is looking at %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative))); } void MessageLogWidget::logStopDumpZone(Player *player, CardZone *zone) { QString zoneName = zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative); - myAppend(tr("%1 stops looking at %2.").arg(sanitizeHtml(player->getName())).arg(zoneName)); + appendHtml(tr("%1 stops looking at %2.").arg(sanitizeHtml(player->getName())).arg(zoneName)); } void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer) @@ -445,28 +431,26 @@ void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId if (cardId == -1) { if (otherPlayer) - myAppend(tr("%1 reveals %2 to %3.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName()))); + appendHtml(tr("%1 reveals %2 to %3.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName()))); else - myAppend(tr("%1 reveals %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + appendHtml(tr("%1 reveals %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); } else if (cardId == -2) { if (otherPlayer) - myAppend(tr("%1 randomly reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); + appendHtml(tr("%1 randomly reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); else - myAppend(tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + appendHtml(tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); } else { if (otherPlayer) - myAppend(tr("%1 reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); + appendHtml(tr("%1 reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); else - myAppend(tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + appendHtml(tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); } } void MessageLogWidget::logSetActivePlayer(Player *player) { soundEngine->notification(); - myAppend(QString()); - myAppend("" + tr("It is now %1's turn.").arg(player->getName()) + ""); - myAppend(QString()); + appendHtml("
" + tr("It is now %1's turn.").arg(player->getName()) + "
"); } void MessageLogWidget::logSetActivePhase(int phase) @@ -486,7 +470,7 @@ void MessageLogWidget::logSetActivePhase(int phase) case 9: phaseName = tr("second main phase"); break; case 10: phaseName = tr("ending phase"); break; } - myAppend("" + tr("It is now the %1.").arg(phaseName) + ""); + appendHtml("" + tr("It is now the %1.").arg(phaseName) + ""); } void MessageLogWidget::containerProcessingStarted(GameEventContext *_context) diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index c99851af0..698489656 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -28,7 +28,6 @@ private: enum MessageContext { MessageContext_None, MessageContext_MoveCard, MessageContext_Mulligan }; QString sanitizeHtml(QString dirty) const; - void myAppend(const QString &message); bool isFemale(Player *player) const; QPair getFromStr(CardZone *zone, QString cardName, int position) const; MessageContext currentContext; From 09d0e65d1d71393ec0a4298bb9d7f4b7970b9755 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Tue, 5 Jul 2011 22:40:03 +0200 Subject: [PATCH 81/87] more visual improvements --- cockatrice/src/chatview.cpp | 31 +++++++++++++++++++++---------- cockatrice/src/chatview.h | 3 ++- cockatrice/src/gameselector.cpp | 1 + cockatrice/src/userlist.cpp | 1 + 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/cockatrice/src/chatview.cpp b/cockatrice/src/chatview.cpp index fba78601e..9aecfd1ee 100644 --- a/cockatrice/src/chatview.cpp +++ b/cockatrice/src/chatview.cpp @@ -6,7 +6,7 @@ #include "chatview.h" ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent) - : QTextBrowser(parent), evenNumber(false), ownName(_ownName), showTimestamps(_showTimestamps) + : QTextBrowser(parent), evenNumber(true), ownName(_ownName), showTimestamps(_showTimestamps) { setReadOnly(true); setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); @@ -14,16 +14,20 @@ ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *paren connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &))); } -QTextCursor ChatView::prepareBlock() +QTextCursor ChatView::prepareBlock(bool same) { + lastSender.clear(); + QTextCursor cursor(document()->lastBlock()); cursor.movePosition(QTextCursor::End); - - QTextBlockFormat blockFormat; - if ((evenNumber = !evenNumber)) - blockFormat.setBackground(palette().alternateBase()); - blockFormat.setBottomMargin(2); - cursor.insertBlock(blockFormat); + if (!same) { + QTextBlockFormat blockFormat; + if ((evenNumber = !evenNumber)) + blockFormat.setBackground(palette().alternateBase()); + blockFormat.setBottomMargin(2); + cursor.insertBlock(blockFormat); + } else + cursor.insertHtml("
"); return cursor; } @@ -36,11 +40,16 @@ void ChatView::appendHtml(const QString &html) void ChatView::appendMessage(QString sender, QString message, QColor playerColor, bool playerBold) { - QTextCursor cursor = prepareBlock(); + bool sameSender = (sender == lastSender) && !lastSender.isEmpty(); + QTextCursor cursor = prepareBlock(sameSender); + lastSender = sender; if (showTimestamps) { QTextCharFormat timeFormat; - timeFormat.setForeground(Qt::black); + if (sameSender) + timeFormat.setForeground(Qt::transparent); + else + timeFormat.setForeground(Qt::black); cursor.setCharFormat(timeFormat); cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] ")); } @@ -57,6 +66,8 @@ void ChatView::appendMessage(QString sender, QString message, QColor playerColor if (playerBold) senderFormat.setFontWeight(QFont::Bold); } + if (sameSender) + senderFormat.setForeground(Qt::transparent); cursor.setCharFormat(senderFormat); if (!sender.isEmpty()) sender.append(": "); diff --git a/cockatrice/src/chatview.h b/cockatrice/src/chatview.h index 1be076212..33c583c68 100644 --- a/cockatrice/src/chatview.h +++ b/cockatrice/src/chatview.h @@ -12,13 +12,14 @@ class QMouseEvent; class ChatView : public QTextBrowser { Q_OBJECT; private: + QString lastSender; bool evenNumber; QString ownName; bool showTimestamps; QTextFragment getFragmentUnderMouse(const QPoint &pos) const; QString getCardNameUnderMouse(QTextFragment frag) const; QString getCardNameUnderMouse(const QPoint &pos) const; - QTextCursor prepareBlock(); + QTextCursor prepareBlock(bool same = false); private slots: void openLink(const QUrl &link); public: diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 9c165d269..1feb63d07 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -22,6 +22,7 @@ GameSelector::GameSelector(AbstractClient *_client, TabRoom *_room, const QMapsetSortCaseSensitivity(Qt::CaseInsensitive); gameListView->setModel(gameListProxyModel); gameListView->setSortingEnabled(true); + gameListView->setAlternatingRowColors(true); if (_room) gameListView->header()->hideSection(0); gameListView->header()->setResizeMode(1, QHeaderView::ResizeToContents); diff --git a/cockatrice/src/userlist.cpp b/cockatrice/src/userlist.cpp index 20b60992d..71101f481 100644 --- a/cockatrice/src/userlist.cpp +++ b/cockatrice/src/userlist.cpp @@ -107,6 +107,7 @@ UserList::UserList(TabSupervisor *_tabSupervisor, AbstractClient *_client, UserL userTree->setRootIsDecorated(false); userTree->setIconSize(QSize(20, 12)); userTree->setItemDelegate(itemDelegate); + userTree->setAlternatingRowColors(true); connect(userTree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, SLOT(userClicked(QTreeWidgetItem *, int))); QVBoxLayout *vbox = new QVBoxLayout; From 9090bc333cefa3d91f957c13c6a2f7e1a1eaba10 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 6 Jul 2011 01:22:09 +0200 Subject: [PATCH 82/87] new phase buttons by capthauq --- .../resources/phases/icon_phase_cleanup.svg | 935 ++------ .../phases/icon_phase_combat_attackers.svg | 265 +-- .../phases/icon_phase_combat_blockers.svg | 2111 +++++++++++++++-- .../phases/icon_phase_combat_damage.svg | 277 +-- .../phases/icon_phase_combat_end.svg | 572 +++-- .../phases/icon_phase_combat_start.svg | 601 +++-- .../resources/phases/icon_phase_draw.svg | 382 ++- .../resources/phases/icon_phase_main1.svg | 214 +- .../resources/phases/icon_phase_main2.svg | 370 +-- .../resources/phases/icon_phase_nextturn.svg | 191 +- .../resources/phases/icon_phase_untap.svg | 318 +-- .../resources/phases/icon_phase_upkeep.svg | 321 +-- .../phases_old/icon_phase_cleanup.svg | 749 ++++++ .../icon_phase_combat_attackers.svg | 162 ++ .../phases_old/icon_phase_combat_blockers.svg | 181 ++ .../phases_old/icon_phase_combat_damage.svg | 169 ++ .../phases_old/icon_phase_combat_end.svg | 253 ++ .../phases_old/icon_phase_combat_start.svg | 253 ++ .../resources/phases_old/icon_phase_draw.svg | 192 ++ .../resources/phases_old/icon_phase_main1.svg | 135 ++ .../resources/phases_old/icon_phase_main2.svg | 135 ++ .../phases_old/icon_phase_nextturn.svg | 89 + .../resources/phases_old/icon_phase_untap.svg | 198 ++ .../phases_old/icon_phase_upkeep.svg | 159 ++ 24 files changed, 6557 insertions(+), 2675 deletions(-) create mode 100644 cockatrice/resources/phases_old/icon_phase_cleanup.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_combat_attackers.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_combat_blockers.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_combat_damage.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_combat_end.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_combat_start.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_draw.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_main1.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_main2.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_nextturn.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_untap.svg create mode 100644 cockatrice/resources/phases_old/icon_phase_upkeep.svg diff --git a/cockatrice/resources/phases/icon_phase_cleanup.svg b/cockatrice/resources/phases/icon_phase_cleanup.svg index a675d66f5..9786daca9 100644 --- a/cockatrice/resources/phases/icon_phase_cleanup.svg +++ b/cockatrice/resources/phases/icon_phase_cleanup.svg @@ -1,749 +1,186 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_combat_attackers.svg b/cockatrice/resources/phases/icon_phase_combat_attackers.svg index 540107ac2..d74832536 100644 --- a/cockatrice/resources/phases/icon_phase_combat_attackers.svg +++ b/cockatrice/resources/phases/icon_phase_combat_attackers.svg @@ -1,162 +1,103 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_combat_blockers.svg b/cockatrice/resources/phases/icon_phase_combat_blockers.svg index 6344ef6b3..6602eaef0 100644 --- a/cockatrice/resources/phases/icon_phase_combat_blockers.svg +++ b/cockatrice/resources/phases/icon_phase_combat_blockers.svg @@ -1,181 +1,1930 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_combat_damage.svg b/cockatrice/resources/phases/icon_phase_combat_damage.svg index 8536764e8..aa356e2a9 100644 --- a/cockatrice/resources/phases/icon_phase_combat_damage.svg +++ b/cockatrice/resources/phases/icon_phase_combat_damage.svg @@ -1,169 +1,108 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_combat_end.svg b/cockatrice/resources/phases/icon_phase_combat_end.svg index 9e7b8950b..bbbbf9bff 100644 --- a/cockatrice/resources/phases/icon_phase_combat_end.svg +++ b/cockatrice/resources/phases/icon_phase_combat_end.svg @@ -1,253 +1,319 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_combat_start.svg b/cockatrice/resources/phases/icon_phase_combat_start.svg index 996571d71..b80b571dc 100644 --- a/cockatrice/resources/phases/icon_phase_combat_start.svg +++ b/cockatrice/resources/phases/icon_phase_combat_start.svg @@ -1,253 +1,348 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_draw.svg b/cockatrice/resources/phases/icon_phase_draw.svg index 51918274c..4d1062199 100644 --- a/cockatrice/resources/phases/icon_phase_draw.svg +++ b/cockatrice/resources/phases/icon_phase_draw.svg @@ -1,192 +1,190 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_main1.svg b/cockatrice/resources/phases/icon_phase_main1.svg index 264cef395..48fce651b 100644 --- a/cockatrice/resources/phases/icon_phase_main1.svg +++ b/cockatrice/resources/phases/icon_phase_main1.svg @@ -1,135 +1,79 @@ - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_main2.svg b/cockatrice/resources/phases/icon_phase_main2.svg index 50f77fa70..61be736ef 100644 --- a/cockatrice/resources/phases/icon_phase_main2.svg +++ b/cockatrice/resources/phases/icon_phase_main2.svg @@ -1,135 +1,235 @@ - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_nextturn.svg b/cockatrice/resources/phases/icon_phase_nextturn.svg index 3cfd19ab0..302a57d67 100644 --- a/cockatrice/resources/phases/icon_phase_nextturn.svg +++ b/cockatrice/resources/phases/icon_phase_nextturn.svg @@ -1,89 +1,102 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_untap.svg b/cockatrice/resources/phases/icon_phase_untap.svg index 2f4d81732..3d316ab04 100644 --- a/cockatrice/resources/phases/icon_phase_untap.svg +++ b/cockatrice/resources/phases/icon_phase_untap.svg @@ -1,198 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases/icon_phase_upkeep.svg b/cockatrice/resources/phases/icon_phase_upkeep.svg index 5a06aae9c..2317a9379 100644 --- a/cockatrice/resources/phases/icon_phase_upkeep.svg +++ b/cockatrice/resources/phases/icon_phase_upkeep.svg @@ -1,159 +1,162 @@ - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_cleanup.svg b/cockatrice/resources/phases_old/icon_phase_cleanup.svg new file mode 100644 index 000000000..a675d66f5 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_cleanup.svg @@ -0,0 +1,749 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_combat_attackers.svg b/cockatrice/resources/phases_old/icon_phase_combat_attackers.svg new file mode 100644 index 000000000..540107ac2 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_combat_attackers.svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_combat_blockers.svg b/cockatrice/resources/phases_old/icon_phase_combat_blockers.svg new file mode 100644 index 000000000..6344ef6b3 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_combat_blockers.svg @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_combat_damage.svg b/cockatrice/resources/phases_old/icon_phase_combat_damage.svg new file mode 100644 index 000000000..8536764e8 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_combat_damage.svg @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_combat_end.svg b/cockatrice/resources/phases_old/icon_phase_combat_end.svg new file mode 100644 index 000000000..9e7b8950b --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_combat_end.svg @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_combat_start.svg b/cockatrice/resources/phases_old/icon_phase_combat_start.svg new file mode 100644 index 000000000..996571d71 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_combat_start.svg @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_draw.svg b/cockatrice/resources/phases_old/icon_phase_draw.svg new file mode 100644 index 000000000..51918274c --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_draw.svg @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_main1.svg b/cockatrice/resources/phases_old/icon_phase_main1.svg new file mode 100644 index 000000000..264cef395 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_main1.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_main2.svg b/cockatrice/resources/phases_old/icon_phase_main2.svg new file mode 100644 index 000000000..50f77fa70 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_main2.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_nextturn.svg b/cockatrice/resources/phases_old/icon_phase_nextturn.svg new file mode 100644 index 000000000..3cfd19ab0 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_nextturn.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_untap.svg b/cockatrice/resources/phases_old/icon_phase_untap.svg new file mode 100644 index 000000000..2f4d81732 --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_untap.svg @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/cockatrice/resources/phases_old/icon_phase_upkeep.svg b/cockatrice/resources/phases_old/icon_phase_upkeep.svg new file mode 100644 index 000000000..5a06aae9c --- /dev/null +++ b/cockatrice/resources/phases_old/icon_phase_upkeep.svg @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + From f10d9c9bec168529a56d976e3667591600589b30 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Wed, 6 Jul 2011 18:45:56 +0200 Subject: [PATCH 83/87] strip newlines from msg in cmdRoomSay; improved i18n in MessageLogWidget --- cockatrice/src/messagelogwidget.cpp | 506 +++++-- cockatrice/src/messagelogwidget.h | 10 +- cockatrice/src/tab_game.cpp | 4 +- cockatrice/src/tab_game.h | 2 +- cockatrice/src/tab_supervisor.cpp | 24 +- cockatrice/src/tab_supervisor.h | 5 +- cockatrice/translations/cockatrice_cs.ts | 1224 +++++++++++----- cockatrice/translations/cockatrice_de.ts | 1184 +++++++++++++--- cockatrice/translations/cockatrice_en.ts | 1251 ++++++++++++----- cockatrice/translations/cockatrice_es.ts | 1209 ++++++++++++---- cockatrice/translations/cockatrice_fr.ts | 1393 ++++++++++++++----- cockatrice/translations/cockatrice_ja.ts | 1222 +++++++++++----- cockatrice/translations/cockatrice_pl.ts | 1224 +++++++++++----- cockatrice/translations/cockatrice_pt-br.ts | 1209 ++++++++++++---- cockatrice/translations/cockatrice_pt.ts | 1187 ++++++++++++---- cockatrice/translations/cockatrice_ru.ts | 1218 ++++++++++++---- cockatrice/translations/cockatrice_sk.ts | 1224 +++++++++++----- common/server_protocolhandler.cpp | 3 +- 18 files changed, 10655 insertions(+), 3444 deletions(-) diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index 8f18cdc84..98b61c907 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -18,58 +18,29 @@ bool MessageLogWidget::isFemale(Player *player) const return player->getUserInfo()->getGender() == ServerInfo_User::Female; } -void MessageLogWidget::logConnecting(QString hostname) -{ - appendHtml(tr("Connecting to %1...").arg(sanitizeHtml(hostname))); -} - -void MessageLogWidget::logConnected() -{ - appendHtml(tr("Connected.")); -} - -void MessageLogWidget::logDisconnected() -{ - appendHtml(tr("Disconnected from server.")); -} - -void MessageLogWidget::logSocketError(const QString &errorString) -{ - appendHtml(sanitizeHtml(errorString)); -} - -void MessageLogWidget::logServerError(ResponseCode response) -{ - switch (response) { - case RespWrongPassword: appendHtml(tr("Invalid password.")); break; - default: ; - } -} - -void MessageLogWidget::logProtocolVersionMismatch(int clientVersion, int serverVersion) -{ - appendHtml(tr("Protocol version mismatch. Client: %1, Server: %2").arg(clientVersion).arg(serverVersion)); -} - -void MessageLogWidget::logProtocolError() -{ - appendHtml(tr("Protocol error.")); -} - void MessageLogWidget::logGameJoined(int gameId) { - appendHtml(tr("You have joined game #%1.").arg(gameId)); + if (female) + appendHtml(tr("You have joined game #%1.", "female").arg(gameId)); + else + appendHtml(tr("You have joined game #%1.", "male").arg(gameId)); } void MessageLogWidget::logJoin(Player *player) { soundEngine->cuckoo(); - appendHtml(tr("%1 has joined the game.").arg(sanitizeHtml(player->getName()))); + if (isFemale(player)) + appendHtml(tr("%1 has joined the game.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 has joined the game.", "male").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logLeave(Player *player) { - appendHtml(tr("%1 has left the game.").arg(sanitizeHtml(player->getName()))); + if (isFemale(player)) + appendHtml(tr("%1 has left the game.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 has left the game.", "male").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logGameClosed() @@ -89,25 +60,41 @@ void MessageLogWidget::logLeaveSpectator(QString name) void MessageLogWidget::logDeckSelect(Player *player, int deckId) { - if (deckId == -1) - appendHtml(tr("%1 has loaded a local deck.").arg(sanitizeHtml(player->getName()))); - else - appendHtml(tr("%1 has loaded deck #%2.").arg(sanitizeHtml(player->getName())).arg(deckId)); + if (deckId == -1) { + if (isFemale(player)) + appendHtml(tr("%1 has loaded a local deck.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 has loaded a local deck.", "male").arg(sanitizeHtml(player->getName()))); + } else { + if (isFemale(player)) + appendHtml(tr("%1 has loaded deck #%2.", "female").arg(sanitizeHtml(player->getName())).arg(deckId)); + else + appendHtml(tr("%1 has loaded deck #%2.", "male").arg(sanitizeHtml(player->getName())).arg(deckId)); + } } void MessageLogWidget::logReadyStart(Player *player) { - appendHtml(tr("%1 is ready to start the game.").arg(sanitizeHtml(player->getName()))); + if (isFemale(player)) + appendHtml(tr("%1 is ready to start the game.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 is ready to start the game.", "male").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logNotReadyStart(Player *player) { - appendHtml(tr("%1 is not ready to start the game any more.").arg(sanitizeHtml(player->getName()))); + if (isFemale(player)) + appendHtml(tr("%1 is not ready to start the game any more.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 is not ready to start the game any more.", "male").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logConcede(Player *player) { - appendHtml(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName()))); + if (isFemale(player)) + appendHtml(tr("%1 has conceded the game.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 has conceded the game.", "male").arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logGameStart() @@ -117,10 +104,17 @@ void MessageLogWidget::logGameStart() void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState) { - if (connectionState) - appendHtml(tr("%1 has restored connection to the game.").arg(sanitizeHtml(player->getName()))); - else - appendHtml(tr("%1 has lost connection to the game.").arg(sanitizeHtml(player->getName()))); + if (connectionState) { + if (isFemale(player)) + appendHtml(tr("%1 has restored connection to the game.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 has restored connection to the game.", "male").arg(sanitizeHtml(player->getName()))); + } else { + if (isFemale(player)) + appendHtml(tr("%1 has lost connection to the game.", "female").arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 has lost connection to the game.", "male").arg(sanitizeHtml(player->getName()))); + } } void MessageLogWidget::logSay(Player *player, QString message) @@ -136,13 +130,20 @@ void MessageLogWidget::logSpectatorSay(QString spectatorName, QString message) void MessageLogWidget::logShuffle(Player *player, CardZone *zone) { soundEngine->shuffle(); - if (currentContext != MessageContext_Mulligan) - appendHtml(tr("%1 shuffles %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + if (currentContext != MessageContext_Mulligan) { + if (isFemale(player)) + appendHtml(tr("%1 shuffles %2.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + else + appendHtml(tr("%1 shuffles %2.", "male").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + } } void MessageLogWidget::logRollDie(Player *player, int sides, int roll) { - appendHtml(tr("%1 rolls a %2 with a %3-sided die.").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides)); + if (isFemale(player)) + appendHtml(tr("%1 rolls a %2 with a %3-sided die.", "female").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides)); + else + appendHtml(tr("%1 rolls a %2 with a %3-sided die.", "male").arg(sanitizeHtml(player->getName())).arg(roll).arg(sides)); } void MessageLogWidget::logDrawCards(Player *player, int number) @@ -151,7 +152,10 @@ void MessageLogWidget::logDrawCards(Player *player, int number) mulliganPlayer = player; else { soundEngine->draw(); - appendHtml(tr("%1 draws %n card(s).", "", number).arg(sanitizeHtml(player->getName()))); + if (isFemale(player)) + appendHtml(tr("%1 draws %n card(s).", "female", number).arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 draws %n card(s).", "male", number).arg(sanitizeHtml(player->getName()))); } } @@ -277,57 +281,200 @@ void MessageLogWidget::logMulligan(Player *player, int number) if (!player) return; - if (number > -1) - appendHtml(tr("%1 takes a mulligan to %n.", "", number).arg(sanitizeHtml(player->getName()))); - else + if (number > -1) { + if (isFemale(player)) + appendHtml(tr("%1 takes a mulligan to %n.", "female", number).arg(sanitizeHtml(player->getName()))); + else + appendHtml(tr("%1 takes a mulligan to %n.", "male", number).arg(sanitizeHtml(player->getName()))); + } else appendHtml((isFemale(player) ? tr("%1 draws her initial hand.") : tr("%1 draws his initial hand.")).arg(sanitizeHtml(player->getName()))); } void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown) { - if (faceDown) - appendHtml(tr("%1 flips %2 face-down.").arg(sanitizeHtml(player->getName())).arg(cardName)); - else - appendHtml(tr("%1 flips %2 face-up.").arg(sanitizeHtml(player->getName())).arg(cardName)); + if (faceDown) { + if (isFemale(player)) + appendHtml(tr("%1 flips %2 face-down.", "female").arg(sanitizeHtml(player->getName())).arg(cardName)); + else + appendHtml(tr("%1 flips %2 face-down.", "male").arg(sanitizeHtml(player->getName())).arg(cardName)); + } else { + if (isFemale(player)) + appendHtml(tr("%1 flips %2 face-up.", "female").arg(sanitizeHtml(player->getName())).arg(cardName)); + else + appendHtml(tr("%1 flips %2 face-up.", "male").arg(sanitizeHtml(player->getName())).arg(cardName)); + } } void MessageLogWidget::logDestroyCard(Player *player, QString cardName) { - appendHtml(tr("%1 destroys %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + if (isFemale(player)) + appendHtml(tr("%1 destroys %2.", "female").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + else + appendHtml(tr("%1 destroys %2.", "male").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName) { - appendHtml(tr("%1 attaches %2 to %3's %4.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("%1").arg(sanitizeHtml(targetCardName)))); + QString str; + if (isFemale(player)) { + if (isFemale(targetPlayer)) + str = tr("%1 attaches %2 to %3's %4.", "p1 female, p2 female"); + else + str = tr("%1 attaches %2 to %3's %4.", "p1 female, p2 male"); + } else { + if (isFemale(targetPlayer)) + str = tr("%1 attaches %2 to %3's %4.", "p1 male, p2 female"); + else + str = tr("%1 attaches %2 to %3's %4.", "p1 male, p2 male"); + } + + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(sanitizeHtml(targetPlayer->getName())).arg(QString("%1").arg(sanitizeHtml(targetCardName)))); } void MessageLogWidget::logUnattachCard(Player *player, QString cardName) { - appendHtml(tr("%1 unattaches %2.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + if (isFemale(player)) + appendHtml(tr("%1 unattaches %2.", "female").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); + else + appendHtml(tr("%1 unattaches %2.", "male").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName)))); } void MessageLogWidget::logCreateToken(Player *player, QString cardName, QString pt) { - appendHtml(tr("%1 creates token: %2%3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); + if (isFemale(player)) + appendHtml(tr("%1 creates token: %2%3.", "female").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); + else + appendHtml(tr("%1 creates token: %2%3.", "male").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(cardName))).arg(pt.isEmpty() ? QString() : QString(" (%1)").arg(sanitizeHtml(pt)))); } void MessageLogWidget::logCreateArrow(Player *player, Player *startPlayer, QString startCard, Player *targetPlayer, QString targetCard, bool playerTarget) { - if (playerTarget) - appendHtml(tr("%1 points from %2's %3 to %4.") - .arg(sanitizeHtml(player->getName())) - .arg(sanitizeHtml(startPlayer->getName())) - .arg(sanitizeHtml(startCard)) - .arg(sanitizeHtml(targetPlayer->getName())) - ); - else - appendHtml(tr("%1 points from %2's %3 to %4's %5.") - .arg(sanitizeHtml(player->getName())) - .arg(sanitizeHtml(startPlayer->getName())) - .arg(sanitizeHtml(startCard)) - .arg(sanitizeHtml(targetPlayer->getName())) - .arg(sanitizeHtml(targetCard)) - ); + startCard = QString("%1").arg(sanitizeHtml(startCard)); + targetCard = QString("%1").arg(sanitizeHtml(targetCard)); + QString str; + if (playerTarget) { + if ((player == startPlayer) && (player == targetPlayer)) { + if (isFemale(player)) + str = tr("%1 points from her %2 to herself.", "female"); + else + str = tr("%1 points from his %2 to himself.", "male"); + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard)); + } else if (player == startPlayer) { + if (isFemale(player)) { + if (isFemale(targetPlayer)) + str = tr("%1 points from her %2 to %3.", "p1 female, p2 female"); + else + str = tr("%1 points from her %2 to %3.", "p1 female, p2 male"); + } else { + if (isFemale(targetPlayer)) + str = tr("%1 points from his %2 to %3.", "p1 male, p2 female"); + else + str = tr("%1 points from his %2 to %3.", "p1 male, p2 male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName()))); + } else if (player == targetPlayer) { + if (isFemale(player)) { + if (isFemale(startPlayer)) + str = tr("%1 points from %2's %3 to herself.", "card owner female, target female"); + else + str = tr("%1 points from %2's %3 to herself.", "card owner male, target female"); + } else { + if (isFemale(startPlayer)) + str = tr("%1 points from %2's %3 to himself.", "card owner female, target male"); + else + str = tr("%1 points from %2's %3 to himself.", "card owner male, target male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard)); + } else { + if (isFemale(player)) { + if (isFemale(startPlayer)) { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 female, p3 female"); + else + str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 female, p3 male"); + } else { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 male, p3 female"); + else + str = tr("%1 points from %2's %3 to %4.", "p1 female, p2 male, p3 male"); + } + } else { + if (isFemale(startPlayer)) { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 female, p3 female"); + else + str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 female, p3 male"); + } else { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 male, p3 female"); + else + str = tr("%1 points from %2's %3 to %4.", "p1 male, p2 male, p3 male"); + } + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName()))); + } + } else { + if ((player == startPlayer) && (player == targetPlayer)) { + if (isFemale(player)) + str = tr("%1 points from her %2 to her %3.", "female"); + else + str = tr("%1 points from his %2 to his %3.", "male"); + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard).arg(targetCard)); + } else if (player == startPlayer) { + if (isFemale(player)) { + if (isFemale(targetPlayer)) + str = tr("%1 points from her %2 to %3's %4.", "p1 female, p2 female"); + else + str = tr("%1 points from her %2 to %3's %4.", "p1 female, p2 male"); + } else { + if (isFemale(targetPlayer)) + str = tr("%1 points from his %2 to %3's %4.", "p1 male, p2 female"); + else + str = tr("%1 points from his %2 to %3's %4.", "p1 male, p2 male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName())).arg(targetCard)); + } else if (player == targetPlayer) { + if (isFemale(player)) { + if (isFemale(startPlayer)) + str = tr("%1 points from %2's %3 to her own %4.", "card owner female, target female"); + else + str = tr("%1 points from %2's %3 to her own %4.", "card owner male, target female"); + } else { + if (isFemale(startPlayer)) + str = tr("%1 points from %2's %3 to his own %4.", "card owner female, target male"); + else + str = tr("%1 points from %2's %3 to his own %4.", "card owner male, target male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard).arg(targetCard)); + } else { + if (isFemale(player)) { + if (isFemale(startPlayer)) { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 female, p3 female"); + else + str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 female, p3 male"); + } else { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 male, p3 female"); + else + str = tr("%1 points from %2's %3 to %4's %5.", "p1 female, p2 male, p3 male"); + } + } else { + if (isFemale(startPlayer)) { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 female, p3 female"); + else + str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 female, p3 male"); + } else { + if (isFemale(targetPlayer)) + str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 male, p3 female"); + else + str = tr("%1 points from %2's %3 to %4's %5.", "p1 male, p2 male, p3 male"); + } + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(sanitizeHtml(startPlayer->getName())).arg(startCard).arg(sanitizeHtml(targetPlayer->getName())).arg(targetCard)); + } + } } void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int counterId, int value, int oldValue) @@ -335,10 +482,17 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c QString finalStr, colorStr; int delta = abs(oldValue - value); - if (value > oldValue) - finalStr = tr("%1 places %n %2 counter(s) on %3 (now %4).", "", delta); - else - finalStr = tr("%1 removes %n %2 counter(s) from %3 (now %4).", "", delta); + if (value > oldValue) { + if (isFemale(player)) + finalStr = tr("%1 places %n %2 counter(s) on %3 (now %4).", "female", delta); + else + finalStr = tr("%1 places %n %2 counter(s) on %3 (now %4).", "male", delta); + } else { + if (isFemale(player)) + finalStr = tr("%1 removes %n %2 counter(s) from %3 (now %4).", "female", delta); + else + finalStr = tr("%1 removes %n %2 counter(s) from %3 (now %4).", "male", delta); + } switch (counterId) { case 0: colorStr = tr("red", "", delta); break; @@ -360,55 +514,111 @@ void MessageLogWidget::logSetTapped(Player *player, CardItem *card, bool tapped) if (currentContext == MessageContext_MoveCard) moveCardTapped.insert(card, tapped); else { - QString cardStr; - if (!card) - cardStr = isFemale(player) ? tr("her permanents") : tr("his permanents"); - else - cardStr = QString("%1").arg(sanitizeHtml(card->getName())); - appendHtml(tr("%1 %2 %3.").arg(sanitizeHtml(player->getName())).arg(tapped ? tr("taps") : tr("untaps")).arg(cardStr)); + QString str; + if (!card) { + if (isFemale(player)) { + if (tapped) + str = tr("%1 taps her permanents.", "female"); + else + str = tr("%1 untaps her permanents.", "female"); + } else { + if (tapped) + str = tr("%1 taps his permanents.", "male"); + else + str = tr("%1 untaps his permanents.", "male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName()))); + } else { + if (isFemale(player)) { + if (tapped) + str = tr("%1 taps %2.", "female"); + else + str = tr("%1 untaps %2.", "female"); + } else { + if (tapped) + str = tr("%1 taps %2.", "male"); + else + str = tr("%1 untaps %2.", "male"); + } + QString cardStr = QString("%1").arg(sanitizeHtml(card->getName())); + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(cardStr)); + } } } void MessageLogWidget::logSetCounter(Player *player, QString counterName, int value, int oldValue) { - appendHtml(tr("%1 sets counter %2 to %3 (%4%5).").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(counterName))).arg(QString("%1").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue)); + QString str; + if (isFemale(player)) + str = tr("%1 sets counter %2 to %3 (%4%5).", "female"); + else + str = tr("%1 sets counter %2 to %3 (%4%5).", "male"); + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(counterName))).arg(QString("%1").arg(value)).arg(value > oldValue ? "+" : "").arg(value - oldValue)); } void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap) { - QString finalStr; - if (doesntUntap) - finalStr = tr("%1 sets %2 to not untap normally."); - else - finalStr = tr("%1 sets %2 to untap normally."); - appendHtml(finalStr.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName())))); + QString str; + if (doesntUntap) { + if (isFemale(player)) + str = tr("%1 sets %2 to not untap normally.", "female"); + else + str = tr("%1 sets %2 to not untap normally.", "male"); + } else { + if (isFemale(player)) + str = tr("%1 sets %2 to untap normally.", "female"); + else + str = tr("%1 sets %2 to untap normally.", "male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName())))); } void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT) { if (currentContext == MessageContext_MoveCard) moveCardPT.insert(card, newPT); - else - appendHtml(tr("%1 sets PT of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newPT)))); + else { + QString str; + if (isFemale(player)) + str = tr("%1 sets PT of %2 to %3.", "female"); + else + str = tr("%1 sets PT of %2 to %3.", "male"); + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newPT)))); + } } void MessageLogWidget::logSetAnnotation(Player *player, CardItem *card, QString newAnnotation) { - appendHtml(tr("%1 sets annotation of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newAnnotation)))); + QString str; + if (isFemale(player)) + str = tr("%1 sets annotation of %2 to %3.", "female"); + else + str = tr("%1 sets annotation of %2 to %3.", "male"); + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(QString("%1").arg(sanitizeHtml(card->getName()))).arg(QString("%1").arg(sanitizeHtml(newAnnotation)))); } void MessageLogWidget::logDumpZone(Player *player, CardZone *zone, int numberCards) { - if (numberCards != -1) - appendHtml(tr("%1 is looking at the top %2 cards %3.").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive))); - else - appendHtml(tr("%1 is looking at %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative))); + if (numberCards != -1) { + if (isFemale(player)) + appendHtml(tr("%1 is looking at the top %2 cards %3.", "female").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive))); + else + appendHtml(tr("%1 is looking at the top %2 cards %3.", "male").arg(sanitizeHtml(player->getName())).arg(numberCards).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseGenitive))); + } else { + if (isFemale(player)) + appendHtml(tr("%1 is looking at %2.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative))); + else + appendHtml(tr("%1 is looking at %2.", "male").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative))); + } } void MessageLogWidget::logStopDumpZone(Player *player, CardZone *zone) { QString zoneName = zone->getTranslatedName(zone->getPlayer() == player, CaseAccusative); - appendHtml(tr("%1 stops looking at %2.").arg(sanitizeHtml(player->getName())).arg(zoneName)); + if (isFemale(player)) + appendHtml(tr("%1 stops looking at %2.", "female").arg(sanitizeHtml(player->getName())).arg(zoneName)); + else + appendHtml(tr("%1 stops looking at %2.", "male").arg(sanitizeHtml(player->getName())).arg(zoneName)); } void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer) @@ -429,28 +639,80 @@ void MessageLogWidget::logRevealCards(Player *player, CardZone *zone, int cardId else cardStr = QString("%1").arg(sanitizeHtml(cardName)); + QString str; if (cardId == -1) { - if (otherPlayer) - appendHtml(tr("%1 reveals %2 to %3.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName()))); - else - appendHtml(tr("%1 reveals %2.").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + if (otherPlayer) { + if (isFemale(player)) { + if (isFemale(otherPlayer)) + str = tr("%1 reveals %2 to %3.", "p1 female, p2 female"); + else + str = tr("%1 reveals %2 to %3.", "p1 female, p2 male"); + } else { + if (isFemale(otherPlayer)) + str = tr("%1 reveals %2 to %3.", "p1 male, p2 female"); + else + str = tr("%1 reveals %2 to %3.", "p1 male, p2 male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative)).arg(sanitizeHtml(otherPlayer->getName()))); + } else { + if (isFemale(player)) + appendHtml(tr("%1 reveals %2.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + else + appendHtml(tr("%1 reveals %2.", "male").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + } } else if (cardId == -2) { - if (otherPlayer) - appendHtml(tr("%1 randomly reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); - else - appendHtml(tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + if (otherPlayer) { + if (isFemale(player)) { + if (isFemale(otherPlayer)) + str = tr("%1 randomly reveals %2%3 to %4.", "p1 female, p2 female"); + else + str = tr("%1 randomly reveals %2%3 to %4.", "p1 female, p2 male"); + } else { + if (isFemale(otherPlayer)) + str = tr("%1 randomly reveals %2%3 to %4.", "p1 male, p2 female"); + else + str = tr("%1 randomly reveals %2%3 to %4.", "p1 male, p2 male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); + } else { + if (isFemale(player)) + appendHtml(tr("%1 randomly reveals %2%3.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + else + appendHtml(tr("%1 randomly reveals %2%3.", "male").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + } } else { - if (otherPlayer) - appendHtml(tr("%1 reveals %2%3 to %4.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); - else - appendHtml(tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + if (otherPlayer) { + if (isFemale(player)) { + if (isFemale(otherPlayer)) + str = tr("%1 reveals %2%3 to %4.", "p1 female, p2 female"); + else + str = tr("%1 reveals %2%3 to %4.", "p1 female, p2 male"); + } else { + if (isFemale(otherPlayer)) + str = tr("%1 reveals %2%3 to %4.", "p1 male, p2 female"); + else + str = tr("%1 reveals %2%3 to %4.", "p1 male, p2 male"); + } + appendHtml(str.arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr).arg(sanitizeHtml(otherPlayer->getName()))); + } else { + if (isFemale(player)) + appendHtml(tr("%1 reveals %2%3.", "female").arg(sanitizeHtml(player->getName())).arg(zone->getTranslatedName(true, CaseAccusative))); + else + appendHtml(tr("%1 reveals %2%3.", "male").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr)); + } } } void MessageLogWidget::logSetActivePlayer(Player *player) { soundEngine->notification(); - appendHtml("
" + tr("It is now %1's turn.").arg(player->getName()) + "
"); + + QString str; + if (isFemale(player)) + str = tr("It is now %1's turn.", "female"); + else + str = tr("It is now %1's turn.", "male"); + appendHtml("
" + str.arg(player->getName()) + "
"); } void MessageLogWidget::logSetActivePhase(int phase) @@ -527,7 +789,7 @@ void MessageLogWidget::connectToPlayer(Player *player) connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *)), this, SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *))); } -MessageLogWidget::MessageLogWidget(const QString &_ownName, QWidget *parent) - : ChatView(_ownName, false, parent) +MessageLogWidget::MessageLogWidget(const QString &_ownName, bool _female, QWidget *parent) + : ChatView(_ownName, false, parent), female(_female) { } diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 698489656..37d4a2422 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -31,6 +31,7 @@ private: bool isFemale(Player *player) const; QPair getFromStr(CardZone *zone, QString cardName, int position) const; MessageContext currentContext; + bool female; QList moveCardQueue; QMap moveCardPT; @@ -39,13 +40,6 @@ private: Player *mulliganPlayer; int mulliganNumber; public slots: - void logConnecting(QString hostname); - void logConnected(); - void logDisconnected(); - void logSocketError(const QString &errorString); - void logServerError(ResponseCode response); - void logProtocolVersionMismatch(int clientVersion, int serverVersion); - void logProtocolError(); void logGameJoined(int gameId); void logJoin(Player *player); void logLeave(Player *player); @@ -88,7 +82,7 @@ public slots: void containerProcessingDone(); public: void connectToPlayer(Player *player); - MessageLogWidget(const QString &_ownName, QWidget *parent = 0); + MessageLogWidget(const QString &_ownName, bool _female, QWidget *parent = 0); }; #endif diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 2e38baf71..9b15e0deb 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -158,7 +158,7 @@ void DeckViewContainer::setDeck(DeckList *deck) readyStartButton->setEnabled(true); } -TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, const QString &_userName, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) +TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, ServerInfo_User *_userInfo, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) : Tab(_tabSupervisor), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1) { phasesToolbar = new PhasesToolbar; @@ -176,7 +176,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList &_client timeElapsedLabel = new QLabel; timeElapsedLabel->setAlignment(Qt::AlignCenter); - messageLog = new MessageLogWidget(_userName); + messageLog = new MessageLogWidget(_userInfo->getName(), _userInfo->getGender() == ServerInfo_User::Female); connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString))); connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString))); connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 289451f14..a5eb5db9f 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -155,7 +155,7 @@ private slots: void actNextPhase(); void actNextTurn(); public: - TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, const QString &_userName, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); + TabGame(TabSupervisor *_tabSupervisor, QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, ServerInfo_User *_userInfo, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); ~TabGame(); void retranslateUi(); void closeRequest(); diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index 10e33afff..824d149d9 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -105,11 +105,10 @@ int TabSupervisor::myAddTab(Tab *tab) return addTab(tab, tab->getTabText()); } -void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo) +void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *_userInfo) { client = _client; - userName = userInfo->getName(); - userLevel = userInfo->getUserLevel(); + userInfo = new ServerInfo_User(_userInfo); connect(client, SIGNAL(roomEventReceived(RoomEvent *)), this, SLOT(processRoomEvent(RoomEvent *))); connect(client, SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *))); @@ -146,6 +145,7 @@ void TabSupervisor::start(AbstractClient *_client, ServerInfo_User *userInfo) void TabSupervisor::startLocal(const QList &_clients) { + userInfo = new ServerInfo_User; localClients = _clients; for (int i = 0; i < localClients.size(); ++i) connect(localClients[i], SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *))); @@ -192,6 +192,9 @@ void TabSupervisor::stop() while (messageIterator.hasNext()) messageIterator.next().value()->deleteLater(); messageTabs.clear(); + + delete userInfo; + userInfo = 0; } void TabSupervisor::updatePingTime(int value, int max) @@ -221,7 +224,7 @@ void TabSupervisor::addCloseButtonToTab(Tab *tab, int tabIndex) void TabSupervisor::gameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(this, QList() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userName, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + TabGame *tab = new TabGame(this, QList() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userInfo, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); int tabIndex = myAddTab(tab); @@ -232,7 +235,7 @@ void TabSupervisor::gameJoined(Event_GameJoined *event) void TabSupervisor::localGameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), QString(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + TabGame *tab = new TabGame(this, localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), userInfo, event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); int tabIndex = myAddTab(tab); addCloseButtonToTab(tab, tabIndex); @@ -258,7 +261,7 @@ void TabSupervisor::gameLeft(TabGame *tab) void TabSupervisor::addRoomTab(ServerInfo_Room *info, bool setCurrent) { - TabRoom *tab = new TabRoom(this, client, userName, info); + TabRoom *tab = new TabRoom(this, client, userInfo->getName(), info); connect(tab, SIGNAL(roomClosing(TabRoom *)), this, SLOT(roomLeft(TabRoom *))); connect(tab, SIGNAL(openMessageDialog(const QString &, bool)), this, SLOT(addMessageTab(const QString &, bool))); int tabIndex = myAddTab(tab); @@ -278,10 +281,10 @@ void TabSupervisor::roomLeft(TabRoom *tab) TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus) { - if (receiverName == userName) + if (receiverName == userInfo->getName()) return 0; - TabMessage *tab = new TabMessage(this, client, userName, receiverName); + TabMessage *tab = new TabMessage(this, client, userInfo->getName(), receiverName); connect(tab, SIGNAL(talkClosing(TabMessage *)), this, SLOT(talkLeft(TabMessage *))); int tabIndex = myAddTab(tab); addCloseButtonToTab(tab, tabIndex); @@ -372,3 +375,8 @@ bool TabSupervisor::getAdminLocked() const return true; return tabAdmin->getLocked(); } + +int TabSupervisor::getUserLevel() const +{ + return userInfo->getUserLevel(); +} diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index 5d7a2c9bc..0a38d5f83 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -37,8 +37,7 @@ protected: class TabSupervisor : public QTabWidget { Q_OBJECT private: - QString userName; - int userLevel; + ServerInfo_User *userInfo; QIcon *tabChangedIcon; AbstractClient *client; QList localClients; @@ -61,7 +60,7 @@ public: int getGameCount() const { return gameTabs.size(); } TabUserLists *getUserListsTab() const { return tabUserLists; } bool getAdminLocked() const; - int getUserLevel() const { return userLevel; } + int getUserLevel() const; signals: void setMenu(QMenu *menu); void localGameEnded(); diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index 9a24bb029..fd3280677 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -230,202 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - + &Draw arrow... - + &Power / toughness - + &Increase power - + Ctrl++ - + &Decrease power - + Ctrl+- - + I&ncrease toughness - + Alt++ - + D&ecrease toughness - + Alt+- - + In&crease power and toughness - + Ctrl+Alt++ - + Dec&rease power and toughness - + Ctrl+Alt+- - + Set &power and toughness... - + Ctrl+P - + &Set annotation... - + red - + yellow - + green - + &Add counter (%1) - + &Remove counter (%1) - + &Set counters (%1)... - + &top of library - + &bottom of library - + &graveyard - + Ctrl+Del - + &exile - + &Move to @@ -1208,7 +1208,6 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - @@ -1216,86 +1215,87 @@ This is only saved for moderators and cannot be seen by the banned person. + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + C&reate - + &Join - + J&oin as spectator @@ -1684,118 +1684,183 @@ Local version is %1, remote version is %2. MessageLogWidget - - Connecting to %1... - - - - - Connected. - - - - - Disconnected from server. - - - - - Invalid password. - - - - - Protocol version mismatch. Client: %1, Server: %2 - - - - - Protocol error. - - - - - You have joined game #%1. - - - - - %1 has joined the game. - - - - - %1 has left the game. - - - - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - - %1 has loaded a local deck. - - - - - %1 has loaded deck #%2. - - - - - %1 is ready to start the game. - - - - - %1 is not ready to start the game any more. - - - - - %1 has conceded the game. - - - - + The game has started. - + + You have joined game #%1. + female + + + + + You have joined game #%1. + male + + + + + %1 has joined the game. + female + + + + + %1 has joined the game. + male + + + + + %1 has left the game. + female + + + + + %1 has left the game. + male + + + + + %1 has loaded a local deck. + female + + + + + %1 has loaded a local deck. + male + + + + + %1 has loaded deck #%2. + female + + + + + %1 has loaded deck #%2. + male + + + + + %1 is ready to start the game. + female + + + + + %1 is ready to start the game. + male + + + + + %1 is not ready to start the game any more. + female + + + + + %1 is not ready to start the game any more. + male + + + + + %1 has conceded the game. + female + + + + + %1 has conceded the game. + male + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female - %1 has lost connection to the game. - - - - %1 shuffles %2. + male - + %1 rolls a %2 with a %3-sided die. + female + + + + + %1 rolls a %2 with a %3-sided die. + male - + %1 draws %n card(s). + female + + + + + + + + + %1 draws %n card(s). + male @@ -1803,189 +1868,200 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. + female + + + + + + + + + %1 takes a mulligan to %n. + male @@ -1994,74 +2070,620 @@ Local version is %1, remote version is %2. + %1 flips %2 face-down. + female + + + + + %1 flips %2 face-down. + male + + + + + %1 flips %2 face-up. + female + + + + + %1 flips %2 face-up. + male + + + + + %1 destroys %2. + female + + + + + %1 destroys %2. + male + + + + + %1 unattaches %2. + female + + + + + %1 unattaches %2. + male + + + + + %1 creates token: %2%3. + female + + + + + %1 creates token: %2%3. + male + + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + + + + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + + + + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + + + + + %1 sets counter %2 to %3 (%4%5). + male + + + + + %1 sets %2 to not untap normally. + female + + + + + %1 sets %2 to not untap normally. + male + + + + + %1 sets %2 to untap normally. + female + + + + + %1 sets %2 to untap normally. + male + + + + + %1 sets PT of %2 to %3. + female + + + + + %1 sets PT of %2 to %3. + male + + + + + %1 sets annotation of %2 to %3. + female + + + + + %1 sets annotation of %2 to %3. + male + + + + + %1 is looking at the top %2 cards %3. + female + + + + + %1 is looking at the top %2 cards %3. + male + + + + + %1 is looking at %2. + female + + + + + %1 is looking at %2. + male + + + + + %1 stops looking at %2. + female + + + + + %1 stops looking at %2. + male + + + + + %1 reveals %2 to %3. + p1 female, p2 female + + + + + %1 reveals %2 to %3. + p1 female, p2 male + + + + + %1 reveals %2 to %3. + p1 male, p2 female + + + + + %1 reveals %2 to %3. + p1 male, p2 male + + + + + %1 reveals %2. + female + + + + + %1 reveals %2. + male + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 randomly reveals %2%3. + female + + + + + %1 randomly reveals %2%3. + male + + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 reveals %2%3. + female + + + + + %1 reveals %2%3. + male + + + + + It is now %1's turn. + female + + + + + It is now %1's turn. + male + + + + %1 draws his initial hand. - + %1 draws her initial hand. - - %1 flips %2 face-down. - - - - - %1 flips %2 face-up. - - - - - %1 destroys %2. - - - - + %1 attaches %2 to %3's %4. + p1 female, p2 female - - %1 unattaches %2. + + %1 attaches %2 to %3's %4. + p1 female, p2 male - - %1 creates token: %2%3. + + %1 attaches %2 to %3's %4. + p1 male, p2 female - - %1 points from %2's %3 to %4. - - - - - %1 points from %2's %3 to %4's %5. + + %1 attaches %2 to %3's %4. + p1 male, p2 male - - %1 places %n %2 counter(s) on %3 (now %4). - - - - - - - - - %1 removes %n %2 counter(s) from %3 (now %4). - - - - - - - - + red @@ -2070,7 +2692,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2079,7 +2701,7 @@ Local version is %1, remote version is %2. - + green @@ -2088,162 +2710,62 @@ Local version is %1, remote version is %2. - - his permanents - - - - - her permanents - - - - - %1 %2 %3. - - - - - taps - - - - - untaps - - - - - %1 sets counter %2 to %3 (%4%5). - - - - - %1 sets %2 to not untap normally. - - - - - %1 sets %2 to untap normally. - - - - - %1 sets PT of %2 to %3. - - - - - %1 sets annotation of %2 to %3. - - - - - %1 is looking at the top %2 cards %3. - - - - - %1 is looking at %2. - - - - - %1 stops looking at %2. - - - - - %1 reveals %2 to %3. - - - - - %1 reveals %2. - - - - - %1 randomly reveals %2%3 to %4. - - - - - %1 randomly reveals %2%3. - - - - - %1 reveals %2%3 to %4. - - - - - %1 reveals %2%3. - - - - - It is now %1's turn. - - - - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -3234,67 +3756,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + %1's games - + User &details - + Direct &chat - + Show this user's &games - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index 0b07c46f6..cd581e185 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -279,57 +279,57 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic CardItem - + &Play &Ausspielen - + &Hide &Verstecken - + &Tap &Tappen - + &Untap E&nttappen - + Toggle &normal untapping N&ormales Enttappen umschalten - + &Flip &Umdrehen - + &Clone &Kopieren - + Ctrl+H Ctrl+H - + &Attach to card... &An Karte anlegen... - + Ctrl+A Ctrl+A - + Unattac&h &Von Karte lösen @@ -338,147 +338,147 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Kampfwerte setzen... - + &Draw arrow... &Pfeil zeichnen... - + &Power / toughness &Kampfwerte - + &Increase power &Stärke erhöhen - + Ctrl++ Ctrl++ - + &Decrease power S&tärke senken - + Ctrl+- Ctrl+- - + I&ncrease toughness &Widerstandskraft erhöhen - + Alt++ Alt++ - + D&ecrease toughness W&iderstandskraft senken - + Alt+- Alt+- - + In&crease power and toughness Stärke und Widerstandskraft &erhöhen - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Stärke und Widerstandskraft s&enken - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... &Kampfwerte setzen... - + Ctrl+P Ctrl+P - + &Set annotation... &Hinweis setzen... - + red rot - + yellow gelb - + green grün - + &Add counter (%1) Zählmarke &hinzufügen (%1) - + &Remove counter (%1) Zählmarke &entfernen (%1) - + &Set counters (%1)... Zählmarken &setzen (%1)... - + &top of library &auf die Bibliothek - + &bottom of library &unter die Bibliothek - + &graveyard in den &Friedhof - + Ctrl+Del Ctrl+Del - + &exile ins &Exil - + &Move to &Verschieben @@ -1952,17 +1952,16 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic GameSelector - + C&reate Spiel e&rstellen - + &Join &Teilnehmen - @@ -1970,6 +1969,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic + Error Fehler @@ -1978,67 +1978,67 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic XXX - + Please join the appropriate room first. Bitte betreten Sie erst den entsprechenden Raum. - + Wrong password. Falsches Passwort. - + Spectators are not allowed in this game. In diesem Spiel sind keine Zuschauer zugelassen. - + The game is already full. Das Spiel ist bereits voll. - + The game does not exist any more. Dieses Spiel gibt es nicht mehr. - + This game is only open to registered users. Dieses Spiel kann nur von registrierten Benutzern betreten werden. - + This game is only open to its creator's buddies. Dieses Spiel kann nur von Freunden des Erstellers betreten werden. - + You are being ignored by the creator of this game. Der Ersteller dieses Spiels ignoriert Sie. - + Join game Spiel beitreten - + Password: Passwort: - + Games Spiele - + Show &full games &Volle Spiele anzeigen - + Show &running games &Laufende Spiele anzeigen @@ -2047,7 +2047,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Volle Spiele anzeigen - + J&oin as spectator &Zuschauen @@ -2491,24 +2491,20 @@ Lokale Version ist %1, Serverversion ist %2. MessageLogWidget - Connecting to %1... - Verbinde zu %1... + Verbinde zu %1... - Connected. - Verbunden. + Verbunden. - Disconnected from server. - Verbindung zum Server getrennt. + Verbindung zum Server getrennt. - Invalid password. - Ungültiges Passwort. + Ungültiges Passwort. You have joined the game. Player list: @@ -2547,8 +2543,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten - - + + a card eine Karte @@ -2605,7 +2601,7 @@ Lokale Version ist %1, Serverversion ist %2. %1s Sideboard - + The game has started. Das Spiel hat begonnen. @@ -2626,89 +2622,71 @@ Lokale Version ist %1, Serverversion ist %2. Protokollversion stimmt nicht überein. - - Protocol version mismatch. Client: %1, Server: %2 - - - - Protocol error. - Protokollfehler. + Protokollfehler. - You have joined game #%1. - Sie sind dem Spiel %1 beigetreten. + Sie sind dem Spiel %1 beigetreten. - %1 has joined the game. - %1 ist dem Spiel beigetreten. + %1 ist dem Spiel beigetreten. - %1 has left the game. - %1 hat das Spiel verlassen. + %1 hat das Spiel verlassen. - + The game has been closed. Das Spiel wurde geschlossen. - + %1 is now watching the game. %1 schaut nun dem Spiel zu. - + %1 is not watching the game any more. %1 schaut dem Spiel nicht mehr zu. - %1 has loaded a local deck. - %1 hat ein lokales Deck geladen. + %1 hat ein lokales Deck geladen. - %1 has loaded deck #%2. - %1 hat das Deck Nr. %2 geladen. + %1 hat das Deck Nr. %2 geladen. - %1 is ready to start the game. - %1 ist bereit, das Spiel zu starten. + %1 ist bereit, das Spiel zu starten. - %1 is not ready to start the game any more. - %1 ist nicht mehr bereit, das Spiel zu starten. + %1 ist nicht mehr bereit, das Spiel zu starten. - %1 has conceded the game. - %1 hat das Spiel aufgegeben. + %1 hat das Spiel aufgegeben. - %1 has restored connection to the game. - %1 ist wieder mit dem Spiel verbunden. + %1 ist wieder mit dem Spiel verbunden. - %1 has lost connection to the game. - %1 hat die Verbindung zum Spiel verloren. + %1 hat die Verbindung zum Spiel verloren. - %1 shuffles %2. - %1 mischt %2. + %1 mischt %2. - %1 rolls a %2 with a %3-sided die. - %1 würfelt eine %2 mit einem %3-seitigen Würfel. + %1 würfelt eine %2 mit einem %3-seitigen Würfel. %1 draws a card. @@ -2719,191 +2697,362 @@ Lokale Version ist %1, Serverversion ist %2. %1 zieht %2 Karten. - %1 draws %n card(s). + + %1 zieht eine Karte. + %1 zieht %n Karten. + + + + + You have joined game #%1. + female + Sie sind dem Spiel %1 beigetreten. + + + + You have joined game #%1. + male + Sie sind dem Spiel %1 beigetreten. + + + + %1 has joined the game. + female + %1 ist dem Spiel beigetreten. + + + + %1 has joined the game. + male + %1 ist dem Spiel beigetreten. + + + + %1 has left the game. + female + %1 hat das Spiel verlassen. + + + + %1 has left the game. + male + %1 hat das Spiel verlassen. + + + + %1 has loaded a local deck. + female + %1 hat ein lokales Deck geladen. + + + + %1 has loaded a local deck. + male + %1 hat ein lokales Deck geladen. + + + + %1 has loaded deck #%2. + female + %1 hat das Deck Nr. %2 geladen. + + + + %1 has loaded deck #%2. + male + %1 hat das Deck Nr. %2 geladen. + + + + %1 is ready to start the game. + female + %1 ist bereit, das Spiel zu starten. + + + + %1 is ready to start the game. + male + %1 ist bereit, das Spiel zu starten. + + + + %1 is not ready to start the game any more. + female + %1 ist nicht mehr bereit, das Spiel zu starten. + + + + %1 is not ready to start the game any more. + male + %1 ist nicht mehr bereit, das Spiel zu starten. + + + + %1 has conceded the game. + female + %1 hat das Spiel aufgegeben. + + + + %1 has conceded the game. + male + %1 hat das Spiel aufgegeben. + + + + %1 has restored connection to the game. + female + %1 ist wieder mit dem Spiel verbunden. + + + + %1 has restored connection to the game. + male + %1 ist wieder mit dem Spiel verbunden. + + + + %1 has lost connection to the game. + female + %1 hat die Verbindung zum Spiel verloren. + + + + %1 has lost connection to the game. + male + %1 hat die Verbindung zum Spiel verloren. + + + + %1 shuffles %2. + female + %1 mischt %2. + + + + %1 shuffles %2. + male + %1 mischt %2. + + + + %1 rolls a %2 with a %3-sided die. + female + %1 würfelt eine %2 mit einem %3-seitigen Würfel. + + + + %1 rolls a %2 with a %3-sided die. + male + %1 würfelt eine %2 mit einem %3-seitigen Würfel. + + + + %1 draws %n card(s). + female + + %1 zieht eine Karte. + %1 zieht %n Karten. + + + + + %1 draws %n card(s). + male %1 zieht eine Karte. %1 zieht %n Karten. - + %1 undoes his last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes her last draw. %1 legt die zuletzt gezogene Karte zurück. - + %1 undoes his last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + %1 undoes her last draw (%2). %1 legt die zuletzt gezogene Karte zurück (%2). - + from table vom Spielfeld - + from graveyard aus dem Friedhof - + from exile aus dem Exil - + from hand von der Hand - + the bottom card of his library die unterste Karte seiner Bibliothek - + the bottom card of her library die unterste Karte ihrer Bibliothek - + from the bottom of his library , die unterste Karte seiner Bibliothek, - + from the bottom of her library , die unterste Karte ihrer Bibliothek, - + the top card of his library die oberste Karte seiner Bibliothek - + the top card of her library die oberste Karte ihrer Bibliothek - + from the top of his library , die oberste Karte seiner Bibliothek, - + from the top of her library , die oberste Karte ihrer Bibliothek, - + from library aus der Bibliothek - + from sideboard aus dem Sideboard - + from the stack vom Stapel - + %1 gives %2 control over %3. %1 überlässt %2 die Kontrolle über %3. - + %1 puts %2 into play tapped%3. %1 bringt %2 getappt%3 ins Spiel. - + %1 puts %2 into play%3. %1 bringt %2%3 ins Spiel. - + %1 puts %2%3 into graveyard. %1 legt %2%3 auf den Friedhof. - + %1 exiles %2%3. %1 schickt %2%3 ins Exil. - + %1 moves %2%3 to hand. %1 nimmt %2%3 auf die Hand. - + %1 puts %2%3 into his library. %1 legt %2%3 in seine Bibliothek. - + %1 puts %2%3 into her library. %1 legt %2%3 in ihre Bibliothek. - + %1 puts %2%3 on bottom of his library. %1 legt %2%3 unter seine Bibliothek. - + %1 puts %2%3 on bottom of her library. %1 legt %2%3 unter ihre Bibliothek. - + %1 puts %2%3 on top of his library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 on top of her library. %1 legt %2%3 auf die Bibliothek. - + %1 puts %2%3 into his library at position %4. %1 legt %2%3 in seine Bibliothek an %4. Stelle. - + %1 puts %2%3 into her library at position %4. %1 legt %2%3 in ihre Bibliothek an %4. Stelle. - + %1 moves %2%3 to sideboard. %1 legt %2%3 in sein Sideboard. - + %1 plays %2%3. %1 spielt %2%3 aus. - + %1 takes a mulligan to %n. + female + + %1 nimmt einen Mulligan auf %n. + %1 nimmt einen Mulligan auf %n. + + + + + %1 takes a mulligan to %n. + male %1 nimmt einen Mulligan auf %n. %1 nimmt einen Mulligan auf %n. @@ -2911,98 +3060,700 @@ Lokale Version ist %1, Serverversion ist %2. - %1 draws his initial hand. - %1 zieht seine Starthand. - - - - %1 draws her initial hand. - %1 zieht ihre Starthand. - - - %1 flips %2 face-down. + female %1 wendet %2 auf die Rückseite. - + + %1 flips %2 face-down. + male + %1 wendet %2 auf die Rückseite. + + + %1 flips %2 face-up. + female %1 wendet %2 auf die Vorderseite. - + + %1 flips %2 face-up. + male + %1 wendet %2 auf die Vorderseite. + + + %1 destroys %2. + female + %1 zerstört %2. + + + + %1 destroys %2. + male %1 zerstört %2. - %1 attaches %2 to %3's %4. + female + %1 legt %2 an %3s %4 an. + + + %1 attaches %2 to %3's %4. + male + %1 legt %2 an %3s %4 an. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 female %1 legt %2 an %3s %4 an. - + + %1 attaches %2 to %3's %4. + p1 female, p2 male + %1 legt %2 an %3s %4 an. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + %1 legt %2 an %3s %4 an. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + %1 legt %2 an %3s %4 an. + + + %1 unattaches %2. + female %1 löst %2 ab. - + + %1 unattaches %2. + male + %1 löst %2 ab. + + + %1 creates token: %2%3. + female %1 erstellt Token: %2%3. - + + %1 creates token: %2%3. + male + %1 erstellt Token: %2%3. + + + + %1 points from her %2 to herself. + female + %1 zeigt von ihrem %2 auf sich selbst. + + + + %1 points from his %2 to himself. + male + %1 zeigt von seinem %2 auf sich selbst. + + + + %1 points from her %2 to %3. + p1 female, p2 female + %1 zeigt von ihrem %2 auf %3. + + + + %1 points from her %2 to %3. + p1 female, p2 male + %1 zeigt von ihrem %2 auf %3. + + + + %1 points from his %2 to %3. + p1 male, p2 female + %1 zeigt von seinem %2 auf %3. + + + + %1 points from his %2 to %3. + p1 male, p2 male + %1 zeigt von seinem %2 auf %3. + + + + %1 points from %2's %3 to herself. + card owner female, target female + %1 zeigt von %2s %3 auf sich selbst. + + + + %1 points from %2's %3 to herself. + card owner male, target female + %1 zeigt von %2s %3 auf sich selbst. + + + + %1 points from %2's %3 to himself. + card owner female, target male + %1 zeigt von %2s %3 auf sich selbst. + + + + %1 points from %2's %3 to himself. + card owner male, target male + %1 zeigt von %2s %3 auf sich selbst. + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female %1 zeigt von %2s %3 auf %4. + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + %1 zeigt von %2s %3 auf %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + %1 zeigt von %2s %3 auf %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + %1 zeigt von %2s %3 auf %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + %1 zeigt von %2s %3 auf %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + %1 zeigt von %2s %3 auf %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + %1 zeigt von %2s %3 auf %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + %1 zeigt von %2s %3 auf %4. + + + + %1 points from her %2 to her %3. + female + %1 zeigt von ihrem %2 auf ihren %3. + + + + %1 points from his %2 to his %3. + male + %1 zeigt von seinem %2 auf seinen %3. + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + %1 zeigt von ihrem %2 auf %3s %4. + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + %1 zeigt von ihrem %2 auf %3s %4. + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + %1 zeigt von seinem %2 auf %3s %4. + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + %1 zeigt von seinem %2 auf %3s %4. + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + %1 zeigt von %2s %3 auf ihren eigenen %4. + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + %1 zeigt von %2s %3 auf ihren eigenen %4. + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + %1 zeigt von %2s %3 auf seinen eigenen %4. + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + %1 zeigt von %2s %3 auf seinen eigenen %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + %1 zeigt von %2s %3 auf %4s %5. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + %1 zeigt von %2s %3 auf %4s %5. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + %1 zeigt von %2s %3 auf %4s %5. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + %1 zeigt von %2s %3 auf %4s %5. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + %1 zeigt von %2s %3 auf %4s %5. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + %1 zeigt von %2s %3 auf %4s %5. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + %1 zeigt von %2s %3 auf %4s %5. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + %1 zeigt von %2s %3 auf %4s %5. + - + %1 places %n %2 counter(s) on %3 (now %4). + female %1 legt eine %2 Marke auf %3 (jetzt %4). %1 legt %n %2 Marken auf %3 (jetzt %4). - + + %1 places %n %2 counter(s) on %3 (now %4). + male + + %1 legt eine %2 Marke auf %3 (jetzt %4). + %1 legt %n %2 Marken auf %3 (jetzt %4). + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + %1 entfernt eine %2 Marke von %3 (jetzt %4). + %1 entfernt %n %2 Marken von %3 (jetzt %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male %1 entfernt eine %2 Marke von %3 (jetzt %4). %1 entfernt %n %2 Marken von %3 (jetzt %4). - - her permanents - ihre bleibenden Karten + + %1 taps her permanents. + female + %1 tappt ihre bleibenden Karten. - + + %1 untaps her permanents. + female + %1 enttappt ihre bleibenden Karten. + + + + %1 taps his permanents. + male + %1 tappt seine bleibenden Karten. + + + + %1 untaps his permanents. + male + %1 enttappt seine bleibenden Karten. + + + + %1 taps %2. + female + %1 tappt %2. + + + + %1 untaps %2. + female + %1 enttappt %2. + + + + %1 taps %2. + male + %1 tappt %2. + + + + %1 untaps %2. + male + %1 enttappt %2. + + + + %1 sets counter %2 to %3 (%4%5). + female + %1 setzt Zähler %2 auf %3 (%4%5). + + + + %1 sets counter %2 to %3 (%4%5). + male + %1 setzt Zähler %2 auf %3 (%4%5). + + + + %1 sets %2 to not untap normally. + female + %1 setzt %2 auf explizites Enttappen. + + + + %1 sets %2 to not untap normally. + male + %1 setzt %2 auf explizites Enttappen. + + + + %1 sets %2 to untap normally. + female + %1 setzt %2 auf normales Enttappen. + + + + %1 sets %2 to untap normally. + male + %1 setzt %2 auf normales Enttappen. + + + + %1 sets PT of %2 to %3. + female + %1 setzt Kampfwerte von %2 auf %3. + + + + %1 sets PT of %2 to %3. + male + %1 setzt Kampfwerte von %2 auf %3. + + + + %1 sets annotation of %2 to %3. + female + %1 versieht %2 mit dem Hinweis %3. + + + + %1 sets annotation of %2 to %3. + male + %1 versieht %2 mit dem Hinweis %3. + + + + %1 is looking at the top %2 cards %3. + female + %1 sieht sich die obersten %2 Karten %3 an. + + + + %1 is looking at the top %2 cards %3. + male + %1 sieht sich die obersten %2 Karten %3 an. + + + + %1 is looking at %2. + female + %1 sieht sich %2 an. + + + + %1 is looking at %2. + male + %1 sieht sich %2 an. + + + + %1 stops looking at %2. + female + %1 sieht sich %2 nicht mehr an. + + + + %1 stops looking at %2. + male + %1 sieht sich %2 nicht mehr an. + + + + %1 reveals %2 to %3. + p1 female, p2 female + %1 zeigt %3 %2. + + + + %1 reveals %2 to %3. + p1 female, p2 male + %1 zeigt %3 %2. + + + + %1 reveals %2 to %3. + p1 male, p2 female + %1 zeigt %3 %2. + + + + %1 reveals %2 to %3. + p1 male, p2 male + %1 zeigt %3 %2. + + + + %1 reveals %2. + female + %1 zeigt %2 offen vor. + + + + %1 reveals %2. + male + %1 zeigt %2 offen vor. + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female %1 zeigt %4 zufällig %2%3 vor. - + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + %1 zeigt %4 zufällig %2%3 vor. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + %1 zeigt %4 zufällig %2%3 vor. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + %1 zeigt %4 zufällig %2%3 vor. + + + %1 randomly reveals %2%3. + female %1 zeigt zufällig %2%3 offen vor. - + + %1 randomly reveals %2%3. + male + %1 zeigt zufällig %2%3 offen vor. + + + %1 reveals %2%3 to %4. + p1 female, p2 female %1 zeigt %4 %2%3 vor. - + + %1 reveals %2%3 to %4. + p1 female, p2 male + %1 zeigt %4 %2%3 vor. + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + %1 zeigt %4 %2%3 vor. + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + %1 zeigt %4 %2%3 vor. + + + %1 reveals %2%3. + female %1 zeigt %2%3 offen vor. + + + %1 reveals %2%3. + male + %1 zeigt %2%3 offen vor. + + + + It is now %1's turn. + female + %1 ist am Zug. + + + + It is now %1's turn. + male + %1 ist am Zug. + + + %1 takes a mulligan to %n. + + %1 nimmt einen Mulligan auf %n. + %1 nimmt einen Mulligan auf %n. + + + + + %1 draws his initial hand. + %1 zieht seine Starthand. + + + + %1 draws her initial hand. + %1 zieht ihre Starthand. + + + %1 flips %2 face-down. + %1 wendet %2 auf die Rückseite. + + + %1 flips %2 face-up. + %1 wendet %2 auf die Vorderseite. + + + %1 destroys %2. + %1 zerstört %2. + + + %1 attaches %2 to %3's %4. + %1 legt %2 an %3s %4 an. + + + %1 unattaches %2. + %1 löst %2 ab. + + + %1 creates token: %2%3. + %1 erstellt Token: %2%3. + + + %1 points from %2's %3 to %4. + %1 zeigt von %2s %3 auf %4. + + + %1 places %n %2 counter(s) on %3 (now %4). + + %1 legt eine %2 Marke auf %3 (jetzt %4). + %1 legt %n %2 Marken auf %3 (jetzt %4). + + + + %1 removes %n %2 counter(s) from %3 (now %4). + + %1 entfernt eine %2 Marke von %3 (jetzt %4). + %1 entfernt %n %2 Marken von %3 (jetzt %4). + + + + her permanents + ihre bleibenden Karten + + + %1 randomly reveals %2%3 to %4. + %1 zeigt %4 zufällig %2%3 vor. + + + %1 randomly reveals %2%3. + %1 zeigt zufällig %2%3 offen vor. + + + %1 reveals %2%3 to %4. + %1 zeigt %4 %2%3 vor. + + + %1 reveals %2%3. + %1 zeigt %2%3 offen vor. + %1 creates token: %2 (%3). %1 erstellt einen Spielstein: %2 (%3). - %1 points from %2's %3 to %4's %5. - %1 zeigt von %2s %3 auf %4s %5. + %1 zeigt von %2s %3 auf %4s %5. %1 places %n counter(s) (%2) on %3 (now %4). @@ -3019,7 +3770,7 @@ Lokale Version ist %1, Serverversion ist %2. - + red rote @@ -3027,7 +3778,7 @@ Lokale Version ist %1, Serverversion ist %2. - + yellow gelbe @@ -3035,7 +3786,7 @@ Lokale Version ist %1, Serverversion ist %2. - + green grüne @@ -3043,24 +3794,20 @@ Lokale Version ist %1, Serverversion ist %2. - %1 sets counter %2 to %3 (%4%5). - %1 setzt Zähler %2 auf %3 (%4%5). + %1 setzt Zähler %2 auf %3 (%4%5). - %1 sets PT of %2 to %3. - %1 setzt Kampfwerte von %2 auf %3. + %1 setzt Kampfwerte von %2 auf %3. - %1 sets annotation of %2 to %3. - %1 versieht %2 mit dem Hinweis %3. + %1 versieht %2 mit dem Hinweis %3. - %1 is looking at the top %2 cards %3. - %1 sieht sich die obersten %2 Karten %3 an. + %1 sieht sich die obersten %2 Karten %3 an. from graveyard @@ -3155,9 +3902,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4). - %1 %2 %3. - %1 %2 %3. + %1 %2 %3. %1 sets counter "%2" to %3 (%4%5). @@ -3168,24 +3914,20 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich die obersten %2 Karten %3 an. - %1 is looking at %2. - %1 sieht sich %2 an. + %1 sieht sich %2 an. - %1 stops looking at %2. - %1 sieht sich %2 nicht mehr an. + %1 sieht sich %2 nicht mehr an. - %1 reveals %2 to %3. - %1 zeigt %3 %2. + %1 zeigt %3 %2. - %1 reveals %2. - %1 zeigt %2 offen vor. + %1 zeigt %2 offen vor. %1 randomly reveals %2 from %3 to %4. @@ -3204,7 +3946,7 @@ Lokale Version ist %1, Serverversion ist %2. %1 zeigt %2 aus %3 offen vor. - + ending phase die Zugendphase @@ -3233,57 +3975,56 @@ Lokale Version ist %1, Serverversion ist %2. %1 sieht sich %2s %3 nicht mehr an - It is now %1's turn. - %1 ist am Zug. + %1 ist am Zug. - + untap step das Enttappsegment - + upkeep step das Versorgungssegment - + draw step das Ziehsegment - + first main phase die erste Hauptphase - + beginning of combat step das Anfangssegment der Kampfphase - + declare attackers step das Angreifer-Deklarieren-Segment - + declare blockers step das Blocker-Deklarieren-Segment - + combat damage step das Kampfschadenssegment - + end of combat step das Endsegment der Kampfphase - + second main phase die zweite Hauptphase @@ -3292,7 +4033,7 @@ Lokale Version ist %1, Serverversion ist %2. das Ende-des-Zuges-Segment - + It is now the %1. Es ist nun %1. @@ -3301,14 +4042,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 bewegt %2 %3 nach %4 - taps - tappt + tappt - untaps - enttappt + enttappt %1 creates token: <font color="blue">%2</font> @@ -3331,9 +4070,8 @@ Lokale Version ist %1, Serverversion ist %2. %1 entfernt %2 Zählmarken von %3 (jetzt %4) - his permanents - seine bleibenden Karten + seine bleibenden Karten %1 %2 %3 @@ -3344,14 +4082,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 setzt Zähler "%2" auf %3 (%4%5) - %1 sets %2 to not untap normally. - %1 setzt %2 auf explizites Enttappen. + %1 setzt %2 auf explizites Enttappen. - %1 sets %2 to untap normally. - %1 setzt %2 auf normales Enttappen. + %1 setzt %2 auf normales Enttappen. %1 is looking at the top %2 cards of %3's %4 @@ -4638,67 +5374,67 @@ Bitte geben Sie einen Namen ein: UserList - + Users online: %1 Benutzer online: %1 - + Users in this room: %1 Benutzer in diesem Raum: %1 - + Buddies online: %1 / %2 Freunde online: %1 / %2 - + Ignored users online: %1 / %2 Ignorierte Benutzer online: %1 / %2 - + %1's games %1s Spiele - + User &details Benutzer&details - + Direct &chat &Persönliches Gespräch - + Show this user's &games Spiele dieses &Benutzers anzeigen - + Add to &buddy list Zur &Freundesliste hinzufügen - + Remove from &buddy list Von &Freundesliste entfernen - + Add to &ignore list &Ignorieren - + Remove from &ignore list Nicht mehr &ignorieren - + Ban from &server Vom &Server bannen diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index e6cc82937..4c6421f19 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -230,202 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - + &Draw arrow... - + &Power / toughness - + &Increase power - + Ctrl++ - + &Decrease power - + Ctrl+- - + I&ncrease toughness - + Alt++ - + D&ecrease toughness - + Alt+- - + In&crease power and toughness - + Ctrl+Alt++ - + Dec&rease power and toughness - + Ctrl+Alt+- - + Set &power and toughness... - + Ctrl+P - + &Set annotation... - + red - + yellow - + green - + &Add counter (%1) - + &Remove counter (%1) - + &Set counters (%1)... - + &top of library - + &bottom of library - + &graveyard - + Ctrl+Del - + &exile - + &Move to @@ -1208,17 +1208,16 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate - + &Join - @@ -1226,76 +1225,77 @@ This is only saved for moderators and cannot be seen by the banned person. + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + J&oin as spectator @@ -1683,277 +1683,962 @@ Local version is %1, remote version is %2. MessageLogWidget - - Connecting to %1... - - - - - Disconnected from server. - - - - - Invalid password. - - - - - Protocol error. - - - - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - - - %1 is not ready to start the game any more. - - - - - %1 has restored connection to the game. - - - - - %1 has lost connection to the game. - - - - - %1 shuffles %2. - - - - - %1 rolls a %2 with a %3-sided die. - - - %1 draws %n card(s). - + %1 draws a card. %1 draws %n cards. - + + You have joined game #%1. + female + + + + + You have joined game #%1. + male + + + + + %1 has joined the game. + female + + + + + %1 has joined the game. + male + + + + + %1 has left the game. + female + + + + + %1 has left the game. + male + + + + + %1 has loaded a local deck. + female + + + + + %1 has loaded a local deck. + male + + + + + %1 has loaded deck #%2. + female + + + + + %1 has loaded deck #%2. + male + + + + + %1 is ready to start the game. + female + + + + + %1 is ready to start the game. + male + + + + + %1 is not ready to start the game any more. + female + + + + + %1 is not ready to start the game any more. + male + + + + + %1 has conceded the game. + female + + + + + %1 has conceded the game. + male + + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female + + + + + %1 shuffles %2. + male + + + + + %1 rolls a %2 with a %3-sided die. + female + + + + + %1 rolls a %2 with a %3-sided die. + male + + + + + %1 draws %n card(s). + female + + %1 draws a card. + %1 draws %n cards. + + + + + %1 draws %n card(s). + male + + %1 draws a card. + %1 draws %n cards. + + + + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - - - a card - + + + %1 takes a mulligan to %n. + female + + + + + + + + %1 takes a mulligan to %n. + male + + + + - + %1 flips %2 face-down. + female - + + %1 flips %2 face-down. + male + + + + %1 flips %2 face-up. + female - - %1 attaches %2 to %3's %4. + + %1 flips %2 face-up. + male - + + %1 destroys %2. + female + + + + + %1 destroys %2. + male + + + + %1 unattaches %2. + female - + + %1 unattaches %2. + male + + + + + %1 creates token: %2%3. + female + + + + + %1 creates token: %2%3. + male + + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + %1 places a %2 counter on %3 (now %4). + %1 places %n %2 counters on %3 (now %4). + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + %1 places a %2 counter on %3 (now %4). + %1 places %n %2 counters on %3 (now %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + %1 removes a %2 counter from %3 (now %4). + %1 removes %n %2 counters from %3 (now %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + %1 removes a %2 counter from %3 (now %4). + %1 removes %n %2 counters from %3 (now %4). + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + + + + + %1 sets counter %2 to %3 (%4%5). + male + + + + + %1 sets %2 to not untap normally. + female + + + + + %1 sets %2 to not untap normally. + male + + + + + %1 sets %2 to untap normally. + female + + + + + %1 sets %2 to untap normally. + male + + + + + %1 sets PT of %2 to %3. + female + + + + + %1 sets PT of %2 to %3. + male + + + + + %1 sets annotation of %2 to %3. + female + + + + + %1 sets annotation of %2 to %3. + male + + + + + %1 is looking at the top %2 cards %3. + female + + + + + %1 is looking at the top %2 cards %3. + male + + + + + %1 is looking at %2. + female + + + + + %1 is looking at %2. + male + + + + + %1 stops looking at %2. + female + + + + + %1 stops looking at %2. + male + + + + + %1 reveals %2 to %3. + p1 female, p2 female + + + + + %1 reveals %2 to %3. + p1 female, p2 male + + + + + %1 reveals %2 to %3. + p1 male, p2 female + + + + + %1 reveals %2 to %3. + p1 male, p2 male + + + + + %1 reveals %2. + female + + + + + %1 reveals %2. + male + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 randomly reveals %2%3. + female + + + + + %1 randomly reveals %2%3. + male + + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 reveals %2%3. + female + + + + + %1 reveals %2%3. + male + + + + + It is now %1's turn. + female + + + + + It is now %1's turn. + male + + + + + + a card @@ -1971,7 +2656,7 @@ Local version is %1, remote version is %2. - + red @@ -1979,7 +2664,7 @@ Local version is %1, remote version is %2. - + yellow @@ -1987,7 +2672,7 @@ Local version is %1, remote version is %2. - + green @@ -1995,264 +2680,118 @@ Local version is %1, remote version is %2. - - %1 sets counter %2 to %3 (%4%5). - - - - - %1 sets PT of %2 to %3. - - - - - %1 sets annotation of %2 to %3. - - - - - %1 is looking at the top %2 cards %3. - - - - + The game has started. - - Connected. - - - - - Protocol version mismatch. Client: %1, Server: %2 - - - - - You have joined game #%1. - - - - - %1 has joined the game. - - - - - %1 has left the game. - - - - - %1 has loaded a local deck. - - - - - %1 has loaded deck #%2. - - - - - %1 is ready to start the game. - - - - - %1 has conceded the game. - - - - - %1 takes a mulligan to %n. - - - - - - - + %1 draws his initial hand. - + %1 draws her initial hand. - - - %1 destroys %2. - - - - - %1 creates token: %2%3. - - - - - %1 points from %2's %3 to %4. - - - %1 places %n %2 counter(s) on %3 (now %4). - + %1 places a %2 counter on %3 (now %4). %1 places %n %2 counters on %3 (now %4). - %1 removes %n %2 counter(s) from %3 (now %4). - + %1 removes a %2 counter from %3 (now %4). %1 removes %n %2 counters from %3 (now %4). - - her permanents - - - - - %1 %2 %3. - - - - - %1 is looking at %2. - - - - - %1 stops looking at %2. - - - - - %1 reveals %2 to %3. - - - - - %1 reveals %2. - - - - + ending phase - - It is now %1's turn. - - - - - %1 randomly reveals %2%3 to %4. - - - - - %1 randomly reveals %2%3. - - - - - %1 reveals %2%3 to %4. - - - - - %1 reveals %2%3. - - - - + untap step - + + %1 attaches %2 to %3's %4. + p1 female, p2 female + + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + + + + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - - - taps - - - - - untaps - - - - - %1 sets %2 to not untap normally. - - - - - %1 sets %2 to untap normally. - - - - - his permanents - - MessagesSettingsPage @@ -3240,67 +3779,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + %1's games - + User &details - + Direct &chat - + Show this user's &games - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 100047e44..cee81068a 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -239,57 +239,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jugar - + &Hide &Ocultar - + &Tap &Girar - + &Untap &Enderezar - + Toggle &normal untapping Alternar enderezamiento &normal - + &Flip &Voltear - + &Clone &Clonar - + Ctrl+H Ctrl+H - + &Attach to card... Ane&xar a una carta... - + Ctrl+A Ctrl+A - + Unattac&h Desane&xar @@ -298,147 +298,147 @@ This is only saved for moderators and cannot be seen by the banned person.Establecer &F/R... - + &Draw arrow... - + &Power / toughness &Fuerza / resistencia - + &Increase power &Incrementar fuerza - + Ctrl++ Ctrl++ - + &Decrease power &Decrementar fuerza - + Ctrl+- Ctrl+- - + I&ncrease toughness I&ncrementar resistencia - + Alt++ Alt++ - + D&ecrease toughness D&ecrementar resistencia - + Alt+- Alt+- - + In&crease power and toughness In&crementar fuerza y resistencia - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Dec&rementar fuerza y resistencia - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Establecer &fuerza y resistencia... - + Ctrl+P Ctrl+P - + &Set annotation... E&scribir anotación... - + red rojo - + yellow amarillo - + green verde - + &Add counter (%1) &Añadir contador (%1) - + &Remove counter (%1) &Quitar contador (%1) - + &Set counters (%1)... E&stablecer contadores (%1)... - + &top of library &parte superior de la biblioteca - + &bottom of library &fondo de la biblioteca - + &graveyard &cementerio - + Ctrl+Del Ctrl+Del - + &exile &exilio - + &Move to &Mover a @@ -1570,17 +1570,16 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate C&rear - + &Join E&ntrar - @@ -1588,71 +1587,72 @@ This is only saved for moderators and cannot be seen by the banned person. + Error Error - + Please join the appropriate room first. - + Wrong password. Contraseña incorrecta. - + Spectators are not allowed in this game. No se permiten espectadores en esta partida. - + The game is already full. La partida no tiene plazas libres. - + The game does not exist any more. La partida ya no existe. - + This game is only open to registered users. Esta partida está abierta sólo a usuarios registrados. - + This game is only open to its creator's buddies. Esta partida está abierta sólo a los amigos del creador. - + You are being ignored by the creator of this game. Estas siendo ignorado por el creador de la partida. - + Join game Entrar en la partida - + Password: Contraseña: - + Games Partidas - + Show &full games Ver partidas &sin plazas libres - + Show &running games @@ -1661,7 +1661,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Ver partidas sin plazas libres - + J&oin as spectator Entrar como e&spectador @@ -2057,278 +2057,1041 @@ La versión local es %1, la versión remota es %2. MessageLogWidget - Connecting to %1... - Conectando a %1... + Conectando a %1... - Disconnected from server. - Desconectado del servidor. + Desconectado del servidor. - Invalid password. - Contraseña incorrecta. + Contraseña incorrecta. - Protocol error. - Error del protocolo. + Error del protocolo. - + The game has been closed. La partida ha sido cerrada. - + %1 is now watching the game. %1 está ahora observando la partida. - + %1 is not watching the game any more. %1 ya no está observado más la partida. - %1 is not ready to start the game any more. - %1 ya no está listo para empezar el juego. + %1 ya no está listo para empezar el juego. - - %1 has restored connection to the game. - - - - - %1 has lost connection to the game. - - - - - %1 shuffles %2. - - - - %1 rolls a %2 with a %3-sided die. - %1 sacó un %2 con un dado de %3 caras. + %1 sacó un %2 con un dado de %3 caras. - %1 draws %n card(s). - + %1 roba %n carta. %1 roba %n cartas. - + + You have joined game #%1. + female + Te has unido a la partida #%1. + + + + You have joined game #%1. + male + Te has unido a la partida #%1. + + + + %1 has joined the game. + female + %1 se ha unido a la partida. + + + + %1 has joined the game. + male + %1 se ha unido a la partida. + + + + %1 has left the game. + female + %1 ha dejado la partida. + + + + %1 has left the game. + male + %1 ha dejado la partida. + + + + %1 has loaded a local deck. + female + %1 ha cargado un mazo local. + + + + %1 has loaded a local deck. + male + %1 ha cargado un mazo local. + + + + %1 has loaded deck #%2. + female + %1 ha cargado el mazo #%2. + + + + %1 has loaded deck #%2. + male + %1 ha cargado el mazo #%2. + + + + %1 is ready to start the game. + female + %1 está preparado para empezar la partida. + + + + %1 is ready to start the game. + male + %1 está preparado para empezar la partida. + + + + %1 is not ready to start the game any more. + female + %1 ya no está listo para empezar el juego. + + + + %1 is not ready to start the game any more. + male + %1 ya no está listo para empezar el juego. + + + + %1 has conceded the game. + female + %1 ha concedido la partida. + + + + %1 has conceded the game. + male + %1 ha concedido la partida. + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female + + + + + %1 shuffles %2. + male + + + + + %1 rolls a %2 with a %3-sided die. + female + %1 sacó un %2 con un dado de %3 caras. + + + + %1 rolls a %2 with a %3-sided die. + male + %1 sacó un %2 con un dado de %3 caras. + + + + %1 draws %n card(s). + female + + %1 roba %n carta. + %1 roba %n cartas. + + + + + %1 draws %n card(s). + male + + %1 roba %n carta. + %1 roba %n cartas. + + + + %1 undoes his last draw. %1 deshace su último robo. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 deshace su último robo (%2). - + %1 undoes her last draw (%2). - + from table de la mesa - + from graveyard del cementerio - + from exile del exilio - + from hand de la mano - + the bottom card of his library el fondo de la biblioteca - + the bottom card of her library - + from the bottom of his library del fondo de la biblioteca - + from the bottom of her library - + the top card of his library la parte superior de la biblioteca - + the top card of her library - + from the top of his library de la parte superior de la biblioteca - + from the top of her library - + from library de la biblioteca - + from sideboard de la reserva - + from the stack de la pila - + %1 gives %2 control over %3. %1 entrega a %2 el control sobre %3. - + %1 puts %2 into play tapped%3. %1 pone %2 en juego%3 girado. - + %1 puts %2 into play%3. %1 pone %2 en juego%3. - + %1 puts %2%3 into graveyard. %1 pone %2%3 en el cementerio. - + %1 exiles %2%3. %1 exilia %2%3. - + %1 moves %2%3 to hand. %1 mueve %2%3 a la mano. - + %1 puts %2%3 into his library. %1 pone %2%3 en la biblioteca. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 pone %2%3 en la parte inferior de su biblioteca. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 pone %2%3 en la parte superior de su biblioteca. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 pone %2%3 en su biblioteca en la posición %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 mueve %2%3 a la reserva. - + %1 plays %2%3. %1 juega %2%3. + + + %1 takes a mulligan to %n. + female + + + + + + + + %1 takes a mulligan to %n. + male + + + + + - - + + %1 flips %2 face-down. + female + %1 voltea %2 boca abajo. + + + + %1 flips %2 face-down. + male + %1 voltea %2 boca abajo. + + + + %1 flips %2 face-up. + female + %1 voltea %2 boca arriba. + + + + %1 flips %2 face-up. + male + %1 voltea %2 boca arriba. + + + + %1 destroys %2. + female + %1 destruye %2. + + + + %1 destroys %2. + male + %1 destruye %2. + + + %1 attaches %2 to %3's %4. + female + %1 anexa %2 a el %4 de %3. + + + %1 attaches %2 to %3's %4. + male + %1 anexa %2 a el %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 female + %1 anexa %2 a el %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + %1 anexa %2 a el %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + %1 anexa %2 a el %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + %1 anexa %2 a el %4 de %3. + + + + %1 unattaches %2. + female + %1 desanexa %2. + + + + %1 unattaches %2. + male + %1 desanexa %2. + + + + %1 creates token: %2%3. + female + %1 crea una ficha: %2%3. + + + + %1 creates token: %2%3. + male + %1 crea una ficha: %2%3. + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + %1 apunta desde el %3 de %2 a %4. + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + %1 apunta desde el %3 de %2 al %5 de %4. + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + %1 pone %n %2 contador en %3 (ahora %4). + %1 pone %n %2 contadores en %3 (ahora %4). + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + %1 pone %n %2 contador en %3 (ahora %4). + %1 pone %n %2 contadores en %3 (ahora %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + %1 remueve %n %2 contador en %3 (ahora %4). + %1 remueve %n %2 contadores en %3 (ahora %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + %1 remueve %n %2 contador en %3 (ahora %4). + %1 remueve %n %2 contadores en %3 (ahora %4). + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + %1 establece los contadores de %2 a %3 (%4%5). + + + + %1 sets counter %2 to %3 (%4%5). + male + %1 establece los contadores de %2 a %3 (%4%5). + + + + %1 sets %2 to not untap normally. + female + %1 establece que %2 no se endereze normalmente. + + + + %1 sets %2 to not untap normally. + male + %1 establece que %2 no se endereze normalmente. + + + + %1 sets %2 to untap normally. + female + %1 establece que %2 se endereze normalmente. + + + + %1 sets %2 to untap normally. + male + %1 establece que %2 se endereze normalmente. + + + + %1 sets PT of %2 to %3. + female + %1 establece F/R de %2 a %3. + + + + %1 sets PT of %2 to %3. + male + %1 establece F/R de %2 a %3. + + + + %1 sets annotation of %2 to %3. + female + %1 establece la anotación de %2 a %3. + + + + %1 sets annotation of %2 to %3. + male + %1 establece la anotación de %2 a %3. + + + + %1 is looking at the top %2 cards %3. + female + %1 esta mirando las primeras %2 cartas de %3. + + + + %1 is looking at the top %2 cards %3. + male + %1 esta mirando las primeras %2 cartas de %3. + + + + %1 is looking at %2. + female + %1 está mirando: %2. + + + + %1 is looking at %2. + male + %1 está mirando: %2. + + + + %1 stops looking at %2. + female + %1 termina de mirar: %2. + + + + %1 stops looking at %2. + male + %1 termina de mirar: %2. + + + + %1 reveals %2 to %3. + p1 female, p2 female + %1 revela %2 a %3. + + + + %1 reveals %2 to %3. + p1 female, p2 male + %1 revela %2 a %3. + + + + %1 reveals %2 to %3. + p1 male, p2 female + %1 revela %2 a %3. + + + + %1 reveals %2 to %3. + p1 male, p2 male + %1 revela %2 a %3. + + + + %1 reveals %2. + female + %1 revela %2. + + + + %1 reveals %2. + male + %1 revela %2. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + %1 revela aleatoriamente %2%3 a %4. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + %1 revela aleatoriamente %2%3 a %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + %1 revela aleatoriamente %2%3 a %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + %1 revela aleatoriamente %2%3 a %4. + + + + %1 randomly reveals %2%3. + female + %1 revela aleatoriamente %2%3. + + + + %1 randomly reveals %2%3. + male + %1 revela aleatoriamente %2%3. + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + %1 revela %2%3 a %4. + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + %1 revela %2%3 a %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + %1 revela %2%3 a %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + %1 revela %2%3 a %4. + + + + %1 reveals %2%3. + female + %1 revela %2%3. + + + + %1 reveals %2%3. + male + %1 revela %2%3. + + + + It is now %1's turn. + female + Es el turno de %1. + + + + It is now %1's turn. + male + Es el turno de %1. + + + + a card una carta - %1 flips %2 face-down. - %1 voltea %2 boca abajo. + %1 voltea %2 boca abajo. - %1 flips %2 face-up. - %1 voltea %2 boca arriba. + %1 voltea %2 boca arriba. - %1 attaches %2 to %3's %4. - %1 anexa %2 a el %4 de %3. + %1 anexa %2 a el %4 de %3. - %1 unattaches %2. - %1 desanexa %2. + %1 desanexa %2. - %1 points from %2's %3 to %4's %5. - %1 apunta desde el %3 de %2 al %5 de %4. + %1 apunta desde el %3 de %2 al %5 de %4. %1 places %n counter(s) (%2) on %3 (now %4). @@ -2345,7 +3108,7 @@ La versión local es %1, la versión remota es %2. - + red rojo @@ -2353,7 +3116,7 @@ La versión local es %1, la versión remota es %2. - + yellow amarillo @@ -2361,7 +3124,7 @@ La versión local es %1, la versión remota es %2. - + green verde @@ -2369,74 +3132,61 @@ La versión local es %1, la versión remota es %2. - %1 sets counter %2 to %3 (%4%5). - %1 establece los contadores de %2 a %3 (%4%5). + %1 establece los contadores de %2 a %3 (%4%5). - %1 sets PT of %2 to %3. - %1 establece F/R de %2 a %3. + %1 establece F/R de %2 a %3. - %1 sets annotation of %2 to %3. - %1 establece la anotación de %2 a %3. + %1 establece la anotación de %2 a %3. - %1 is looking at the top %2 cards %3. - %1 esta mirando las primeras %2 cartas de %3. + %1 esta mirando las primeras %2 cartas de %3. - + The game has started. La partida ha comenzado. - Connected. - Conectado. + Conectado. - Protocol version mismatch. Client: %1, Server: %2 - La versión del protocolo es diferente. Cliente: %1, Servidor: %2 + La versión del protocolo es diferente. Cliente: %1, Servidor: %2 - You have joined game #%1. - Te has unido a la partida #%1. + Te has unido a la partida #%1. - %1 has joined the game. - %1 se ha unido a la partida. + %1 se ha unido a la partida. - %1 has left the game. - %1 ha dejado la partida. + %1 ha dejado la partida. - %1 has loaded a local deck. - %1 ha cargado un mazo local. + %1 ha cargado un mazo local. - %1 has loaded deck #%2. - %1 ha cargado el mazo #%2. + %1 ha cargado el mazo #%2. - %1 is ready to start the game. - %1 está preparado para empezar la partida. + %1 está preparado para empezar la partida. - %1 has conceded the game. - %1 ha concedido la partida. + %1 ha concedido la partida. %1 draws a card. @@ -2447,197 +3197,164 @@ La versión local es %1, la versión remota es %2. %1 roba %2 cartas. - %1 destroys %2. - %1 destruye %2. + %1 destruye %2. - %1 creates token: %2%3. - %1 crea una ficha: %2%3. + %1 crea una ficha: %2%3. - %1 points from %2's %3 to %4. - %1 apunta desde el %3 de %2 a %4. + %1 apunta desde el %3 de %2 a %4. - %1 places %n %2 counter(s) on %3 (now %4). - + %1 pone %n %2 contador en %3 (ahora %4). %1 pone %n %2 contadores en %3 (ahora %4). - %1 removes %n %2 counter(s) from %3 (now %4). - + %1 remueve %n %2 contador en %3 (ahora %4). %1 remueve %n %2 contadores en %3 (ahora %4). - %1 %2 %3. - %1 %2 %3. + %1 %2 %3. - %1 is looking at %2. - %1 está mirando: %2. + %1 está mirando: %2. - %1 stops looking at %2. - %1 termina de mirar: %2. + %1 termina de mirar: %2. - %1 reveals %2 to %3. - %1 revela %2 a %3. + %1 revela %2 a %3. - %1 reveals %2. - %1 revela %2. + %1 revela %2. - + ending phase fase de fin de turno - It is now %1's turn. - Es el turno de %1. + Es el turno de %1. %1 shuffles his library. %1 baraja su biblioteca. - - - %1 takes a mulligan to %n. - - - - - - + %1 draws his initial hand. - + %1 draws her initial hand. - - her permanents - - - - %1 randomly reveals %2%3 to %4. - %1 revela aleatoriamente %2%3 a %4. + %1 revela aleatoriamente %2%3 a %4. - %1 randomly reveals %2%3. - %1 revela aleatoriamente %2%3. + %1 revela aleatoriamente %2%3. - %1 reveals %2%3 to %4. - %1 revela %2%3 a %4. + %1 revela %2%3 a %4. - %1 reveals %2%3. - %1 revela %2%3. + %1 revela %2%3. - + untap step paso de enderezar - + upkeep step paso de mantenimiento - + draw step paso de robar - + first main phase primera fase principal - + beginning of combat step paso de inicio de combate - + declare attackers step paso de declarar atacantes - + declare blockers step paso de declarar bloqueadores - + combat damage step paso de daño de combate - + end of combat step paso de fin de combate - + second main phase segunda fase principal - + It is now the %1. Ahora es el %1. - taps - gira + gira - untaps - endereza + endereza - %1 sets %2 to not untap normally. - %1 establece que %2 no se endereze normalmente. + %1 establece que %2 no se endereze normalmente. - %1 sets %2 to untap normally. - %1 establece que %2 se endereze normalmente. + %1 establece que %2 se endereze normalmente. - his permanents - sus permanentes + sus permanentes @@ -3701,67 +4418,67 @@ Por favor, introduzca un nombre: UserList - + Users online: %1 Usuarios online: %1 - + Users in this room: %1 Usuarios en esta sala: %1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Usuarios ignorados online: %1 / %2 - + %1's games - + User &details &Detalles del usuario - + Direct &chat &Chat privado - + Show this user's &games - + Add to &buddy list Añadir a la lista de &amigos - + Remove from &buddy list Quitar de la lista de &amigos - + Add to &ignore list Añadir a la lista de &ignorados - + Remove from &ignore list Quitar de la lista de &ignorados - + Ban from &server Banear del &servidor diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 3c10129ca..301f32172 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -231,57 +231,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jouer - + &Hide &Cacher - + &Tap &Engager - + &Untap &Dégager - + Toggle &normal untapping Activer/ Désactiver le dégagement &normal - + &Flip &Retourner la carte - + &Clone &Copier une carte - + Ctrl+H - + &Attach to card... &Attacher à la carte... - + Ctrl+A Ctrl+A - + Unattac&h Détac&her @@ -290,147 +290,147 @@ This is only saved for moderators and cannot be seen by the banned person.Fixer &F/E... - + &Draw arrow... - + &Power / toughness F&orce / Endurance - + &Increase power &Augmenter force - + Ctrl++ Ctrl++ - + &Decrease power &Diminuer force - + Ctrl+- Ctrl+- - + I&ncrease toughness A&ugmenter endurance - + Alt++ Alt++ - + D&ecrease toughness D&iminuer endurance - + Alt+- Alt+- - + In&crease power and toughness Au&gmenter la force et l'endurance - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Di&minuer la force et l'endurance - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Fi&xer la force et l'endurance... - + Ctrl+P Ctrl+P - + &Set annotation... A&jouter note... - + red rouge - + yellow jaune - + green vert - + &Add counter (%1) &Ajouter compteur (%1) - + &Remove counter (%1) &Retirer compteur (%1) - + &Set counters (%1)... &Fixer marqueurs (%1)... - + &top of library dessus de la &Bibliothèque - + &bottom of library &dessous de la bibliothèque - + &graveyard &cimetière - + Ctrl+Del Ctrl+Del - + &exile &exiler - + &Move to &Aller @@ -1420,7 +1420,6 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - @@ -1428,71 +1427,72 @@ This is only saved for moderators and cannot be seen by the banned person. + Error Erreur - + Please join the appropriate room first. - + Wrong password. Mot de passe erroné. - + Spectators are not allowed in this game. Les spectateurs ne sont pas autorisés dans cette partie. - + The game is already full. Cette partie est déjà pleine. - + The game does not exist any more. La partie n'existe plus. - + This game is only open to registered users. Cette partie n'est accessible qu'aux joueurs enregistrés. - + This game is only open to its creator's buddies. Cette partie n'est accessible qu'aux amis. - + You are being ignored by the creator of this game. Vous avez été ignoré par le créateur de la partie. - + Join game Rejoindre partie - + Password: Mot de passe: - + Games Parties - + Show &full games Montrer &toutes les parties - + Show &running games @@ -1502,17 +1502,17 @@ This is only saved for moderators and cannot be seen by the banned person.&Montrer toutes les parties - + C&reate C&réer - + &Join Re&joindre - + J&oin as spectator Rej&oindre en tant que spectateur @@ -1914,93 +1914,79 @@ La version la plus récente est %1, l'ancienne version est %2. MessageLogWidget - Connecting to %1... - Connexion à %1... + Connexion à %1... - Connected. - Connecté. + Connecté. - Disconnected from server. - Déconnecté du serveur. + Déconnecté du serveur. - Invalid password. - Mot de passe invalide. + Mot de passe invalide. - Protocol version mismatch. Client: %1, Server: %2 - Version de protocole différente. Version locale: %1 ,version distante: %2 + Version de protocole différente. Version locale: %1 ,version distante: %2 - Protocol error. - Erreur de protocole. + Erreur de protocole. - You have joined game #%1. - Vous avez rejoint la partie #%1. + Vous avez rejoint la partie #%1. - %1 has joined the game. - %1 a rejoint la partie. + %1 a rejoint la partie. - %1 has left the game. - %1 a quitté la partie. + %1 a quitté la partie. - + The game has been closed. La partie a été fermée. - + %1 is now watching the game. %1 est maintenant spectateur. - + %1 is not watching the game any more. %1 n'est plus spectateur. - %1 has loaded a local deck. - %1 a chargé un deck local. + %1 a chargé un deck local. - %1 has loaded deck #%2. - %1 a chargé le deck #%2. + %1 a chargé le deck #%2. - %1 is ready to start the game. - %1 est prêt à démarrer la partie. + %1 est prêt à démarrer la partie. - %1 is not ready to start the game any more. - %1 n'est plus prêt à démarrer la partie. + %1 n'est plus prêt à démarrer la partie. - %1 has conceded the game. partie ou jeu - %1 a concédé la partie. + %1 a concédé la partie. - + The game has started. La partie commence. @@ -2009,10 +1995,9 @@ La version la plus récente est %1, l'ancienne version est %2.%1 mélange sa bibliothèque. - %1 rolls a %2 with a %3-sided die. is it always a dice? - %1 lance un %2 à %3 faces. + %1 lance un %2 à %3 faces. %1 draws a card. @@ -2023,213 +2008,331 @@ La version la plus récente est %1, l'ancienne version est %2.%1 pioche %2 cartes. - - from table - depuis le champ de bataille + + You have joined game #%1. + female + Vous avez rejoint la partie #%1. - - from graveyard - depuis son cimetière + + You have joined game #%1. + male + Vous avez rejoint la partie #%1. - - from exile - depuis la zone exil + + %1 has joined the game. + female + %1 a rejoint la partie. - - from hand - depuis sa main + + %1 has joined the game. + male + %1 a rejoint la partie. - - the bottom card of his library - la carte du dessous de sa bibliothèque + + %1 has left the game. + female + %1 a quitté la partie. - - the bottom card of her library + + %1 has left the game. + male + %1 a quitté la partie. + + + + %1 has loaded a local deck. + female + %1 a chargé un deck local. + + + + %1 has loaded a local deck. + male + %1 a chargé un deck local. + + + + %1 has loaded deck #%2. + female + %1 a chargé le deck #%2. + + + + %1 has loaded deck #%2. + male + %1 a chargé le deck #%2. + + + + %1 is ready to start the game. + female + %1 est prêt à démarrer la partie. + + + + %1 is ready to start the game. + male + %1 est prêt à démarrer la partie. + + + + %1 is not ready to start the game any more. + female + %1 n'est plus prêt à démarrer la partie. + + + + %1 is not ready to start the game any more. + male + %1 n'est plus prêt à démarrer la partie. + + + + %1 has conceded the game. + female + %1 a concédé la partie. + + + + %1 has conceded the game. + male + %1 a concédé la partie. + + + + %1 has restored connection to the game. + female - - from the bottom of his library - du dessous de sa bibliothèque - - - - from the bottom of her library + + %1 has restored connection to the game. + male - - the top card of his library - le carte du dessus de sa bibliothèque - - - - the top card of her library + + %1 has lost connection to the game. + female - - from the top of his library - du dessus de sa bibliothèque - - - - from the top of her library + + %1 has lost connection to the game. + male - - - from library - depuis sa bibliothèque - - - - from sideboard - depuis sa réserve - - - - from the stack - depuis la pile - - - - %1 puts %2 into play tapped%3. - %1 met %2 en jeu engagé%3. - - - - %1 puts %2 into play%3. - what is %3? plz exemple (resp. by Ranma : XX met island en jeu -depuis sa main-.) - %1 met %2 en jeu %3. - - - - %1 puts %2%3 into graveyard. - %1 met %2%3 dans son cimetière. - - - - %1 exiles %2%3. - %1 exile %2%3. - - - - %1 moves %2%3 to hand. - %1 met %2%3 dans sa main. - - - - %1 puts %2%3 into his library. - %1 met %2%3 dans sa bibliothèque. - - - - %1 puts %2%3 into her library. - - - - - %1 puts %2%3 on bottom of his library. - %1 met %2%3 en-dessous de sa bibliothèque. - - - - %1 puts %2%3 on bottom of her library. - - - - - %1 puts %2%3 on top of his library. - %1 met %2%3 au-dessus de sa bibliothèque. - - - - %1 puts %2%3 on top of her library. - - - - - %1 puts %2%3 into his library at position %4. - %1 met %2%3 dans sa bibliothèque à la position n°%4. - - - - %1 puts %2%3 into her library at position %4. - - - - - %1 moves %2%3 to sideboard. - %1 met %2%3 à sa réserve. - - - - %1 plays %2%3. - %1 joue %2%3. - - - - - a card - une carte - - %1 has restored connection to the game. + %1 shuffles %2. + female - %1 has lost connection to the game. + %1 shuffles %2. + male - - %1 shuffles %2. - + + %1 rolls a %2 with a %3-sided die. + female + %1 lance un %2 à %3 faces. + + + + %1 rolls a %2 with a %3-sided die. + male + %1 lance un %2 à %3 faces. - + %1 draws %n card(s). - + female + + %1 pioche %n carte. + %1 pioche %n cartes. + + + + + %1 draws %n card(s). + male + %1 pioche %n carte. %1 pioche %n cartes. - - %1 undoes his last draw. - %1 annule sa dernière pioche. + + from table + depuis le champ de bataille - - %1 undoes her last draw. + + from graveyard + depuis son cimetière + + + + from exile + depuis la zone exil + + + + from hand + depuis sa main + + + + the bottom card of his library + la carte du dessous de sa bibliothèque + + + + the bottom card of her library - - %1 undoes his last draw (%2). - %1 annule sa dernière pioche (%2). + + from the bottom of his library + du dessous de sa bibliothèque - - %1 undoes her last draw (%2). + + from the bottom of her library + + + the top card of his library + le carte du dessus de sa bibliothèque + + + + the top card of her library + + + + + from the top of his library + du dessus de sa bibliothèque + + + + from the top of her library + + + + + from library + depuis sa bibliothèque + + + + from sideboard + depuis sa réserve + + + + from the stack + depuis la pile + + + + %1 puts %2 into play tapped%3. + %1 met %2 en jeu engagé%3. + - %1 gives %2 control over %3. - %1 donne le contrôle de %2 à %3. + %1 puts %2 into play%3. + what is %3? plz exemple (resp. by Ranma : XX met island en jeu -depuis sa main-.) + %1 met %2 en jeu %3. + + + + %1 puts %2%3 into graveyard. + %1 met %2%3 dans son cimetière. + + + + %1 exiles %2%3. + %1 exile %2%3. + + + + %1 moves %2%3 to hand. + %1 met %2%3 dans sa main. + + + + %1 puts %2%3 into his library. + %1 met %2%3 dans sa bibliothèque. + + + + %1 puts %2%3 into her library. + + + + + %1 puts %2%3 on bottom of his library. + %1 met %2%3 en-dessous de sa bibliothèque. + + + + %1 puts %2%3 on bottom of her library. + + + + + %1 puts %2%3 on top of his library. + %1 met %2%3 au-dessus de sa bibliothèque. + + + + %1 puts %2%3 on top of her library. + + + + + %1 puts %2%3 into his library at position %4. + %1 met %2%3 dans sa bibliothèque à la position n°%4. + + + + %1 puts %2%3 into her library at position %4. + + + + + %1 moves %2%3 to sideboard. + %1 met %2%3 à sa réserve. + + + + %1 plays %2%3. + %1 joue %2%3. - + %1 takes a mulligan to %n. + female + + + + + + + + %1 takes a mulligan to %n. + male @@ -2237,56 +2340,696 @@ La version la plus récente est %1, l'ancienne version est %2. + %1 flips %2 face-down. + female + %1 retourne %2 face cachée. + + + + %1 flips %2 face-down. + male + %1 retourne %2 face cachée. + + + + %1 flips %2 face-up. + female + %1 retourne %2 face visible. + + + + %1 flips %2 face-up. + male + %1 retourne %2 face visible. + + + + %1 destroys %2. + female + %1 détruit %2. + + + + %1 destroys %2. + male + %1 détruit %2. + + + %1 attaches %2 to %3's %4. + female + %1 attache %2 sur %4 de %3. + + + %1 attaches %2 to %3's %4. + male + %1 attache %2 sur %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 female + %1 attache %2 sur %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + %1 attache %2 sur %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + %1 attache %2 sur %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + %1 attache %2 sur %4 de %3. + + + + %1 unattaches %2. + female + %1 détache %2. + + + + %1 unattaches %2. + male + %1 détache %2. + + + + %1 creates token: %2%3. + female + %1 crée un jeton %2%3. + + + + %1 creates token: %2%3. + male + %1 crée un jeton %2%3. + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + %1 désigne le %3 de %2 à %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + %1 désigne le %3 de %2 à %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + %1 désigne le %3 de %2 à %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + %1 désigne le %3 de %2 à %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + %1 désigne le %3 de %2 à %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + %1 désigne le %3 de %2 à %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + %1 désigne le %3 de %2 à %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + %1 désigne le %3 de %2 à %4. + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + %1 désigne le %3 de %2 à %5 de %4. + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + %1 met %n %2 marqueur sur %3 (maintenant %4). + %1 met %n %2 marqueurs sur %3 (maintenant %4). + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + %1 met %n %2 marqueur sur %3 (maintenant %4). + %1 met %n %2 marqueurs sur %3 (maintenant %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + %1 retire %n %2 marqueur de %3 (maintenant %4). + %1 retire %n %2 marqueurs de %3 (maintenant %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + %1 retire %n %2 marqueur de %3 (maintenant %4). + %1 retire %n %2 marqueurs de %3 (maintenant %4). + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + %1 met les marqueurs %2 à %3 (%4%5). + + + + %1 sets counter %2 to %3 (%4%5). + male + %1 met les marqueurs %2 à %3 (%4%5). + + + + %1 sets %2 to not untap normally. + female + %2 de %1 ne se dégagera pas lors de l'étape de dégagement. + + + + %1 sets %2 to not untap normally. + male + %2 de %1 ne se dégagera pas lors de l'étape de dégagement. + + + + %1 sets %2 to untap normally. + female + %2 de %1 se dégagera lors de l'étape de dégagement. + + + + %1 sets %2 to untap normally. + male + %2 de %1 se dégagera lors de l'étape de dégagement. + + + + %1 sets PT of %2 to %3. + female + %1 change la F/E de %2 à %3. + + + + %1 sets PT of %2 to %3. + male + %1 change la F/E de %2 à %3. + + + + %1 sets annotation of %2 to %3. + female + %1 met l'annotation %3 à %2. + + + + %1 sets annotation of %2 to %3. + male + %1 met l'annotation %3 à %2. + + + + %1 is looking at the top %2 cards %3. + female + %1 regarde les %2 cartes du dessus %3. + + + + %1 is looking at the top %2 cards %3. + male + %1 regarde les %2 cartes du dessus %3. + + + + %1 is looking at %2. + female + %1 regarde %2. + + + + %1 is looking at %2. + male + %1 regarde %2. + + + + %1 stops looking at %2. + female + %1 arrête de regarder %2. + + + + %1 stops looking at %2. + male + %1 arrête de regarder %2. + + + + %1 reveals %2 to %3. + p1 female, p2 female + %1 révèle %2 à %3. + + + + %1 reveals %2 to %3. + p1 female, p2 male + %1 révèle %2 à %3. + + + + %1 reveals %2 to %3. + p1 male, p2 female + %1 révèle %2 à %3. + + + + %1 reveals %2 to %3. + p1 male, p2 male + %1 révèle %2 à %3. + + + + %1 reveals %2. + female + %1 révèle %2. + + + + %1 reveals %2. + male + %1 révèle %2. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + %1 révèle au hasard %2%3 à %4. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + %1 révèle au hasard %2%3 à %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + %1 révèle au hasard %2%3 à %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + %1 révèle au hasard %2%3 à %4. + + + + %1 randomly reveals %2%3. + female + %1 révèle au hasard %2%3. + + + + %1 randomly reveals %2%3. + male + %1 révèle au hasard %2%3. + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + %1 révèle %2%3 à %4. + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + %1 révèle %2%3 à %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + %1 révèle %2%3 à %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + %1 révèle %2%3 à %4. + + + + %1 reveals %2%3. + female + %1 révèle %2%3. + + + + %1 reveals %2%3. + male + %1 révèle %2%3. + + + + It is now %1's turn. + female + C'est maintenant le tour de %1. + + + + It is now %1's turn. + male + C'est maintenant le tour de %1. + + + + + a card + une carte + + + %1 draws %n card(s). + + %1 pioche %n carte. + %1 pioche %n cartes. + + + + + %1 undoes his last draw. + %1 annule sa dernière pioche. + + + + %1 undoes her last draw. + + + + + %1 undoes his last draw (%2). + %1 annule sa dernière pioche (%2). + + + + %1 undoes her last draw (%2). + + + + + %1 gives %2 control over %3. + %1 donne le contrôle de %2 à %3. + + + %1 draws his initial hand. - + %1 draws her initial hand. - %1 flips %2 face-down. - %1 retourne %2 face cachée. + %1 retourne %2 face cachée. - %1 flips %2 face-up. - %1 retourne %2 face visible. + %1 retourne %2 face visible. - %1 destroys %2. - %1 détruit %2. + %1 détruit %2. - %1 attaches %2 to %3's %4. need exemple (Resp'.by Ranma: JoueurA attache Adventuring Gear sur -Plated Geopede- de -JoueurB-.) - %1 attache %2 sur %4 de %3. + %1 attache %2 sur %4 de %3. - %1 unattaches %2. - %1 détache %2. + %1 détache %2. - %1 creates token: %2%3. - %1 crée un jeton %2%3. + %1 crée un jeton %2%3. - %1 points from %2's %3 to %4. need exemple - %1 désigne le %3 de %2 à %4. + %1 désigne le %3 de %2 à %4. - %1 points from %2's %3 to %4's %5. need exemple - %1 désigne le %3 de %2 à %5 de %4. + %1 désigne le %3 de %2 à %5 de %4. %1 places %n counter(s) (%2) on %3 (now %4). @@ -2305,23 +3048,21 @@ La version la plus récente est %1, l'ancienne version est %2. - %1 places %n %2 counter(s) on %3 (now %4). - + %1 met %n %2 marqueur sur %3 (maintenant %4). %1 met %n %2 marqueurs sur %3 (maintenant %4). - %1 removes %n %2 counter(s) from %3 (now %4). - + %1 retire %n %2 marqueur de %3 (maintenant %4). %1 retire %n %2 marqueurs de %3 (maintenant %4). - + red rouge @@ -2329,7 +3070,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + yellow jaune @@ -2337,7 +3078,7 @@ La version la plus récente est %1, l'ancienne version est %2. - + green vert @@ -2345,169 +3086,145 @@ La version la plus récente est %1, l'ancienne version est %2. - his permanents - ses permanents + ses permanents - - her permanents - - - - %1 %2 %3. wtf ? - %1 %2 %3. + %1 %2 %3. - taps - engage + engage - untaps - dégage + dégage - %1 sets counter %2 to %3 (%4%5). need exemple - %1 met les marqueurs %2 à %3 (%4%5). + %1 met les marqueurs %2 à %3 (%4%5). - %1 sets %2 to not untap normally. need exemple - %2 de %1 ne se dégagera pas lors de l'étape de dégagement. + %2 de %1 ne se dégagera pas lors de l'étape de dégagement. - %1 sets %2 to untap normally. - %2 de %1 se dégagera lors de l'étape de dégagement. + %2 de %1 se dégagera lors de l'étape de dégagement. - %1 sets PT of %2 to %3. exemple plz - %1 change la F/E de %2 à %3. + %1 change la F/E de %2 à %3. - %1 sets annotation of %2 to %3. - %1 met l'annotation %3 à %2. + %1 met l'annotation %3 à %2. - %1 is looking at the top %2 cards %3. exemple plz - %1 regarde les %2 cartes du dessus %3. + %1 regarde les %2 cartes du dessus %3. - %1 is looking at %2. exemple plz - %1 regarde %2. + %1 regarde %2. - %1 stops looking at %2. need exemple to be sure - %1 arrête de regarder %2. + %1 arrête de regarder %2. - %1 reveals %2 to %3. - %1 révèle %2 à %3. + %1 révèle %2 à %3. - %1 reveals %2. - %1 révèle %2. + %1 révèle %2. - %1 randomly reveals %2%3 to %4. - %1 révèle au hasard %2%3 à %4. + %1 révèle au hasard %2%3 à %4. - %1 randomly reveals %2%3. - %1 révèle au hasard %2%3. + %1 révèle au hasard %2%3. - %1 reveals %2%3 to %4. - %1 révèle %2%3 à %4. + %1 révèle %2%3 à %4. - %1 reveals %2%3. - %1 révèle %2%3. + %1 révèle %2%3. - It is now %1's turn. - C'est maintenant le tour de %1. + C'est maintenant le tour de %1. - + untap step étape de dégagement - + upkeep step étape d'entretien - + draw step étape de pioche - + first main phase première phase principale - + beginning of combat step étape de début du combat - + declare attackers step étape de déclaration des attaquants - + declare blockers step étape de déclaration des bloqueurs - + combat damage step étape de répartition et de résolution des blessures - + end of combat step étape de fin de combat - + second main phase seconde phase principale - + ending phase phase de fin de tour - + It is now the %1. need exemple C'est maintenant %1. @@ -3562,67 +4279,67 @@ Entrez un nom s'il vous plaît: UserList - + Users online: %1 Utilisateurs en ligne:%1 - + Users in this room: %1 Utilisateurs dans ce salon: %1 - + Buddies online: %1 / %2 Amis connectés; %1 / %2 - + Ignored users online: %1 / %2 Personnes sur liste noire connectés: %1 / %2 - + %1's games - + User &details &Détails utilisateur - + Direct &chat &Chat direct - + Show this user's &games - + Add to &buddy list Ajouter à la liste d'&amis - + Remove from &buddy list Retirer de la liste d'&amis - + Add to &ignore list Ajouter à la liste &noire - + Remove from &ignore list Retirer de la liste &noire - + Ban from &server Bannir du &serveur diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index 5bd20b46a..5470b7724 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -235,58 +235,58 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play プレイ - + &Hide テスト版のため確認取れず再度チェック 裏にしてプレイ - + &Tap タップ - + &Untap アンタップ - + Toggle &normal untapping 通常のアンタップをしない - + &Flip 裏にする - + &Clone 複製する - + Ctrl+H - + &Attach to card... カードに付ける... - + Ctrl+A - + Unattac&h 取り外す @@ -295,147 +295,147 @@ This is only saved for moderators and cannot be seen by the banned person.P/Tを決める... - + &Draw arrow... - + &Power / toughness パワー / タフネス - + &Increase power パワーを上げる - + Ctrl++ - + &Decrease power パワーを下げる - + Ctrl+- - + I&ncrease toughness タフネスを上げる - + Alt++ - + D&ecrease toughness タフネスを下げる - + Alt+- - + In&crease power and toughness パワーとタフネスを上げる - + Ctrl+Alt++ - + Dec&rease power and toughness パワーとタフネスを下げる - + Ctrl+Alt+- - + Set &power and toughness... パワーとタフネスを設定する... - + Ctrl+P - + &Set annotation... 注釈を付ける... - + red - + yellow - + green - + &Add counter (%1) カウンターを乗せる (%1) - + &Remove counter (%1) カウンターを取り除く (%1) - + &Set counters (%1)... カウンターの数を決める (%1)... - + &top of library ライブラリーの一番上へ - + &bottom of library ライブラリーの一番下へ - + &graveyard 墓地へ - + Ctrl+Del - + &exile 追放領域へ - + &Move to 移動させる @@ -1256,17 +1256,16 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate 部屋を作る - + &Join 参加する - @@ -1274,71 +1273,72 @@ This is only saved for moderators and cannot be seen by the banned person. + Error エラー - + Please join the appropriate room first. - + Wrong password. パスワードが間違っています. - + Spectators are not allowed in this game. この試合は観戦者は許可されていません. - + The game is already full. このゲームはすでに満員です. - + The game does not exist any more. このゲームはもう存在しません. - + This game is only open to registered users. このゲームは登録済みプレイヤーにのみ公開されています. - + This game is only open to its creator's buddies. このゲームは作成者のフレンドのみに公開されています. - + You are being ignored by the creator of this game. あなたはこのゲームの作成者によって拒否されています. - + Join game 参加 - + Password: パスワード: - + Games ゲーム - + Show &full games 全てのゲームを見る - + Show &running games @@ -1347,7 +1347,7 @@ This is only saved for moderators and cannot be seen by the banned person.全てのゲームを見る - + J&oin as spectator 観戦者として参加 @@ -1739,276 +1739,947 @@ Local version is %1, remote version is %2. MessageLogWidget - - Connecting to %1... - - - - - Disconnected from server. - - - - - Invalid password. - - - - - Protocol error. - - - - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - + + You have joined game #%1. + female + + + + + You have joined game #%1. + male + + + + + %1 has joined the game. + female + + + + + %1 has joined the game. + male + + + + + %1 has left the game. + female + + + + + %1 has left the game. + male + + + + + %1 has loaded a local deck. + female + + + + + %1 has loaded a local deck. + male + + + + + %1 has loaded deck #%2. + female + + + + + %1 has loaded deck #%2. + male + + + + + %1 is ready to start the game. + female + + + + + %1 is ready to start the game. + male + + + + %1 is not ready to start the game any more. - + female + + + + + %1 is not ready to start the game any more. + male + + + + + %1 has conceded the game. + female + + + + + %1 has conceded the game. + male + + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + - %1 has restored connection to the game. + %1 shuffles %2. + female - %1 has lost connection to the game. - - - - %1 shuffles %2. + male - + %1 rolls a %2 with a %3-sided die. - + female + + + + + %1 rolls a %2 with a %3-sided die. + male + - + %1 draws %n card(s). - + female + + + + + + + %1 draws %n card(s). + male + - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - - - - a card - + + + %1 takes a mulligan to %n. + female + + + + + + + %1 takes a mulligan to %n. + male + + + - + %1 flips %2 face-down. - + female + - + + %1 flips %2 face-down. + male + + + + %1 flips %2 face-up. - + female + - - %1 attaches %2 to %3's %4. - + + %1 flips %2 face-up. + male + - + + %1 destroys %2. + female + + + + + %1 destroys %2. + male + + + + %1 unattaches %2. - + female + - + + %1 unattaches %2. + male + + + + + %1 creates token: %2%3. + female + + + + + %1 creates token: %2%3. + male + + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + + + + + %1 sets counter %2 to %3 (%4%5). + male + + + + + %1 sets %2 to not untap normally. + female + + + + + %1 sets %2 to not untap normally. + male + + + + + %1 sets %2 to untap normally. + female + + + + + %1 sets %2 to untap normally. + male + + + + + %1 sets PT of %2 to %3. + female + + + + + %1 sets PT of %2 to %3. + male + + + + + %1 sets annotation of %2 to %3. + female + + + + + %1 sets annotation of %2 to %3. + male + + + + + %1 is looking at the top %2 cards %3. + female + + + + + %1 is looking at the top %2 cards %3. + male + + + + + %1 is looking at %2. + female + + + + + %1 is looking at %2. + male + + + + + %1 stops looking at %2. + female + + + + + %1 stops looking at %2. + male + + + + + %1 reveals %2 to %3. + p1 female, p2 female + + + + + %1 reveals %2 to %3. + p1 female, p2 male + + + + + %1 reveals %2 to %3. + p1 male, p2 female + + + + + %1 reveals %2 to %3. + p1 male, p2 male + + + + + %1 reveals %2. + female + + + + + %1 reveals %2. + male + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 randomly reveals %2%3. + female + + + + + %1 randomly reveals %2%3. + male + + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 reveals %2%3. + female + + + + + %1 reveals %2%3. + male + + + + + It is now %1's turn. + female + + + + + It is now %1's turn. + male + + + + + + a card @@ -2024,282 +2695,125 @@ Local version is %1, remote version is %2. - + red - + yellow - + green - - %1 sets counter %2 to %3 (%4%5). - - - - - %1 sets PT of %2 to %3. - - - - - %1 sets annotation of %2 to %3. - - - - - %1 is looking at the top %2 cards %3. - - - - + The game has started. - - Connected. - - - - - Protocol version mismatch. Client: %1, Server: %2 - - - - - You have joined game #%1. - - - - - %1 has joined the game. - - - - - %1 has left the game. - - - - - %1 has loaded a local deck. - - - - - %1 has loaded deck #%2. - - - - - %1 is ready to start the game. - - - - - %1 has conceded the game. - - - - - %1 takes a mulligan to %n. - - - - - - + %1 draws his initial hand. - + %1 draws her initial hand. - - %1 destroys %2. - - - - - %1 creates token: %2%3. - - - - - %1 points from %2's %3 to %4. - - - - - %1 places %n %2 counter(s) on %3 (now %4). - - - - - - - %1 removes %n %2 counter(s) from %3 (now %4). - - - - - - - her permanents - - - - - %1 %2 %3. - - - - - %1 is looking at %2. - - - - - %1 stops looking at %2. - - - - - %1 reveals %2 to %3. - - - - - %1 reveals %2. - - - - + ending phase - - It is now %1's turn. - - - - - %1 randomly reveals %2%3 to %4. - - - - - %1 randomly reveals %2%3. - - - - - %1 reveals %2%3 to %4. - - - - - %1 reveals %2%3. - - - - + untap step - + + %1 attaches %2 to %3's %4. + p1 female, p2 female + + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + + + + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + It is now the %1. - - - taps - - - - - untaps - - - - - %1 sets %2 to not untap normally. - - - - - %1 sets %2 to untap normally. - - - - - his permanents - - MessagesSettingsPage @@ -3337,67 +3851,67 @@ Please enter a name: UserList - + Users online: %1 ユーザー オンライン: %1 - + Users in this room: %1 部屋のユーザー数: %1 - + Buddies online: %1 / %2 フレンドオンライン: %1 / %2 - + Ignored users online: %1 / %2 無視ユーザーオンライン: %1 / %2 - + %1's games - + User &details ユーザー補足 - + Direct &chat 個人チャット - + Show this user's &games - + Add to &buddy list フレンドリストに追加 - + Remove from &buddy list フレンドリストから削除 - + Add to &ignore list 無視リストに追加 - + Remove from &ignore list 無視リストから削除 - + Ban from &server サーバーからバンする diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 2994392ac..f13d9e828 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -230,202 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - + &Draw arrow... - + &Power / toughness - + &Increase power - + Ctrl++ - + &Decrease power - + Ctrl+- - + I&ncrease toughness - + Alt++ - + D&ecrease toughness - + Alt+- - + In&crease power and toughness - + Ctrl+Alt++ - + Dec&rease power and toughness - + Ctrl+Alt+- - + Set &power and toughness... - + Ctrl+P - + &Set annotation... - + red - + yellow - + green - + &Add counter (%1) - + &Remove counter (%1) - + &Set counters (%1)... - + &top of library - + &bottom of library - + &graveyard - + Ctrl+Del - + &exile - + &Move to @@ -1208,7 +1208,6 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - @@ -1216,86 +1215,87 @@ This is only saved for moderators and cannot be seen by the banned person. + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + C&reate - + &Join - + J&oin as spectator @@ -1684,118 +1684,183 @@ Local version is %1, remote version is %2. MessageLogWidget - - Connecting to %1... - - - - - Connected. - - - - - Disconnected from server. - - - - - Invalid password. - - - - - Protocol version mismatch. Client: %1, Server: %2 - - - - - Protocol error. - - - - - You have joined game #%1. - - - - - %1 has joined the game. - - - - - %1 has left the game. - - - - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - - %1 has loaded a local deck. - - - - - %1 has loaded deck #%2. - - - - - %1 is ready to start the game. - - - - - %1 is not ready to start the game any more. - - - - - %1 has conceded the game. - - - - + The game has started. - + + You have joined game #%1. + female + + + + + You have joined game #%1. + male + + + + + %1 has joined the game. + female + + + + + %1 has joined the game. + male + + + + + %1 has left the game. + female + + + + + %1 has left the game. + male + + + + + %1 has loaded a local deck. + female + + + + + %1 has loaded a local deck. + male + + + + + %1 has loaded deck #%2. + female + + + + + %1 has loaded deck #%2. + male + + + + + %1 is ready to start the game. + female + + + + + %1 is ready to start the game. + male + + + + + %1 is not ready to start the game any more. + female + + + + + %1 is not ready to start the game any more. + male + + + + + %1 has conceded the game. + female + + + + + %1 has conceded the game. + male + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female - %1 has lost connection to the game. - - - - %1 shuffles %2. + male - + %1 rolls a %2 with a %3-sided die. + female + + + + + %1 rolls a %2 with a %3-sided die. + male - + %1 draws %n card(s). + female + + + + + + + + + %1 draws %n card(s). + male @@ -1803,189 +1868,200 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. + female + + + + + + + + + %1 takes a mulligan to %n. + male @@ -1994,74 +2070,620 @@ Local version is %1, remote version is %2. + %1 flips %2 face-down. + female + + + + + %1 flips %2 face-down. + male + + + + + %1 flips %2 face-up. + female + + + + + %1 flips %2 face-up. + male + + + + + %1 destroys %2. + female + + + + + %1 destroys %2. + male + + + + + %1 unattaches %2. + female + + + + + %1 unattaches %2. + male + + + + + %1 creates token: %2%3. + female + + + + + %1 creates token: %2%3. + male + + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + + + + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + + + + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + + + + + %1 sets counter %2 to %3 (%4%5). + male + + + + + %1 sets %2 to not untap normally. + female + + + + + %1 sets %2 to not untap normally. + male + + + + + %1 sets %2 to untap normally. + female + + + + + %1 sets %2 to untap normally. + male + + + + + %1 sets PT of %2 to %3. + female + + + + + %1 sets PT of %2 to %3. + male + + + + + %1 sets annotation of %2 to %3. + female + + + + + %1 sets annotation of %2 to %3. + male + + + + + %1 is looking at the top %2 cards %3. + female + + + + + %1 is looking at the top %2 cards %3. + male + + + + + %1 is looking at %2. + female + + + + + %1 is looking at %2. + male + + + + + %1 stops looking at %2. + female + + + + + %1 stops looking at %2. + male + + + + + %1 reveals %2 to %3. + p1 female, p2 female + + + + + %1 reveals %2 to %3. + p1 female, p2 male + + + + + %1 reveals %2 to %3. + p1 male, p2 female + + + + + %1 reveals %2 to %3. + p1 male, p2 male + + + + + %1 reveals %2. + female + + + + + %1 reveals %2. + male + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 randomly reveals %2%3. + female + + + + + %1 randomly reveals %2%3. + male + + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 reveals %2%3. + female + + + + + %1 reveals %2%3. + male + + + + + It is now %1's turn. + female + + + + + It is now %1's turn. + male + + + + %1 draws his initial hand. - + %1 draws her initial hand. - - %1 flips %2 face-down. - - - - - %1 flips %2 face-up. - - - - - %1 destroys %2. - - - - + %1 attaches %2 to %3's %4. + p1 female, p2 female - - %1 unattaches %2. + + %1 attaches %2 to %3's %4. + p1 female, p2 male - - %1 creates token: %2%3. + + %1 attaches %2 to %3's %4. + p1 male, p2 female - - %1 points from %2's %3 to %4. - - - - - %1 points from %2's %3 to %4's %5. + + %1 attaches %2 to %3's %4. + p1 male, p2 male - - %1 places %n %2 counter(s) on %3 (now %4). - - - - - - - - - %1 removes %n %2 counter(s) from %3 (now %4). - - - - - - - - + red @@ -2070,7 +2692,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2079,7 +2701,7 @@ Local version is %1, remote version is %2. - + green @@ -2088,162 +2710,62 @@ Local version is %1, remote version is %2. - - his permanents - - - - - her permanents - - - - - %1 %2 %3. - - - - - taps - - - - - untaps - - - - - %1 sets counter %2 to %3 (%4%5). - - - - - %1 sets %2 to not untap normally. - - - - - %1 sets %2 to untap normally. - - - - - %1 sets PT of %2 to %3. - - - - - %1 sets annotation of %2 to %3. - - - - - %1 is looking at the top %2 cards %3. - - - - - %1 is looking at %2. - - - - - %1 stops looking at %2. - - - - - %1 reveals %2 to %3. - - - - - %1 reveals %2. - - - - - %1 randomly reveals %2%3 to %4. - - - - - %1 randomly reveals %2%3. - - - - - %1 reveals %2%3 to %4. - - - - - %1 reveals %2%3. - - - - - It is now %1's turn. - - - - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -3234,67 +3756,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + %1's games - + User &details - + Direct &chat - + Show this user's &games - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 7f4c14cb9..9c018f044 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -235,57 +235,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jogar - + &Hide &Ocultar - + &Tap &Virar - + &Untap &Desvirar - + Toggle &normal untapping &Trocar o modo de desvirar - + &Flip Virar a &face - + &Clone Clo&nar - + Ctrl+H Ctrl+H - + &Attach to card... Ane&xar ao card... - + Ctrl+A Ctrl+A - + Unattac&h De&sanexar @@ -294,147 +294,147 @@ This is only saved for moderators and cannot be seen by the banned person.Alterar &P/R... - + &Draw arrow... - + &Power / toughness Po&der / resistência - + &Increase power Au&mentar poder - + Ctrl++ Ctrl++ - + &Decrease power Dimi&nuir poder - + Ctrl+- Ctrl+- - + I&ncrease toughness A&umentar resistência - + Alt++ Alt++ - + D&ecrease toughness D&iminuir resistência - + Alt+- Alt+- - + In&crease power and toughness Aumen&tar poder e resistência - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Diminuir p&oder e resistência - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Alterar poder e resis&tência... - + Ctrl+P Ctrl+P - + &Set annotation... Alterar &nota... - + red vermelho - + yellow amarelo - + green verde - + &Add counter (%1) Adicionar &marcador (%1) - + &Remove counter (%1) &Remover marcador (%1) - + &Set counters (%1)... &Alterar marcadores (%1)... - + &top of library topo do &grimório - + &bottom of library &fundo do grimório - + &graveyard &cemitério - + Ctrl+Del Ctrl+Del - + &exile &exílio - + &Move to Mo&ver para @@ -1424,17 +1424,16 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - + C&reate &Criar - + &Join &Entrar - @@ -1442,71 +1441,72 @@ This is only saved for moderators and cannot be seen by the banned person. + Error Erro - + Please join the appropriate room first. - + Wrong password. Senha incorreta. - + Spectators are not allowed in this game. Não são permitidos visitantes neste jogo. - + The game is already full. O jogo está cheio. - + The game does not exist any more. O jogo não existe mais. - + This game is only open to registered users. Este jogo é aberto apenas para usuários registrados. - + This game is only open to its creator's buddies. Este jogo é aberto apenas para os amigos de quem criou o jogo. - + You are being ignored by the creator of this game. Você está sendo ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Senha: - + Games Jogos - + Show &full games &Mostrar os jogos cheios - + Show &running games @@ -1515,7 +1515,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Mostrar os jogos cheios - + J&oin as spectator E&ntrar como visitante @@ -1915,278 +1915,1041 @@ A versão local é %1 e a versão remota é %2. MessageLogWidget - Connecting to %1... - Conectando a %1... + Conectando a %1... - Disconnected from server. - Desconectado do servidor. + Desconectado do servidor. - Invalid password. - Senha incorreta. + Senha incorreta. - Protocol error. - Erro de protocolo. + Erro de protocolo. - + The game has been closed. O jogo foi fechado. - + %1 is now watching the game. %1 está assistindo o jogo agora. - + %1 is not watching the game any more. %1 não está mais assistindo o jogo. - %1 is not ready to start the game any more. - %1 não está mais pronto para começar o jogo. + %1 não está mais pronto para começar o jogo. - - %1 has restored connection to the game. - - - - - %1 has lost connection to the game. - - - - - %1 shuffles %2. - - - - %1 rolls a %2 with a %3-sided die. - %1 tirou um %2 com um dado de %3 lados. + %1 tirou um %2 com um dado de %3 lados. - %1 draws %n card(s). - + %1 compra %n card. %1 compra %n cards. - + + You have joined game #%1. + female + Você entrou no jogo nº %1. + + + + You have joined game #%1. + male + Você entrou no jogo nº %1. + + + + %1 has joined the game. + female + %1 entrou no jogo. + + + + %1 has joined the game. + male + %1 entrou no jogo. + + + + %1 has left the game. + female + %1 saiu do jogo. + + + + %1 has left the game. + male + %1 saiu do jogo. + + + + %1 has loaded a local deck. + female + %1 carregou um deck local. + + + + %1 has loaded a local deck. + male + %1 carregou um deck local. + + + + %1 has loaded deck #%2. + female + %1 carregou o deck nº %2. + + + + %1 has loaded deck #%2. + male + %1 carregou o deck nº %2. + + + + %1 is ready to start the game. + female + %1 está pronto para começar o jogo. + + + + %1 is ready to start the game. + male + %1 está pronto para começar o jogo. + + + + %1 is not ready to start the game any more. + female + %1 não está mais pronto para começar o jogo. + + + + %1 is not ready to start the game any more. + male + %1 não está mais pronto para começar o jogo. + + + + %1 has conceded the game. + female + %1 concedeu o jogo. + + + + %1 has conceded the game. + male + %1 concedeu o jogo. + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female + + + + + %1 shuffles %2. + male + + + + + %1 rolls a %2 with a %3-sided die. + female + %1 tirou um %2 com um dado de %3 lados. + + + + %1 rolls a %2 with a %3-sided die. + male + %1 tirou um %2 com um dado de %3 lados. + + + + %1 draws %n card(s). + female + + %1 compra %n card. + %1 compra %n cards. + + + + + %1 draws %n card(s). + male + + %1 compra %n card. + %1 compra %n cards. + + + + %1 undoes his last draw. %1 desfaz sua última compra. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 desfaz sua última compra (%2). - + %1 undoes her last draw (%2). - + from table vindo do campo de batalha - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library o card do fundo do seu grimório - + the bottom card of her library - + from the bottom of his library vindo do fundo do seu grimório - + from the bottom of her library - + the top card of his library o card do topo do seu grimório - + the top card of her library - + from the top of his library vindo do topo do seu grimório - + from the top of her library - + from library vindo do grimório - + from sideboard vindo do sideboard - + from the stack vindo da pilha - + %1 gives %2 control over %3. %1 dá controle para %2 sobre %3. - + %1 puts %2 into play tapped%3. %1 põe %2 em jogo virado%3. - + %1 puts %2 into play%3. %1 põe %2 no campo de batalha %3. - + %1 puts %2%3 into graveyard. %1 põe %2 no cemitério%3. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2 para a mão%3. - + %1 puts %2%3 into his library. %1 põe %2 no seu grimório%3. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 põe %2 no fundo do seu grimório%3. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 põe %2 no topo do seu grimório%3. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 põe %2 no seu grimório na posição %4%3. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 move %2 para o sideboard%3. - + %1 plays %2%3. %1 põe %2 na pilha%3. + + + %1 takes a mulligan to %n. + female + + + + + + + + %1 takes a mulligan to %n. + male + + + + + - - + + %1 flips %2 face-down. + female + %1 vira %2 para baixo. + + + + %1 flips %2 face-down. + male + %1 vira %2 para baixo. + + + + %1 flips %2 face-up. + female + %1 vira %2 para cima. + + + + %1 flips %2 face-up. + male + %1 vira %2 para cima. + + + + %1 destroys %2. + female + %1 destrói %2. + + + + %1 destroys %2. + male + %1 destrói %2. + + + %1 attaches %2 to %3's %4. + female + %1 anexa %2 a %4 de %3. + + + %1 attaches %2 to %3's %4. + male + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 female + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + %1 anexa %2 a %4 de %3. + + + + %1 unattaches %2. + female + %1 desanexa %2. + + + + %1 unattaches %2. + male + %1 desanexa %2. + + + + %1 creates token: %2%3. + female + %1 cria a ficha: %2%3. + + + + %1 creates token: %2%3. + male + %1 cria a ficha: %2%3. + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + %1 aponta para %4 com %3 de %2 . + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + %1 aponta para %4 com %3 de %2 . + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + %1 aponta para %4 com %3 de %2 . + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + %1 aponta para %4 com %3 de %2 . + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + %1 aponta para %4 com %3 de %2 . + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + %1 aponta para %4 com %3 de %2 . + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + %1 aponta para %4 com %3 de %2 . + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + %1 aponta para %4 com %3 de %2 . + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + %1 aponta para %5 de %4 com %3 de %2. + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + %1 põe %n marcador %2 em %3 (agora %4). + %1 põe %n marcadores %2 em %3 (agora %4). + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + %1 põe %n marcador %2 em %3 (agora %4). + %1 põe %n marcadores %2 em %3 (agora %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + %1 tira %n marcador %2 em %3 (agora %4). + %1 tira %n marcadores %2 em %3 (agora %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + %1 tira %n marcador %2 em %3 (agora %4). + %1 tira %n marcadores %2 em %3 (agora %4). + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + %1 altera o marcador %2 para %3 (%4%5). + + + + %1 sets counter %2 to %3 (%4%5). + male + %1 altera o marcador %2 para %3 (%4%5). + + + + %1 sets %2 to not untap normally. + female + %1 define que %2 não desvira normalmente. + + + + %1 sets %2 to not untap normally. + male + %1 define que %2 não desvira normalmente. + + + + %1 sets %2 to untap normally. + female + %1 define que %2 desvira normalmente. + + + + %1 sets %2 to untap normally. + male + %1 define que %2 desvira normalmente. + + + + %1 sets PT of %2 to %3. + female + %1 altera o P/R de %2 para %3. + + + + %1 sets PT of %2 to %3. + male + %1 altera o P/R de %2 para %3. + + + + %1 sets annotation of %2 to %3. + female + %1 altera a nota de %2 para%3. + + + + %1 sets annotation of %2 to %3. + male + %1 altera a nota de %2 para%3. + + + + %1 is looking at the top %2 cards %3. + female + %1 está olhando para os %2 cards do topo %3. + + + + %1 is looking at the top %2 cards %3. + male + %1 está olhando para os %2 cards do topo %3. + + + + %1 is looking at %2. + female + %1 está olhando para %2. + + + + %1 is looking at %2. + male + %1 está olhando para %2. + + + + %1 stops looking at %2. + female + %1 para de olhar para %2. + + + + %1 stops looking at %2. + male + %1 para de olhar para %2. + + + + %1 reveals %2 to %3. + p1 female, p2 female + %1 revela %2 para %3. + + + + %1 reveals %2 to %3. + p1 female, p2 male + %1 revela %2 para %3. + + + + %1 reveals %2 to %3. + p1 male, p2 female + %1 revela %2 para %3. + + + + %1 reveals %2 to %3. + p1 male, p2 male + %1 revela %2 para %3. + + + + %1 reveals %2. + female + %1 revela %2. + + + + %1 reveals %2. + male + %1 revela %2. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + %1 revela aleatoriamente %2%3. para %4. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + %1 revela aleatoriamente %2%3. para %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + %1 revela aleatoriamente %2%3. para %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + %1 revela aleatoriamente %2%3. para %4. + + + + %1 randomly reveals %2%3. + female + %1 revela aleatoriamente %2%3. + + + + %1 randomly reveals %2%3. + male + %1 revela aleatoriamente %2%3. + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + %1 revela %2%3 para %4. + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + %1 revela %2%3 para %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + %1 revela %2%3 para %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + %1 revela %2%3 para %4. + + + + %1 reveals %2%3. + female + %1 revela %2%3. + + + + %1 reveals %2%3. + male + %1 revela %2%3. + + + + It is now %1's turn. + female + Agora é o turno de %1. + + + + It is now %1's turn. + male + Agora é o turno de %1. + + + + a card um card - %1 flips %2 face-down. - %1 vira %2 para baixo. + %1 vira %2 para baixo. - %1 flips %2 face-up. - %1 vira %2 para cima. + %1 vira %2 para cima. - %1 attaches %2 to %3's %4. - %1 anexa %2 a %4 de %3. + %1 anexa %2 a %4 de %3. - %1 unattaches %2. - %1 desanexa %2. + %1 desanexa %2. - %1 points from %2's %3 to %4's %5. - %1 aponta para %5 de %4 com %3 de %2. + %1 aponta para %5 de %4 com %3 de %2. %1 places %n counter(s) (%2) on %3 (now %4). @@ -2203,7 +2966,7 @@ A versão local é %1 e a versão remota é %2. - + red vermelho @@ -2211,7 +2974,7 @@ A versão local é %1 e a versão remota é %2. - + yellow amarelo @@ -2219,7 +2982,7 @@ A versão local é %1 e a versão remota é %2. - + green verde @@ -2227,74 +2990,61 @@ A versão local é %1 e a versão remota é %2. - %1 sets counter %2 to %3 (%4%5). - %1 altera o marcador %2 para %3 (%4%5). + %1 altera o marcador %2 para %3 (%4%5). - %1 sets PT of %2 to %3. - %1 altera o P/R de %2 para %3. + %1 altera o P/R de %2 para %3. - %1 sets annotation of %2 to %3. - %1 altera a nota de %2 para%3. + %1 altera a nota de %2 para%3. - %1 is looking at the top %2 cards %3. - %1 está olhando para os %2 cards do topo %3. + %1 está olhando para os %2 cards do topo %3. - + The game has started. O jogo começou. - Connected. - Conectado. + Conectado. - Protocol version mismatch. Client: %1, Server: %2 - Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 + Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - You have joined game #%1. - Você entrou no jogo nº %1. + Você entrou no jogo nº %1. - %1 has joined the game. - %1 entrou no jogo. + %1 entrou no jogo. - %1 has left the game. - %1 saiu do jogo. + %1 saiu do jogo. - %1 has loaded a local deck. - %1 carregou um deck local. + %1 carregou um deck local. - %1 has loaded deck #%2. - %1 carregou o deck nº %2. + %1 carregou o deck nº %2. - %1 is ready to start the game. - %1 está pronto para começar o jogo. + %1 está pronto para começar o jogo. - %1 has conceded the game. - %1 concedeu o jogo. + %1 concedeu o jogo. %1 draws a card. @@ -2305,197 +3055,164 @@ A versão local é %1 e a versão remota é %2. %1 compra %2 cards. - %1 destroys %2. - %1 destrói %2. + %1 destrói %2. - %1 creates token: %2%3. - %1 cria a ficha: %2%3. + %1 cria a ficha: %2%3. - %1 points from %2's %3 to %4. - %1 aponta para %4 com %3 de %2 . + %1 aponta para %4 com %3 de %2 . - %1 places %n %2 counter(s) on %3 (now %4). - + %1 põe %n marcador %2 em %3 (agora %4). %1 põe %n marcadores %2 em %3 (agora %4). - %1 removes %n %2 counter(s) from %3 (now %4). - + %1 tira %n marcador %2 em %3 (agora %4). %1 tira %n marcadores %2 em %3 (agora %4). - %1 %2 %3. - %1 %2 %3. + %1 %2 %3. - %1 is looking at %2. - %1 está olhando para %2. + %1 está olhando para %2. - %1 stops looking at %2. - %1 para de olhar para %2. + %1 para de olhar para %2. - %1 reveals %2 to %3. - %1 revela %2 para %3. + %1 revela %2 para %3. - %1 reveals %2. - %1 revela %2. + %1 revela %2. - + ending phase fase final - It is now %1's turn. - Agora é o turno de %1. + Agora é o turno de %1. %1 shuffles his library. %1 embaralha o seu grimório. - - - %1 takes a mulligan to %n. - - - - - - + %1 draws his initial hand. - + %1 draws her initial hand. - - her permanents - - - - %1 randomly reveals %2%3 to %4. - %1 revela aleatoriamente %2%3. para %4. + %1 revela aleatoriamente %2%3. para %4. - %1 randomly reveals %2%3. - %1 revela aleatoriamente %2%3. + %1 revela aleatoriamente %2%3. - %1 reveals %2%3 to %4. - %1 revela %2%3 para %4. + %1 revela %2%3 para %4. - %1 reveals %2%3. - %1 revela %2%3. + %1 revela %2%3. - + untap step etapa de desvirar - + upkeep step etapa de manutenção - + draw step etapa de compra - + first main phase primeira fase principal - + beginning of combat step etapa de início de combate - + declare attackers step etapa de declaracão de atacantes - + declare blockers step etapa de declaração de bloqueadores - + combat damage step etapa de dano de combate - + end of combat step etapa de fim de combate - + second main phase segunda fase principal - + It is now the %1. Agora é a %1. - taps - vira + vira - untaps - desvira + desvira - %1 sets %2 to not untap normally. - %1 define que %2 não desvira normalmente. + %1 define que %2 não desvira normalmente. - %1 sets %2 to untap normally. - %1 define que %2 desvira normalmente. + %1 define que %2 desvira normalmente. - his permanents - as suas permanentes + as suas permanentes @@ -3543,67 +4260,67 @@ Por favor, entre um nome: UserList - + Users online: %1 Usuários online: %1 - + Users in this room: %1 Usuários nesta sala: %1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Usuários ignorados online: %1 / %2 - + %1's games - + User &details &Detalhes do usuário - + Direct &chat &Chat direto - + Show this user's &games - + Add to &buddy list Adicionar à &lista de amigos - + Remove from &buddy list Remover da li&sta de amigos - + Add to &ignore list Adicionar à li&sta dos ignorados - + Remove from &ignore list Remover da lista dos i&gnorados - + Ban from &server Ban&ir do servidor diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index d42405415..db115aa25 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -235,57 +235,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Jogar - + &Hide Esco&nder - + &Tap &Virar - + &Untap Desv&irar - + Toggle &normal untapping A&lterar desvirar normalmente - + &Flip Vol&tar - + &Clone Copi&ar - + Ctrl+H Ctrl+H - + &Attach to card... Ane&xar a carta... - + Ctrl+A Ctrl+A - + Unattac&h De&sanexar @@ -294,147 +294,147 @@ This is only saved for moderators and cannot be seen by the banned person.Definir &P/R... - + &Draw arrow... - + &Power / toughness &Poder / resistência - + &Increase power &Aumentar poder - + Ctrl++ Ctrl++ - + &Decrease power &Diminuir poder - + Ctrl+- Ctrl+- - + I&ncrease toughness A&umentar resistência - + Alt++ Alt++ - + D&ecrease toughness Di&minuir resistência - + Alt+- Alt+- - + In&crease power and toughness Aumen&tar poder e resistência - + Ctrl+Alt++ Ctrl+Alt++ - + Dec&rease power and toughness Dimin&uir poder e resistência - + Ctrl+Alt+- Ctrl+Alt+- - + Set &power and toughness... Definir &poder e resistência... - + Ctrl+P Ctrl+P - + &Set annotation... Colocar &nota... - + red vermelho - + yellow amarelo - + green verde - + &Add counter (%1) Adicionar &marcador (%1) - + &Remove counter (%1) &Remover marcador (%1) - + &Set counters (%1)... &Denifir marcadores (%1)... - + &top of library Topo do &grimório - + &bottom of library &Fundo do grimório - + &graveyard &Cemitério - + Ctrl+Del Ctrl+Del - + &exile &Exílio - + &Move to M&over para @@ -1424,7 +1424,6 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - @@ -1432,71 +1431,72 @@ This is only saved for moderators and cannot be seen by the banned person. + Error Erro - + Please join the appropriate room first. - + Wrong password. Password incorrecta. - + Spectators are not allowed in this game. Não são permitidos espectadores neste jogo. - + The game is already full. O jogo já se encontra cheio. - + The game does not exist any more. O jogo já não existe. - + This game is only open to registered users. Este jogo só está aberto a utilizadores registados. - + This game is only open to its creator's buddies. Este jogo só está aberto aos amigos do seu criador. - + You are being ignored by the creator of this game. Você está a ser ignorado pelo criador deste jogo. - + Join game Entrar no jogo - + Password: Password: - + Games Jogos - + Show &full games &Mostrar jogos cheios - + Show &running games @@ -1505,17 +1505,17 @@ This is only saved for moderators and cannot be seen by the banned person.&Mostrar jogos cheios - + C&reate &Criar - + &Join &Entrar - + J&oin as spectator Entrar como &espectador @@ -1919,92 +1919,78 @@ Versão local é %1, versão remota é %2. MessageLogWidget - Connecting to %1... - Ligando a %1... + Ligando a %1... - Connected. - Ligado. + Ligado. - Disconnected from server. - Desligado do servidor. + Desligado do servidor. - Invalid password. - Password incorrecto. + Password incorrecto. - Protocol version mismatch. Client: %1, Server: %2 - Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 + Versão dos protocolos incompatível. Versão do utilizador:%1, versão do servidor:%2 - Protocol error. - Erro de protocolo. + Erro de protocolo. - You have joined game #%1. - Você entrou no jogo #%1. + Você entrou no jogo #%1. - %1 has joined the game. - %1 entrou no jogo. + %1 entrou no jogo. - %1 has left the game. - %1 abandonou o jogo. + %1 abandonou o jogo. - + The game has been closed. Este jogo foi encerrado. - + %1 is now watching the game. %1 está agora a ver o jogo. - + %1 is not watching the game any more. %1 já não está a ver o jogo. - %1 has loaded a local deck. - %1 carregou um deck local. + %1 carregou um deck local. - %1 has loaded deck #%2. - %1 carregou o deck #%2. + %1 carregou o deck #%2. - %1 is ready to start the game. - %1 está pronto a começar o jogo. + %1 está pronto a começar o jogo. - %1 is not ready to start the game any more. - %1 já não está pronto a começar o jogo. + %1 já não está pronto a começar o jogo. - %1 has conceded the game. - %1 concedeu o jogo. + %1 concedeu o jogo. - + The game has started. O jogo começou. @@ -2013,9 +1999,8 @@ Versão local é %1, versão remota é %2. %1 baralha o grimório. - %1 rolls a %2 with a %3-sided die. - %1 obteve %2 com um dado de %3 faces. + %1 obteve %2 com um dado de %3 faces. %1 draws a card. @@ -2026,158 +2011,330 @@ Versão local é %1, versão remota é %2. %1 compra %2 cartas. - + + You have joined game #%1. + female + Você entrou no jogo #%1. + + + + You have joined game #%1. + male + Você entrou no jogo #%1. + + + + %1 has joined the game. + female + %1 entrou no jogo. + + + + %1 has joined the game. + male + %1 entrou no jogo. + + + + %1 has left the game. + female + %1 abandonou o jogo. + + + + %1 has left the game. + male + %1 abandonou o jogo. + + + + %1 has loaded a local deck. + female + %1 carregou um deck local. + + + + %1 has loaded a local deck. + male + %1 carregou um deck local. + + + + %1 has loaded deck #%2. + female + %1 carregou o deck #%2. + + + + %1 has loaded deck #%2. + male + %1 carregou o deck #%2. + + + + %1 is ready to start the game. + female + %1 está pronto a começar o jogo. + + + + %1 is ready to start the game. + male + %1 está pronto a começar o jogo. + + + + %1 is not ready to start the game any more. + female + %1 já não está pronto a começar o jogo. + + + + %1 is not ready to start the game any more. + male + %1 já não está pronto a começar o jogo. + + + + %1 has conceded the game. + female + %1 concedeu o jogo. + + + + %1 has conceded the game. + male + %1 concedeu o jogo. + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female + + + + + %1 shuffles %2. + male + + + + + %1 rolls a %2 with a %3-sided die. + female + %1 obteve %2 com um dado de %3 faces. + + + + %1 rolls a %2 with a %3-sided die. + male + %1 obteve %2 com um dado de %3 faces. + + + + %1 draws %n card(s). + female + + %1 compra %n carta. + %1 compra %n cartas. + + + + + %1 draws %n card(s). + male + + %1 compra %n carta. + %1 compra %n cartas. + + + + from table vindo da mesa - + from graveyard vindo do cemitério - + from exile vindo do exílio - + from hand vindo da mão - + the bottom card of his library a carta do fundo do seu grimório - + the bottom card of her library - + from the bottom of his library do fundo do seu grimório - + from the bottom of her library - + the top card of his library a carta do topo do seu grimório - + the top card of her library - + from the top of his library do topo do seu grimório - + from the top of her library - + from library do grimório - + from sideboard do sideboard - + from the stack da pilha - + %1 puts %2 into play tapped%3. %1 coloca %2 em jogo virado(a)%3. - + %1 puts %2 into play%3. %1 coloca %2 em jogo %3. - + %1 puts %2%3 into graveyard. %1 coloca %2%3 no cemitério. - + %1 exiles %2%3. %1 exila %2%3. - + %1 moves %2%3 to hand. %1 move %2%3 para a mão. - + %1 puts %2%3 into his library. %1 coloca %2%3 no seu grimório. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. %1 coloca %2%3 no fundo do seu grimório. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. %1 coloca %2%3 no topo do seu grimório. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. %1 coloca %2%3 no seu grimório na posição %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. %1 move %2%3 para o sideboard. - + %1 plays %2%3. %1 joga %2%3. - + %1 takes a mulligan to %n. + female + + + + + + + + %1 takes a mulligan to %n. + male @@ -2185,123 +2342,707 @@ Versão local é %1, versão remota é %2. - %1 draws his initial hand. + %1 flips %2 face-down. + female + %1 volta a face de %2 para baixo. + + + + %1 flips %2 face-down. + male + %1 volta a face de %2 para baixo. + + + + %1 flips %2 face-up. + female + %1 volta a face de %2 para cima. + + + + %1 flips %2 face-up. + male + %1 volta a face de %2 para cima. + + + + %1 destroys %2. + female + %1 destrói %2. + + + + %1 destroys %2. + male + %1 destrói %2. + + + %1 attaches %2 to %3's %4. + female + %1 anexa %2 a %4 de %3. + + + %1 attaches %2 to %3's %4. + male + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 female + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + %1 anexa %2 a %4 de %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + %1 anexa %2 a %4 de %3. + + + + %1 unattaches %2. + female + %1 desanexa %2. + + + + %1 unattaches %2. + male + %1 desanexa %2. + + + + %1 creates token: %2%3. + female + %1 cria ficha: %2%3. + + + + %1 creates token: %2%3. + male + %1 cria ficha: %2%3. + + + + %1 points from her %2 to herself. + female - - %1 draws her initial hand. + + %1 points from his %2 to himself. + male + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + %1 aponta de %3 de %2 para %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + %1 aponta de %3 de %2 para %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + %1 aponta de %3 de %2 para %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + %1 aponta de %3 de %2 para %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + %1 aponta de %3 de %2 para %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + %1 aponta de %3 de %2 para %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + %1 aponta de %3 de %2 para %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + %1 aponta de %3 de %2 para %4. + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + %1 aponta de %3 de %2 para %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + %1 aponta de %3 de %2 para %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + %1 aponta de %3 de %2 para %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + %1 aponta de %3 de %2 para %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + %1 aponta de %3 de %2 para %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + %1 aponta de %3 de %2 para %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + %1 aponta de %3 de %2 para %5 de %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + %1 aponta de %3 de %2 para %5 de %4. + - + %1 places %n %2 counter(s) on %3 (now %4). - + female + %1 coloca %n %2 marcador em %3 (agora com %4). %1 coloca %n %2 marcadores em %3 (agora com %4). - + + %1 places %n %2 counter(s) on %3 (now %4). + male + + %1 coloca %n %2 marcador em %3 (agora com %4). + %1 coloca %n %2 marcadores em %3 (agora com %4). + + + + %1 removes %n %2 counter(s) from %3 (now %4). - + female + + %1 remove %n %2 marcador de %3 (agora com %4). + %1 remove %n %2 marcadores de %3 (agora com %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + %1 remove %n %2 marcador de %3 (agora com %4). %1 remove %n %2 marcadores de %3 (agora com %4). - - - a card - uma carta - - - - %1 has restored connection to the game. + + %1 taps her permanents. + female - - %1 has lost connection to the game. + + %1 untaps her permanents. + female - - %1 shuffles %2. + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + %1 altera o número de marcadores %2 para %3(%4%5). + + + + %1 sets counter %2 to %3 (%4%5). + male + %1 altera o número de marcadores %2 para %3(%4%5). + + + + %1 sets %2 to not untap normally. + female + %1 define %2 para não desvirar normalmente. + + + + %1 sets %2 to not untap normally. + male + %1 define %2 para não desvirar normalmente. + + + + %1 sets %2 to untap normally. + female + %1 define %2 para desvirar normalmente. + + + + %1 sets %2 to untap normally. + male + %1 define %2 para desvirar normalmente. + + + + %1 sets PT of %2 to %3. + female + %1 define o P/R de %2 como %3. + + + + %1 sets PT of %2 to %3. + male + %1 define o P/R de %2 como %3. + + + + %1 sets annotation of %2 to %3. + female + %1 coloca uma nota de %2 em%3. + + + + %1 sets annotation of %2 to %3. + male + %1 coloca uma nota de %2 em%3. + + + + %1 is looking at the top %2 cards %3. + female + %1 está a olhar para as %2 cartas do topo %3. + + + + %1 is looking at the top %2 cards %3. + male + %1 está a olhar para as %2 cartas do topo %3. + + + + %1 is looking at %2. + female + %1 está a olhar para %2. + + + + %1 is looking at %2. + male + %1 está a olhar para %2. + + + + %1 stops looking at %2. + female + %1 para de olhar para %2. + + + + %1 stops looking at %2. + male + %1 para de olhar para %2. + + + + %1 reveals %2 to %3. + p1 female, p2 female + %1 revela %2 a %3. + + + + %1 reveals %2 to %3. + p1 female, p2 male + %1 revela %2 a %3. + + + + %1 reveals %2 to %3. + p1 male, p2 female + %1 revela %2 a %3. + + + + %1 reveals %2 to %3. + p1 male, p2 male + %1 revela %2 a %3. + + + + %1 reveals %2. + female + %1 revela %2. + + + + %1 reveals %2. + male + %1 revela %2. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + %1 revela aleatoreamente %2%3. a %4. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + %1 revela aleatoreamente %2%3. a %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + %1 revela aleatoreamente %2%3. a %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + %1 revela aleatoreamente %2%3. a %4. + + + + %1 randomly reveals %2%3. + female + %1 revela aleatoreamente %2%3. + + + + %1 randomly reveals %2%3. + male + %1 revela aleatoreamente %2%3. + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + %1 revela %2%3 a %4. + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + %1 revela %2%3 a %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + %1 revela %2%3 a %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + %1 revela %2%3 a %4. + + + + %1 reveals %2%3. + female + %1 revela %2%3. + + + + %1 reveals %2%3. + male + %1 revela %2%3. + + + + It is now %1's turn. + female + É agora o turno de %1. + + + + It is now %1's turn. + male + É agora o turno de %1. + + + + %1 draws his initial hand. + + + + + %1 draws her initial hand. - + %1 places %n %2 counter(s) on %3 (now %4). + + %1 coloca %n %2 marcador em %3 (agora com %4). + %1 coloca %n %2 marcadores em %3 (agora com %4). + + + + %1 removes %n %2 counter(s) from %3 (now %4). + + %1 remove %n %2 marcador de %3 (agora com %4). + %1 remove %n %2 marcadores de %3 (agora com %4). + + + + + + a card + uma carta + + %1 draws %n card(s). - + %1 compra %n carta. %1 compra %n cartas. - + %1 undoes his last draw. %1 desfaz a sua última compra. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). %1 desfaz a sua última compra (%2). - + %1 undoes her last draw (%2). - + %1 gives %2 control over %3. %1 dá controlo sobre %3 a %2. - %1 flips %2 face-down. - %1 volta a face de %2 para baixo. + %1 volta a face de %2 para baixo. - %1 flips %2 face-up. - %1 volta a face de %2 para cima. + %1 volta a face de %2 para cima. - %1 destroys %2. - %1 destrói %2. + %1 destrói %2. - %1 attaches %2 to %3's %4. - %1 anexa %2 a %4 de %3. + %1 anexa %2 a %4 de %3. - %1 unattaches %2. - %1 desanexa %2. + %1 desanexa %2. - %1 creates token: %2%3. - %1 cria ficha: %2%3. + %1 cria ficha: %2%3. - %1 points from %2's %3 to %4. - %1 aponta de %3 de %2 para %4. + %1 aponta de %3 de %2 para %4. - %1 points from %2's %3 to %4's %5. - %1 aponta de %3 de %2 para %5 de %4. + %1 aponta de %3 de %2 para %5 de %4. %1 places %n counter(s) (%2) on %3 (now %4). @@ -2318,7 +3059,7 @@ Versão local é %1, versão remota é %2. - + red vermelho @@ -2326,7 +3067,7 @@ Versão local é %1, versão remota é %2. - + yellow amarelo @@ -2334,7 +3075,7 @@ Versão local é %1, versão remota é %2. - + green verde @@ -2342,162 +3083,138 @@ Versão local é %1, versão remota é %2. - his permanents - as suas permanentes + as suas permanentes - - her permanents - - - - %1 %2 %3. - %1 %2 %3. + %1 %2 %3. - taps - vira + vira - untaps - desvira + desvira - %1 sets counter %2 to %3 (%4%5). - %1 altera o número de marcadores %2 para %3(%4%5). + %1 altera o número de marcadores %2 para %3(%4%5). - %1 sets %2 to not untap normally. - %1 define %2 para não desvirar normalmente. + %1 define %2 para não desvirar normalmente. - %1 sets %2 to untap normally. - %1 define %2 para desvirar normalmente. + %1 define %2 para desvirar normalmente. - %1 sets PT of %2 to %3. - %1 define o P/R de %2 como %3. + %1 define o P/R de %2 como %3. - %1 sets annotation of %2 to %3. - %1 coloca uma nota de %2 em%3. + %1 coloca uma nota de %2 em%3. - %1 is looking at the top %2 cards %3. - %1 está a olhar para as %2 cartas do topo %3. + %1 está a olhar para as %2 cartas do topo %3. - %1 is looking at %2. - %1 está a olhar para %2. + %1 está a olhar para %2. - %1 stops looking at %2. - %1 para de olhar para %2. + %1 para de olhar para %2. - %1 reveals %2 to %3. - %1 revela %2 a %3. + %1 revela %2 a %3. - %1 reveals %2. - %1 revela %2. + %1 revela %2. - %1 randomly reveals %2%3 to %4. - %1 revela aleatoreamente %2%3. a %4. + %1 revela aleatoreamente %2%3. a %4. - %1 randomly reveals %2%3. - %1 revela aleatoreamente %2%3. + %1 revela aleatoreamente %2%3. - %1 reveals %2%3 to %4. - %1 revela %2%3 a %4. + %1 revela %2%3 a %4. - %1 reveals %2%3. - %1 revela %2%3. + %1 revela %2%3. - It is now %1's turn. - É agora o turno de %1. + É agora o turno de %1. - + untap step Etapa de Desvirar - + upkeep step Etapa de Manutenção - + draw step Etapa de Compra - + first main phase 1ª Fase Principal (pré-combate) - + beginning of combat step Etapa de Início de Combate - + declare attackers step Etapa de Declaração de Atacantes - + declare blockers step Etapa de Declaração de Bloqueadores - + combat damage step Etapa de Dano de Combate - + end of combat step Etapa de Fim de Combate - + second main phase 2ª Fase Principal (pós-combate) - + ending phase Fase Final - + It is now the %1. É agora a %1. @@ -3547,67 +4264,67 @@ Por favor introduza um nome: UserList - + Users online: %1 Utilizadores online: %1 - + Users in this room: %1 Utilizadores nesta sala:%1 - + Buddies online: %1 / %2 Amigos online: %1 / %2 - + Ignored users online: %1 / %2 Utilizadores ignorados online %1 / %2 - + %1's games - + User &details Detalhes do &utilizador - + Direct &chat Conversação &directa - + Show this user's &games - + Add to &buddy list Adicionar a lista de &amigos - + Remove from &buddy list Remover da lista de &amigos - + Add to &ignore list Adicionar a lista a &ignorar - + Remove from &ignore list Remover da lista a &ignorar - + Ban from &server Banir do &servidor diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index b467a4e0c..a32a425d0 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -231,57 +231,57 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play &Разыграть - + &Hide &Cкрыть - + &Tap &Повернуть - + &Untap &Развернуть - + Toggle &normal untapping (Не) &Разворачивать как обычно - + &Flip &Рубашкой вверх (вниз) - + &Clone &Клонировать - + Ctrl+H Ctrl+H - + &Attach to card... &Прикрепить к... - + Ctrl+A - + Unattac&h &Открепить @@ -290,147 +290,147 @@ This is only saved for moderators and cannot be seen by the banned person.Установить &Силу/Защиту... - + &Draw arrow... - + &Power / toughness &Сила / защита - + &Increase power &Увеличить силу - + Ctrl++ - + &Decrease power У&меньшить силу - + Ctrl+- - + I&ncrease toughness У&величить защиту - + Alt++ - + D&ecrease toughness Уменьшить &защиту - + Alt+- - + In&crease power and toughness Увеличить силу &и защиту - + Ctrl+Alt++ - + Dec&rease power and toughness Уменьшить силу и за&щиту - + Ctrl+Alt+- - + Set &power and toughness... Уст&ановить силу / защиту... - + Ctrl+P - + &Set annotation... &Пометить... - + red Красный - + yellow Желтый - + green Зеленый - + &Add counter (%1) &Добавить жетон (%1) - + &Remove counter (%1) &Убрать жетон (%1) - + &Set counters (%1)... &Установить жетоны (%1)... - + &top of library &Наверх библиотеки - + &bottom of library &Вниз библиотеки - + &graveyard &На кладбище - + Ctrl+Del - + &exile &Изгнать - + &Move to &Переместить... @@ -1363,7 +1363,6 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - @@ -1371,86 +1370,87 @@ This is only saved for moderators and cannot be seen by the banned person. + Error Ошибка - + Please join the appropriate room first. - + Wrong password. Неверный пароль. - + Spectators are not allowed in this game. В эту игру не пускают зрителей. - + The game is already full. Все места заняты! =Ь - + The game does not exist any more. Эта игра была удалена. - + This game is only open to registered users. Доступно только для зарегистрированных. - + This game is only open to its creator's buddies. Доступно только для друзей. - + You are being ignored by the creator of this game. Вы добавлены в игнор-лист данного игрока. - + Join game Присоединиться - + Password: Пароль: - + Games Игры - + Show &full games Показывать &текущие - + Show &running games - + C&reate С&оздать - + &Join &Присоединиться - + J&oin as spectator П&рисоединиться как зритель @@ -1843,92 +1843,78 @@ Local version is %1, remote version is %2. MessageLogWidget - Connecting to %1... - Подключение к %1... + Подключение к %1... - Connected. - Подключено. + Подключено. - Disconnected from server. - Нет соединения с сервером. + Нет соединения с сервером. - Invalid password. - Неверный пароль. + Неверный пароль. - Protocol version mismatch. Client: %1, Server: %2 - Несовпадение версий. Клиент: %1, Сервер: %2 + Несовпадение версий. Клиент: %1, Сервер: %2 - Protocol error. - Ошибка протокола. + Ошибка протокола. - You have joined game #%1. - Вы присоединились к игре #%1. + Вы присоединились к игре #%1. - %1 has joined the game. - %1 присоединился к игре. + %1 присоединился к игре. - %1 has left the game. - %1 покиул игру. + %1 покиул игру. - + The game has been closed. Игра закрыта. - + %1 is now watching the game. %1 вошел как зритель. - + %1 is not watching the game any more. %1 покинул зрительскую ложу. - %1 has loaded a local deck. - %1 загрузил колоду с диска. + %1 загрузил колоду с диска. - %1 has loaded deck #%2. - %1 загрузил колоду #%2. + %1 загрузил колоду #%2. - %1 is ready to start the game. - %1 готов начать игру. + %1 готов начать игру. - %1 is not ready to start the game any more. - %1 все еще не готов. + %1 все еще не готов. - %1 has conceded the game. - %1 решил сдаться. + %1 решил сдаться. - + The game has started. Игра началась. @@ -1937,9 +1923,8 @@ Local version is %1, remote version is %2. %1 размешивает библиотеку. - %1 rolls a %2 with a %3-sided die. - %1 выкинул %2 / %3. + %1 выкинул %2 / %3. %1 draws a card. @@ -1950,170 +1935,960 @@ Local version is %1, remote version is %2. %1 взял %2 карт. - + + You have joined game #%1. + female + Вы присоединились к игре #%1. + + + + You have joined game #%1. + male + Вы присоединились к игре #%1. + + + + %1 has joined the game. + female + %1 присоединился к игре. + + + + %1 has joined the game. + male + %1 присоединился к игре. + + + + %1 has left the game. + female + %1 покиул игру. + + + + %1 has left the game. + male + %1 покиул игру. + + + + %1 has loaded a local deck. + female + %1 загрузил колоду с диска. + + + + %1 has loaded a local deck. + male + %1 загрузил колоду с диска. + + + + %1 has loaded deck #%2. + female + %1 загрузил колоду #%2. + + + + %1 has loaded deck #%2. + male + %1 загрузил колоду #%2. + + + + %1 is ready to start the game. + female + %1 готов начать игру. + + + + %1 is ready to start the game. + male + %1 готов начать игру. + + + + %1 is not ready to start the game any more. + female + %1 все еще не готов. + + + + %1 is not ready to start the game any more. + male + %1 все еще не готов. + + + + %1 has conceded the game. + female + %1 решил сдаться. + + + + %1 has conceded the game. + male + %1 решил сдаться. + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female + + + + + %1 shuffles %2. + male + + + + + %1 rolls a %2 with a %3-sided die. + female + %1 выкинул %2 / %3. + + + + %1 rolls a %2 with a %3-sided die. + male + %1 выкинул %2 / %3. + + + + %1 draws %n card(s). + female + + %1 взял %n карту. + %1 взял %n карты. + %1 взял %n карт(ы). + + + + + %1 draws %n card(s). + male + + %1 взял %n карту. + %1 взял %n карты. + %1 взял %n карт(ы). + + + + %1 undoes his last draw. %1 отменил последнее взятие. - + %1 undoes his last draw (%2). %1 отменил %2 последних взятий. - + from table с поля битвы - + from graveyard из кладбища - + from exile из изгнания - + from hand из руки - + the bottom card of his library нижнюю карту своей библиотеки - + from the bottom of his library со дна своей библиотеки - + the top card of his library верхнюю карту своей библиотеки - + from the top of his library с верха своей библиотеки - + from library из библиотеки - + from sideboard из сайда - + from the stack из стека - - + + a card карту - + %1 gives %2 control over %3. %1 передает %2 контроль над %3. - + %1 puts %2 into play%3. %1 поместил %2 на поле битвы %3. - + %1 puts %2%3 into graveyard. %1 поместил %2%3 на кладбище. - + %1 exiles %2%3. %1 изгоняет %2%3. - + %1 moves %2%3 to hand. %1 поместил %2%3 в руку. - + %1 puts %2%3 into his library. %1 поместил %2%3 в свою библиотеку. - + %1 puts %2%3 on bottom of his library. %1 поместил %2%3 на дно своей библиотеки. - + %1 puts %2%3 on top of his library. %1 поместил %2%3 на верх своей библиотеки. - + %1 puts %2%3 into his library at position %4. %1 поместил %2%3 в свою библиотеку %4 сверху. - + %1 moves %2%3 to sideboard. %1 поместил %2%3 в сайд. - + %1 plays %2%3. %1 разыгрывает %2%3. + + + %1 takes a mulligan to %n. + female + + + + + + + + + %1 takes a mulligan to %n. + male + + + + + + - + %1 flips %2 face-down. - %1 перевернул %2 лицом вниз. + female + %1 перевернул %2 лицом вниз. - + + %1 flips %2 face-down. + male + %1 перевернул %2 лицом вниз. + + + %1 flips %2 face-up. - %1 перевернул %2 лицом вверх. + female + %1 перевернул %2 лицом вверх. - + + %1 flips %2 face-up. + male + %1 перевернул %2 лицом вверх. + + + %1 destroys %2. - %1 уничтожил %2. + female + %1 уничтожил %2. + + + + %1 destroys %2. + male + %1 уничтожил %2. - %1 attaches %2 to %3's %4. - %1 присоединил %2 к %4 игрока %3. + female + %1 присоединил %2 к %4 игрока %3. - + %1 attaches %2 to %3's %4. + male + %1 присоединил %2 к %4 игрока %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 female + %1 присоединил %2 к %4 игрока %3. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + %1 присоединил %2 к %4 игрока %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + %1 присоединил %2 к %4 игрока %3. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + %1 присоединил %2 к %4 игрока %3. + + + %1 unattaches %2. - %1 отсоединил %2. + female + %1 отсоединил %2. - + + %1 unattaches %2. + male + %1 отсоединил %2. + + + %1 creates token: %2%3. - %1 создал фишку: %2%3. + female + %1 создал фишку: %2%3. - + + %1 creates token: %2%3. + male + %1 создал фишку: %2%3. + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + %1 points from %2's %3 to %4. - %1 указывает с %3 контролируемого %2 на %4. + p1 female, p2 female, p3 female + %1 указывает с %3 контролируемого %2 на %4. - + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + %1 указывает с %3 контролируемого %2 на %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + %1 указывает с %3 контролируемого %2 на %4. + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + %1 указывает с %3 контролируемого %2 на %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + %1 указывает с %3 контролируемого %2 на %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + %1 указывает с %3 контролируемого %2 на %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + %1 указывает с %3 контролируемого %2 на %4. + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + %1 указывает с %3 контролируемого %2 на %4. + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + %1 points from %2's %3 to %4's %5. - %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + p1 female, p2 female, p3 female + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + %1 поместил %n %2 жетон на %3 (теперь %4). + %1 поместил %n %2 жетона на %3 (теперь %4). + %1 поместил %n %2 жетонов на %3 (теперь %4). + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + %1 поместил %n %2 жетон на %3 (теперь %4). + %1 поместил %n %2 жетона на %3 (теперь %4). + %1 поместил %n %2 жетонов на %3 (теперь %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + %1 снял %n %2 жетон с %3 (теперь %4). + %1 снял %n %2 жетона с %3 (теперь %4). + %1 снял %n %2 жетонов с %3 (теперь %4). + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + %1 снял %n %2 жетон с %3 (теперь %4). + %1 снял %n %2 жетона с %3 (теперь %4). + %1 снял %n %2 жетонов с %3 (теперь %4). + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + %1 установил жетон %2 на %3 (%4%5). + + + + %1 sets counter %2 to %3 (%4%5). + male + %1 установил жетон %2 на %3 (%4%5). + + + + %1 sets %2 to not untap normally. + female + %2 теперь не разворачивается как обычно (%1). + + + + %1 sets %2 to not untap normally. + male + %2 теперь не разворачивается как обычно (%1). + + + + %1 sets %2 to untap normally. + female + %2 теперь разворачивается как обычно (%1). + + + + %1 sets %2 to untap normally. + male + %2 теперь разворачивается как обычно (%1). + + + + %1 sets PT of %2 to %3. + female + %1 установил Силу/Защиту %2 %3. + + + + %1 sets PT of %2 to %3. + male + %1 установил Силу/Защиту %2 %3. + + + + %1 sets annotation of %2 to %3. + female + %1 сделал пометку на %2 "%3". + + + + %1 sets annotation of %2 to %3. + male + %1 сделал пометку на %2 "%3". + + + + %1 is looking at the top %2 cards %3. + female + %1 смотрит верхние %2 карт библиотеки %3. + + + + %1 is looking at the top %2 cards %3. + male + %1 смотрит верхние %2 карт библиотеки %3. + + + + %1 is looking at %2. + female + %1 просматривает %2. + + + + %1 is looking at %2. + male + %1 просматривает %2. + + + + %1 stops looking at %2. + female + %1 закончил просматривать %2. + + + + %1 stops looking at %2. + male + %1 закончил просматривать %2. + + + + %1 reveals %2 to %3. + p1 female, p2 female + %1 показывает его %2 %3. + + + + %1 reveals %2 to %3. + p1 female, p2 male + %1 показывает его %2 %3. + + + + %1 reveals %2 to %3. + p1 male, p2 female + %1 показывает его %2 %3. + + + + %1 reveals %2 to %3. + p1 male, p2 male + %1 показывает его %2 %3. + + + + %1 reveals %2. + female + %1 открыл его %2. + + + + %1 reveals %2. + male + %1 открыл его %2. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + %1 показывает случайно выбранную%3 карту (%2) %4. + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + %1 показывает случайно выбранную%3 карту (%2) %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + %1 показывает случайно выбранную%3 карту (%2) %4. + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + %1 показывает случайно выбранную%3 карту (%2) %4. + + + + %1 randomly reveals %2%3. + female + %1 открывает случайно выбранную%3 карту (%2). + + + + %1 randomly reveals %2%3. + male + %1 открывает случайно выбранную%3 карту (%2). + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + %1 показывает%2%3 %4. + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + %1 показывает%2%3 %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + %1 показывает%2%3 %4. + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + %1 показывает%2%3 %4. + + + + %1 reveals %2%3. + female + %1 открывает%2%3. + + + + %1 reveals %2%3. + male + %1 открывает%2%3. + + + + It is now %1's turn. + female + Ход игрока %1. + + + + It is now %1's turn. + male + Ход игрока %1. + + + %1 flips %2 face-down. + %1 перевернул %2 лицом вниз. + + + %1 flips %2 face-up. + %1 перевернул %2 лицом вверх. + + + %1 destroys %2. + %1 уничтожил %2. + + + %1 attaches %2 to %3's %4. + %1 присоединил %2 к %4 игрока %3. + + + %1 unattaches %2. + %1 отсоединил %2. + + + %1 creates token: %2%3. + %1 создал фишку: %2%3. + + + %1 points from %2's %3 to %4. + %1 указывает с %3 контролируемого %2 на %4. + + + %1 points from %2's %3 to %4's %5. + %1 указывает с %3 контролируемого %2 на %5 контролируемого %4. %1 places %n counter(s) (%2) on %3 (now %4). @@ -2131,124 +2906,97 @@ Local version is %1, remote version is %2. %1 удалил %n жетоны (%2) с %3 (теперь %4). - - - %1 has restored connection to the game. - - - - - %1 has lost connection to the game. - - - - - %1 shuffles %2. - - - %1 draws %n card(s). - + %1 взял %n карту. %1 взял %n карты. %1 взял %n карт(ы). - + %1 undoes her last draw. - + %1 undoes her last draw (%2). - + the bottom card of her library - + from the bottom of her library - + the top card of her library - + from the top of her library - + %1 puts %2 into play tapped%3. %1 положил %2 повернутым на поле битвы%3. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into her library at position %4. - - - %1 takes a mulligan to %n. - - - - - - - + %1 draws his initial hand. - + %1 draws her initial hand. - %1 places %n %2 counter(s) on %3 (now %4). - + %1 поместил %n %2 жетон на %3 (теперь %4). %1 поместил %n %2 жетона на %3 (теперь %4). %1 поместил %n %2 жетонов на %3 (теперь %4). - %1 removes %n %2 counter(s) from %3 (now %4). - + %1 снял %n %2 жетон с %3 (теперь %4). %1 снял %n %2 жетона с %3 (теперь %4). %1 снял %n %2 жетонов с %3 (теперь %4). - + red красный @@ -2257,7 +3005,7 @@ Local version is %1, remote version is %2. - + yellow желтый @@ -2266,7 +3014,7 @@ Local version is %1, remote version is %2. - + green зеленый @@ -2275,162 +3023,138 @@ Local version is %1, remote version is %2. - his permanents - свои перманенты + свои перманенты - - her permanents - - - - %1 %2 %3. - %1 %2 %3. + %1 %2 %3. - taps - повернул + повернул - untaps - развернул + развернул - %1 sets counter %2 to %3 (%4%5). - %1 установил жетон %2 на %3 (%4%5). + %1 установил жетон %2 на %3 (%4%5). - %1 sets %2 to not untap normally. - %2 теперь не разворачивается как обычно (%1). + %2 теперь не разворачивается как обычно (%1). - %1 sets %2 to untap normally. - %2 теперь разворачивается как обычно (%1). + %2 теперь разворачивается как обычно (%1). - %1 sets PT of %2 to %3. - %1 установил Силу/Защиту %2 %3. + %1 установил Силу/Защиту %2 %3. - %1 sets annotation of %2 to %3. - %1 сделал пометку на %2 "%3". + %1 сделал пометку на %2 "%3". - %1 is looking at the top %2 cards %3. - %1 смотрит верхние %2 карт библиотеки %3. + %1 смотрит верхние %2 карт библиотеки %3. - %1 is looking at %2. - %1 просматривает %2. + %1 просматривает %2. - %1 stops looking at %2. - %1 закончил просматривать %2. + %1 закончил просматривать %2. - %1 reveals %2 to %3. - %1 показывает его %2 %3. + %1 показывает его %2 %3. - %1 reveals %2. - %1 открыл его %2. + %1 открыл его %2. - %1 randomly reveals %2%3 to %4. - %1 показывает случайно выбранную%3 карту (%2) %4. + %1 показывает случайно выбранную%3 карту (%2) %4. - %1 randomly reveals %2%3. - %1 открывает случайно выбранную%3 карту (%2). + %1 открывает случайно выбранную%3 карту (%2). - %1 reveals %2%3 to %4. - %1 показывает%2%3 %4. + %1 показывает%2%3 %4. - %1 reveals %2%3. - %1 открывает%2%3. + %1 открывает%2%3. - It is now %1's turn. - Ход игрока %1. + Ход игрока %1. - + untap step шаг разворота - + upkeep step шаг поддержки - + draw step шаг взятия карты - + first main phase первая главная фаза - + beginning of combat step шаг начала битвы - + declare attackers step шаг назначения атакующих - + declare blockers step шаг назначения блокирующих - + combat damage step шаг нанесения повреждений - + end of combat step шаг завершения битвы - + second main phase вторая главная фаза - + ending phase заключительный шаг - + It is now the %1. Сейчас %1. @@ -3438,67 +4162,67 @@ Please enter a name: UserList - + Users online: %1 Пользователей онлайн: %1 - + Users in this room: %1 Пользователей в этой комнате: %1 - + Buddies online: %1 / %2 Друзей онлайн: %1 / %2 - + Ignored users online: %1 / %2 Игнорируемых пользователей онлайн: %1 / %2 - + %1's games - + User &details Данные о &пользователе - + Direct &chat Обратиться &лично - + Show this user's &games - + Add to &buddy list Добавить в список &друзей - + Remove from &buddy list &Удалить из друзей - + Add to &ignore list Добавить в &игнор-лист - + Remove from &ignore list Удалить и&з игнор-листа - + Ban from &server За&банить на сервере diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 59267fe5b..a5155a2fc 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -230,202 +230,202 @@ This is only saved for moderators and cannot be seen by the banned person. CardItem - + &Play - + &Hide - + &Tap - + &Untap - + Toggle &normal untapping - + &Flip - + &Clone - + Ctrl+H - + &Attach to card... - + Ctrl+A - + Unattac&h - + &Draw arrow... - + &Power / toughness - + &Increase power - + Ctrl++ - + &Decrease power - + Ctrl+- - + I&ncrease toughness - + Alt++ - + D&ecrease toughness - + Alt+- - + In&crease power and toughness - + Ctrl+Alt++ - + Dec&rease power and toughness - + Ctrl+Alt+- - + Set &power and toughness... - + Ctrl+P - + &Set annotation... - + red - + yellow - + green - + &Add counter (%1) - + &Remove counter (%1) - + &Set counters (%1)... - + &top of library - + &bottom of library - + &graveyard - + Ctrl+Del - + &exile - + &Move to @@ -1208,7 +1208,6 @@ This is only saved for moderators and cannot be seen by the banned person. GameSelector - @@ -1216,86 +1215,87 @@ This is only saved for moderators and cannot be seen by the banned person. + Error - + Please join the appropriate room first. - + Wrong password. - + Spectators are not allowed in this game. - + The game is already full. - + The game does not exist any more. - + This game is only open to registered users. - + This game is only open to its creator's buddies. - + You are being ignored by the creator of this game. - + Join game - + Password: - + Games - + Show &full games - + Show &running games - + C&reate - + &Join - + J&oin as spectator @@ -1684,118 +1684,183 @@ Local version is %1, remote version is %2. MessageLogWidget - - Connecting to %1... - - - - - Connected. - - - - - Disconnected from server. - - - - - Invalid password. - - - - - Protocol version mismatch. Client: %1, Server: %2 - - - - - Protocol error. - - - - - You have joined game #%1. - - - - - %1 has joined the game. - - - - - %1 has left the game. - - - - + The game has been closed. - + %1 is now watching the game. - + %1 is not watching the game any more. - - %1 has loaded a local deck. - - - - - %1 has loaded deck #%2. - - - - - %1 is ready to start the game. - - - - - %1 is not ready to start the game any more. - - - - - %1 has conceded the game. - - - - + The game has started. - + + You have joined game #%1. + female + + + + + You have joined game #%1. + male + + + + + %1 has joined the game. + female + + + + + %1 has joined the game. + male + + + + + %1 has left the game. + female + + + + + %1 has left the game. + male + + + + + %1 has loaded a local deck. + female + + + + + %1 has loaded a local deck. + male + + + + + %1 has loaded deck #%2. + female + + + + + %1 has loaded deck #%2. + male + + + + + %1 is ready to start the game. + female + + + + + %1 is ready to start the game. + male + + + + + %1 is not ready to start the game any more. + female + + + + + %1 is not ready to start the game any more. + male + + + + + %1 has conceded the game. + female + + + + + %1 has conceded the game. + male + + + + %1 has restored connection to the game. + female + + + + + %1 has restored connection to the game. + male + + + + + %1 has lost connection to the game. + female + + + + + %1 has lost connection to the game. + male + + + + + %1 shuffles %2. + female - %1 has lost connection to the game. - - - - %1 shuffles %2. + male - + %1 rolls a %2 with a %3-sided die. + female + + + + + %1 rolls a %2 with a %3-sided die. + male - + %1 draws %n card(s). + female + + + + + + + + + %1 draws %n card(s). + male @@ -1803,189 +1868,200 @@ Local version is %1, remote version is %2. - + %1 undoes his last draw. - + %1 undoes her last draw. - + %1 undoes his last draw (%2). - + %1 undoes her last draw (%2). - + from table - + from graveyard - + from exile - + from hand - + the bottom card of his library - + the bottom card of her library - + from the bottom of his library - + from the bottom of her library - + the top card of his library - + the top card of her library - + from the top of his library - + from the top of her library - + from library - + from sideboard - + from the stack - - + + a card - + %1 gives %2 control over %3. - + %1 puts %2 into play tapped%3. - + %1 puts %2 into play%3. - + %1 puts %2%3 into graveyard. - + %1 exiles %2%3. - + %1 moves %2%3 to hand. - + %1 puts %2%3 into his library. - + %1 puts %2%3 into her library. - + %1 puts %2%3 on bottom of his library. - + %1 puts %2%3 on bottom of her library. - + %1 puts %2%3 on top of his library. - + %1 puts %2%3 on top of her library. - + %1 puts %2%3 into his library at position %4. - + %1 puts %2%3 into her library at position %4. - + %1 moves %2%3 to sideboard. - + %1 plays %2%3. - + %1 takes a mulligan to %n. + female + + + + + + + + + %1 takes a mulligan to %n. + male @@ -1994,74 +2070,620 @@ Local version is %1, remote version is %2. + %1 flips %2 face-down. + female + + + + + %1 flips %2 face-down. + male + + + + + %1 flips %2 face-up. + female + + + + + %1 flips %2 face-up. + male + + + + + %1 destroys %2. + female + + + + + %1 destroys %2. + male + + + + + %1 unattaches %2. + female + + + + + %1 unattaches %2. + male + + + + + %1 creates token: %2%3. + female + + + + + %1 creates token: %2%3. + male + + + + + %1 points from her %2 to herself. + female + + + + + %1 points from his %2 to himself. + male + + + + + %1 points from her %2 to %3. + p1 female, p2 female + + + + + %1 points from her %2 to %3. + p1 female, p2 male + + + + + %1 points from his %2 to %3. + p1 male, p2 female + + + + + %1 points from his %2 to %3. + p1 male, p2 male + + + + + %1 points from %2's %3 to herself. + card owner female, target female + + + + + %1 points from %2's %3 to herself. + card owner male, target female + + + + + %1 points from %2's %3 to himself. + card owner female, target male + + + + + %1 points from %2's %3 to himself. + card owner male, target male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4. + p1 male, p2 male, p3 male + + + + + %1 points from her %2 to her %3. + female + + + + + %1 points from his %2 to his %3. + male + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 female + + + + + %1 points from her %2 to %3's %4. + p1 female, p2 male + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 female + + + + + %1 points from his %2 to %3's %4. + p1 male, p2 male + + + + + %1 points from %2's %3 to her own %4. + card owner female, target female + + + + + %1 points from %2's %3 to her own %4. + card owner male, target female + + + + + %1 points from %2's %3 to his own %4. + card owner female, target male + + + + + %1 points from %2's %3 to his own %4. + card owner male, target male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 female, p2 male, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 female, p3 male + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 female + + + + + %1 points from %2's %3 to %4's %5. + p1 male, p2 male, p3 male + + + + + %1 places %n %2 counter(s) on %3 (now %4). + female + + + + + + + + + %1 places %n %2 counter(s) on %3 (now %4). + male + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + female + + + + + + + + + %1 removes %n %2 counter(s) from %3 (now %4). + male + + + + + + + + + %1 taps her permanents. + female + + + + + %1 untaps her permanents. + female + + + + + %1 taps his permanents. + male + + + + + %1 untaps his permanents. + male + + + + + %1 taps %2. + female + + + + + %1 untaps %2. + female + + + + + %1 taps %2. + male + + + + + %1 untaps %2. + male + + + + + %1 sets counter %2 to %3 (%4%5). + female + + + + + %1 sets counter %2 to %3 (%4%5). + male + + + + + %1 sets %2 to not untap normally. + female + + + + + %1 sets %2 to not untap normally. + male + + + + + %1 sets %2 to untap normally. + female + + + + + %1 sets %2 to untap normally. + male + + + + + %1 sets PT of %2 to %3. + female + + + + + %1 sets PT of %2 to %3. + male + + + + + %1 sets annotation of %2 to %3. + female + + + + + %1 sets annotation of %2 to %3. + male + + + + + %1 is looking at the top %2 cards %3. + female + + + + + %1 is looking at the top %2 cards %3. + male + + + + + %1 is looking at %2. + female + + + + + %1 is looking at %2. + male + + + + + %1 stops looking at %2. + female + + + + + %1 stops looking at %2. + male + + + + + %1 reveals %2 to %3. + p1 female, p2 female + + + + + %1 reveals %2 to %3. + p1 female, p2 male + + + + + %1 reveals %2 to %3. + p1 male, p2 female + + + + + %1 reveals %2 to %3. + p1 male, p2 male + + + + + %1 reveals %2. + female + + + + + %1 reveals %2. + male + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 randomly reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 randomly reveals %2%3. + female + + + + + %1 randomly reveals %2%3. + male + + + + + %1 reveals %2%3 to %4. + p1 female, p2 female + + + + + %1 reveals %2%3 to %4. + p1 female, p2 male + + + + + %1 reveals %2%3 to %4. + p1 male, p2 female + + + + + %1 reveals %2%3 to %4. + p1 male, p2 male + + + + + %1 reveals %2%3. + female + + + + + %1 reveals %2%3. + male + + + + + It is now %1's turn. + female + + + + + It is now %1's turn. + male + + + + %1 draws his initial hand. - + %1 draws her initial hand. - - %1 flips %2 face-down. - - - - - %1 flips %2 face-up. - - - - - %1 destroys %2. - - - - + %1 attaches %2 to %3's %4. + p1 female, p2 female - - %1 unattaches %2. + + %1 attaches %2 to %3's %4. + p1 female, p2 male - - %1 creates token: %2%3. + + %1 attaches %2 to %3's %4. + p1 male, p2 female - - %1 points from %2's %3 to %4. - - - - - %1 points from %2's %3 to %4's %5. + + %1 attaches %2 to %3's %4. + p1 male, p2 male - - %1 places %n %2 counter(s) on %3 (now %4). - - - - - - - - - %1 removes %n %2 counter(s) from %3 (now %4). - - - - - - - - + red @@ -2070,7 +2692,7 @@ Local version is %1, remote version is %2. - + yellow @@ -2079,7 +2701,7 @@ Local version is %1, remote version is %2. - + green @@ -2088,162 +2710,62 @@ Local version is %1, remote version is %2. - - his permanents - - - - - her permanents - - - - - %1 %2 %3. - - - - - taps - - - - - untaps - - - - - %1 sets counter %2 to %3 (%4%5). - - - - - %1 sets %2 to not untap normally. - - - - - %1 sets %2 to untap normally. - - - - - %1 sets PT of %2 to %3. - - - - - %1 sets annotation of %2 to %3. - - - - - %1 is looking at the top %2 cards %3. - - - - - %1 is looking at %2. - - - - - %1 stops looking at %2. - - - - - %1 reveals %2 to %3. - - - - - %1 reveals %2. - - - - - %1 randomly reveals %2%3 to %4. - - - - - %1 randomly reveals %2%3. - - - - - %1 reveals %2%3 to %4. - - - - - %1 reveals %2%3. - - - - - It is now %1's turn. - - - - + untap step - + upkeep step - + draw step - + first main phase - + beginning of combat step - + declare attackers step - + declare blockers step - + combat damage step - + end of combat step - + second main phase - + ending phase - + It is now the %1. @@ -3234,67 +3756,67 @@ Please enter a name: UserList - + Users online: %1 - + Users in this room: %1 - + Buddies online: %1 / %2 - + Ignored users online: %1 / %2 - + %1's games - + User &details - + Direct &chat - + Show this user's &games - + Add to &buddy list - + Remove from &buddy list - + Add to &ignore list - + Remove from &ignore list - + Ban from &server diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 05b3c0d9d..a4167009e 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -468,8 +468,9 @@ ResponseCode Server_ProtocolHandler::cmdRoomSay(Command_RoomSay *cmd, CommandCon if ((totalSize > server->getMaxMessageSizePerInterval()) || (totalCount > server->getMaxMessageCountPerInterval())) return RespChatFlood; } + msg.replace(QChar('\n'), QChar(' ')); - room->say(this, cmd->getMessage()); + room->say(this, msg); return RespOk; } From fbc9ff7601f292453532af6d9e22bbc2edfddf07 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 9 Jul 2011 12:14:07 +0200 Subject: [PATCH 84/87] extra logging --- servatrice/src/server_logger.cpp | 7 +++++-- servatrice/src/server_logger.h | 3 ++- servatrice/src/serversocketinterface.cpp | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index de08c2881..7cfaf3ed3 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -31,13 +31,16 @@ ServerLogger::~ServerLogger() flushBuffer(); } -void ServerLogger::logMessage(QString message) +void ServerLogger::logMessage(QString message, ServerSocketInterface *ssi) { if (!logFile) return; bufferMutex.lock(); - buffer.append(QDateTime::currentDateTime().toString() + " " + QString::number((qulonglong) QThread::currentThread(), 16) + " " + message); + QString ssiString; + if (ssi) + ssiString = QString::number((qulonglong) ssi) + " "; + buffer.append(QDateTime::currentDateTime().toString() + " " + QString::number((qulonglong) QThread::currentThread(), 16) + " " + ssiString + message); bufferMutex.unlock(); emit sigFlushBuffer(); diff --git a/servatrice/src/server_logger.h b/servatrice/src/server_logger.h index 62d785372..77c7f12d7 100644 --- a/servatrice/src/server_logger.h +++ b/servatrice/src/server_logger.h @@ -9,6 +9,7 @@ class QSocketNotifier; class QFile; +class ServerSocketInterface; class ServerLogger : public QObject { Q_OBJECT @@ -17,7 +18,7 @@ public: ~ServerLogger(); static void hupSignalHandler(int unused); public slots: - void logMessage(QString message); + void logMessage(QString message, ServerSocketInterface *ssi = 0); private slots: #ifdef Q_OS_UNIX void handleSigHup(); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index f02747cae..f8e01ab47 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -93,7 +93,8 @@ void ServerSocketInterface::flushXmlBuffer() void ServerSocketInterface::readClient() { QByteArray data = socket->readAll(); - logger->logMessage(QString(data)); + if (!data.contains("logMessage(QString(data), this); xmlReader->addData(data); while (!xmlReader->atEnd()) { From a4359b22ffe691d11f52d134a512f9fbab417341 Mon Sep 17 00:00:00 2001 From: Ondrej Trhon Date: Sun, 10 Jul 2011 13:39:26 +0200 Subject: [PATCH 85/87] Czech translation finished --- cockatrice/translations/cockatrice_cs.ts | 1220 +++++++++++----------- 1 file changed, 614 insertions(+), 606 deletions(-) diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index d2acd311a..b43c9b208 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -6,32 +6,32 @@ &Set counter... - + &Nastavit žeton... Ctrl+L - + Ctrl+L F11 - + F11 F12 - + F12 Set counter - + Nastavit žeton New value for counter '%1': - + Nová hodnota pro žeton '%1': @@ -39,77 +39,77 @@ Zone background pictures - + Pozadí zón Path to hand background: - + Cesta k pozadí ruky: Path to stack background: - + Cesta k pozadí stacku: Path to table background: - + Cesta k pozadí stolu: Path to player info background: - + Cesta k pozadí informací o uživateli: Path to picture of card back: - + Cesta k rubu karet: Card rendering - + Vykreslování karet Display card names on cards having a picture - + Zobrazit jména karet na kartách s obrázky Hand layout - + Rozvržení ruky Display hand horizontally (wastes space) - + Zobrazit ruku horizontálně (zabírá více místa) Table grid layout - + Rozložení herní mřížky Invert vertical coordinate - + Převrátit vertikální souřadnice Zone view layout - + Rozvržení zón Sort by name - + Seřadit dle jména Sort by type - + Seřadit dle typu @@ -118,7 +118,7 @@ Choose path - + Vyberte cestu @@ -126,27 +126,27 @@ Name - + Jméno Sets - + Sady Mana cost - + Sesílací cena Card type - + Typ karty P/T - + S/O @@ -154,42 +154,42 @@ Hide card info - + Skrýt informace o kartě Show card only - + Zobrazit pouze kartu Show text only - + Zobrazit pouze text Show full info - + Zobrazit všechny informace Name: - + Jméno: Mana cost: - + Sesílací cena: Card type: - + Typ karty: P / T: - + S / O: @@ -197,197 +197,197 @@ &Play - + &Zahrát &Hide - + &Skrýt &Tap - + &Tapnout &Untap - + &Odtapnout Toggle &normal untapping - + Přepnout &normální odtapnutí &Flip - + &Otočit &Clone - + &Zdvojit Ctrl+H - + Ctrl+H &Attach to card... - + Připojit ke k&artě... Ctrl+A - + Ctrl+A Unattac&h - + Od&pojit &Power / toughness - + &Síla / odolnost &Increase power - + &Zvýšit sílu Ctrl++ - + Ctrl++ &Decrease power - + &Snížit sílu Ctrl+- - + Ctrl+- I&ncrease toughness - + &Zvýšit odolnost Alt++ - + Alt++ D&ecrease toughness - + &Snížit sílu Alt+- - + Alt+- In&crease power and toughness - + &Zvýšit sílu a odolnost Ctrl+Alt++ - + Ctrl+Alt++ Dec&rease power and toughness - + &Snížit sílu a odolnost Ctrl+Alt+- - + Ctrl+Alt+- Set &power and toughness... - + Nastavit &sílu a odolnost... Ctrl+P - + Ctrl+P &Set annotation... - + Na&stavit poznámku... red - + červená yellow - + žlutá green - + zelená &Add counter (%1) - + Přid&at žeton (%1) &Remove counter (%1) - + Odst&ranit žeton (%1) &Set counters (%1)... - + Na&stavit žetony (%1)... &top of library - + &vršek knihovny &bottom of library - + &spodek knihovny &graveyard - + &hřbitov Ctrl+Del - + Ctrl+Del &exile - + &exilnout &Move to - + &Přesunout @@ -396,181 +396,181 @@ his hand nominative - + jeho ruka %1's hand nominative - + ruka hráče %1 of his hand genitive - + jeho ruky of %1's hand genitive - + ruky hráče %1 his hand accusative - + jeho ruka %1's hand accusative - + ruka hráče %1 his library nominative - + knihovna %1's library nominative - + knihovna hráče %1 of his library genitive - + jeho knihovny of %1's library genitive - + knihovny hráče %1 his library accusative - + knihovnu %1's library accusative - + knihovna hráče %1 his graveyard nominative - + jeho hřbitov %1's graveyard nominative - + hřbitov hráče %1 of his graveyard genitive - + jeho hřbitova of %1's graveyard genitive - + hřbitova hráče %1 his graveyard accusative - + jeho hřbitov %1's graveyard accusative - + hřbitov hráče %1 his exile nominative - + jeho exilnuté karty %1's exile nominative - + exilnuté karty hráče %1 of his exile genitive - + exilnutých karet of %1's exile genitive - + exilnutých karet hráče %1 his exile accusative - + jeho exilnuté karty %1's exile accusative - + exilnuté karty hráče %1 his sideboard nominative - + jeho sideboard %1's sideboard nominative - + sideboard hráče %1 of his sideboard genitive - + sideboardu hráče of %1's sideboard genitive - + sideboardu hráče %1 his sideboard accusative - + jeho sideboard %1's sideboard accusative - + sideboard hráče %1 @@ -578,12 +578,12 @@ Enable &price tag feature (using data from blacklotusproject.com) - + &Povolit zobrazovaní cen (použijí se data z blacklotusproject.com) General - + Obecné @@ -591,17 +591,17 @@ Number - + Počet Card - + Karta Price - + Cena @@ -609,22 +609,22 @@ Load &local deck - + Nahrát &lokální balíček Load d&eck from server - + Nahrát &balíček ze serveru Ready to s&tart - + Připraven ke &hře Load deck - + Nahrát balíček @@ -632,37 +632,37 @@ Card name: - + Jméno karty: Card text: - + Text karty: Card type (OR): - + Typ karty (NEBO): Color (OR): - + Barva (NEBO): O&K - + O&K &Cancel - + &Cancel Card search - + Hledat kartu @@ -670,37 +670,37 @@ &Host: - + &Hostitel: &Port: - + &Port: Player &name: - + Jméno &hráče: P&assword: - + H&eslo: &OK - + &OK &Cancel - + &Zrušit Connect to server - + Připojit k serveru @@ -708,87 +708,87 @@ &Description: - + &Popis: P&layers: - + H&ráči: Game type - + Formát &Password: - + &Heslo: Only &buddies can join - + Jen pro &přátele Only &registered users can join - + Jen pro &registrované Joining restrictions - + Omezení připojení &Spectators allowed - + &Diváci povoleni Spectators &need a password to join - + Diváci &musí znát heslo Spectators can &chat - + Diváci mohou &chatovat Spectators see &everything - + Diváci vidí &všechno Spectators - + Diváci &OK - + &OK &Cancel - + &Zrušit Create game - + Vytvořit hru Error - + Chyba Server error. - + Chyba serveru. @@ -796,82 +796,82 @@ &Name: - + &Jméno: Token - + Token C&olor: - + B&arva: white - + bílá blue - + modrá black - + černá red - + červená green - + zelená multicolor - + multicolor colorless - + bezbarvý &P/T: - + &S/O: &Annotation: - + &Poznámka: &Destroy token when it leaves the table - + &Token se při odchodu z bojiště zničí &OK - + &OK &Cancel - + &Zrušit Create token - + Vytvořit token @@ -879,32 +879,32 @@ &Refresh - + &Obnovit &OK - + &OK &Cancel - + &Zrušit Load deck from clipboard - + Nahrát balíček ze schránky Error - + Chyba Invalid deck list. - + Neplatný formát balíčku. @@ -912,17 +912,17 @@ O&K - + O&K &Cancel - + &Zrušit Load deck - + Nahrát balíček @@ -932,57 +932,57 @@ Error - + Chyba Your card database is invalid. Would you like to go back and set the correct path? - + Cesta k databázi je neplatná. Chcete se vrátit a nastavit správnou? The path to your deck directory is invalid. Would you like to go back and set the correct path? - + Cesta k adresáři s balíčky je neplatná. Chcete se vrátit a nastavit správnou? The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Cesta k adresáři s obrázky je neplatná. Chcete se vrátit a nastavit správnou? Settings - + Nastavení General - + Obecné Appearance - + Vzhled User interface - + Uživatelské rozhraní Deck editor - + Editor balíčků Messages - + Zprávy &Close - + &Zavřít @@ -996,77 +996,77 @@ Error - + Chyba Wrong password. - + Špatné heslo. Spectators are not allowed in this game. - + Do této hry je divákům přístup zakázán. The game is already full. - + Hra je plná. The game does not exist any more. - + Hra již neexistuje. This game is only open to registered users. - + Hra je určena jen pro registrované. This game is only open to its creator's buddies. - + Hra je dostupná jen pro přátele zakládajícícho. You are being ignored by the creator of this game. - + Zakladatel hry vás ignoruje. Join game - + Připojit ke hře Password: - + Heslo: Games - + Hry Show &full games - + Ukázat &plné hry C&reate - + V&ytvořit &Join - + &Připojit J&oin as spectator - + P&řipojit se jako divák @@ -1074,7 +1074,7 @@ Esc - + Esc @@ -1082,67 +1082,67 @@ yes - + ano yes, free for spectators - + diváci povoleni no - + ne buddies only - + jen pro přátele reg. users only - + jen pro registrované not allowed - + nepovolené Description - + Popis Creator - + Zakladatel Game type - + Formát Password - + Heslo Restrictions - + Omezení Players - + Hráči Spectators - + Diváci @@ -1151,49 +1151,49 @@ English - + Česky Choose path - + Vyberte cestu Personal settings - + Osobní nastavení Language: - + Jazyk: Download card pictures on the fly - + Stahovat obrázky karet za běhu Paths - + Cesty Decks directory: - + Adresář s balíčky: Pictures directory: - + Adresář s obrázky: Path to card database: - + Karetní databáze: @@ -1201,104 +1201,105 @@ There are too many concurrent connections from your address. - + Z vaší adresy jde mnoho současných připojení. Banned by moderator. - + Zabanován moderátorem. Unknown reason. - + Neznámý důvod. Connection closed - + Připojení uzavřeno The server has terminated your connection. Reason: %1 - + Server přerušil spojení. +Důvod: %1 Number of players - + Počet hráčů Please enter the number of players. - + Vložte počet hráčů. Player %1 - + Hráč %1 About Cockatrice - + O Cockatrice Version %1 - + Verze %1 Authors: - + Autoři: Translators: - + Překlad: Spanish: - + Španělština: Portugese (Portugal): - + Portugalština (Portugalsko): Portugese (Brazil): - + Portugalština (Brazílie): French: - + Francouzština: Japanese: - + Japonština: Russian: - + Ruština: Czech: - + Čeština: Slovak: - + Slovenština: @@ -1308,120 +1309,123 @@ Reason: %1 Error - + Chyba Server timeout - + Vypršel časový limit Invalid login data. - + Nesprávné údaje uživatele. There is already an active session using this user name. Please close that session first and re-login. - + S tímto uživatelským jménem jste již připojeni. +Přerušte spojení a znovu se přihlašte. Socket error: %1 - + Chyba socketu: %1 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. - + Snažíte se připojit na zastaralý server. Prosíme, stáhněte si nižší verzi Cockatrice, nebo se připojte k odpovídajícímu serveru. +Lokální verze je %1, verze serveru je %2. Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Váš klient je zastaralý. Prosíme, aktualizujte Cockatrice na vyšší verzi. +Lokální verze je %1, verze serveru je %2. Connecting to %1... - + Připojování k %1... Disconnected - + Odpojeno Logged in at %1 - + Přihlášeno k %1 &Connect... - + &Připojit... &Disconnect - + &Odpojit Start &local game... - + Spustit &lokální hru... &Deck editor - + &Editor balíčků &Full screen - + &Celá obrazovka Ctrl+F - + CTRL+F &Settings... - + &Nastavení... &Exit - + &Konec &Cockatrice - + &Cockatrice &About Cockatrice - + &O Cockatrice &Help - + &Nápověda Are you sure? - + Jste si jisti? There are still open games. Are you sure you want to quit? - + Některé hry jsou stále otevřené. Opravdu chcete odejít? @@ -1429,496 +1433,496 @@ Local version is %1, remote version is %2. Connecting to %1... - + Připojování k %1... Connected. - + Připojeno. Disconnected from server. - + Odpojeno. Invalid password. - + Nesprávné heslo. Protocol version mismatch. Client: %1, Server: %2 - + Neodpovídá verze protokolu. Klient: %1, Server: %2 Protocol error. - + Chyba protokolu. You have joined game #%1. - + Připojili jste se ke hře #%1. %1 has joined the game. - + %1 se připojil ke hře. %1 has left the game. - + %1 opustil hru. The game has been closed. - + Hra byla ukončena. %1 is now watching the game. - + %1 nyní sleduje hru. %1 is not watching the game any more. - + %1 přestal sledovat hru. %1 has loaded a local deck. - + %1 nahrál lokální balíček. %1 has loaded deck #%2. - + %1 nahrál balíček #%2. %1 is ready to start the game. - + %1 je připraven ke hře. %1 is not ready to start the game any more. - + %1 již není připraven ke hře. %1 has conceded the game. - + %1 ukončil hru. The game has started. - + Hra začíná. %1 shuffles his library. - + %1 míchá knihovnu. %1 rolls a %2 with a %3-sided die. - + %1 hodil kostkou %2 (%3 stěn). %1 draws %n card(s). - - - - + + %1 si lízl %n kartu. + %1 si lízl %n karty. + %1 si lízl %n karet. %1 undoes his last draw. - + %1 vrátil zpět svoje poslední líznutí. %1 undoes his last draw (%2). - + %1 vrátil svoje poslední líznutí (%2). from table - + z bojiště from graveyard - + ze hřbitova from exile - + z exilnutých karet from hand - + z ruky the bottom card of his library - + spodní kartu knihovny from the bottom of his library - + ze spodku knihovny the top card of his library - + vrchní kartu knihovny from the top of his library - + z vršku knihovny from library - + z knihovny from sideboard - + ze sideboardu from the stack - + ze stacku a card - + kartu %1 gives %2 control over %3. - + %1 předává kontrolu hráči %2 karty %3. %1 puts %2 into play tapped%3. - + %1 dává kartu %2 do hry %3 tapnutou. %1 puts %2 into play%3. - + %1 dává kartu %2 %3 do hry. %1 puts %2%3 into graveyard. - + %1 dává kartu %2%3 do hřbitova. %1 exiles %2%3. - + %1 exiluje %2%3. %1 moves %2%3 to hand. - + %1 přesouvá %2%3 do ruky. %1 puts %2%3 into his library. - + %1 dává %2%3 do knihovny. %1 puts %2%3 on bottom of his library. - + %1 dává %2%3 na spodek knihovny. %1 puts %2%3 on top of his library. - + %1 dává %2%3 na vršek knihovny. %1 puts %2%3 into his library at position %4. - + %1 dává %2%3 knihovny na pozici %4. %1 moves %2%3 to sideboard. - + %1 přesouvá %2%3 do sideboardu. %1 plays %2%3. - + %1 sesílá %2%3. %1 takes a mulligan to %n. - - - - + + %1 mulliganuje do %n. + %1 mulliganuje do %n. + %1 mulliganuje do %n. %1 draws his initial hand. - + %1 líže startovní ruku. %1 flips %2 face-down. - + %1 otáčí %2 lícem dolů. %1 flips %2 face-up. - + %1 otáčí %2 lícem vzhůru. %1 destroys %2. - + %1 ničí %2. %1 attaches %2 to %3's %4. - + %1 připojuje %2 k %3 %4. %1 unattaches %2. - + %1 odpojuje %2. %1 creates token: %2%3. - + %1 vykládá token %2%3. %1 points from %2's %3 to %4. - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4's %5. - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 places %n %2 counter(s) on %3 (now %4). - - - - + + %1 pokládá %n %2 žeton na %3 (nyní %4). + %1 pokládá %n %2 žetony na %3 (nyní %4). + %1 pokládá %n %2 žetonů na %3 (nyní %4). %1 removes %n %2 counter(s) from %3 (now %4). - - - - + + %1 odebírá %n %2 žeton z %3 (nyní %4). + %1 odebírá %n %2 žetony z %3 (nyní %4). + %1 odebírá %n %2 žetonů z %3 (nyní %4). red - - - - + + červený + červené + červených yellow - - - - + + žlutý + žluté + žlutých green - - - - + + zelený + zelené + zelených his permanents - + permanenty %1 %2 %3. - + %1 %2 %3. taps - + tapuje untaps - + odtapuje %1 sets counter %2 to %3 (%4%5). - + %1 nastavuje počet %2 žetonů na %3 (%4%5). %1 sets %2 to not untap normally. - + %1 nastavuje %2 na neodtapování. %1 sets %2 to untap normally. - + %1 nastavuje %2 na standardní odtapnutí. %1 sets PT of %2 to %3. - + %1 nastavuje sílu a odolnost pro %2 na %3. %1 sets annotation of %2 to %3. - + %1 nastavuje poznámku pro %2 na %3. %1 is looking at the top %2 cards %3. - + %1 si prohlíží %2 vrchních karet %3. %1 is looking at %2. - + %1 si prohlíží %2. %1 stops looking at %2. - + %1 si přestává prohlížet %2. %1 reveals %2 to %3. - + %1 ukazuje %2 hráči %3. %1 reveals %2. - + %1 ukazuje %2. %1 randomly reveals %2%3 to %4. - + %1 náhodně ukazuje %2%3 hráči %4. %1 randomly reveals %2%3. - + %1 náhodně ukazuje %2%3. %1 reveals %2%3 to %4. - + %1 ukazuje %2%3 hráči %4. %1 reveals %2%3. - + %1 ukazuje %2%3. It is now %1's turn. - + Nyní je kolo hráče %1. untap step - + Odtapovací fáze upkeep step - + Upkeep draw step - + Lízací fáze first main phase - + První hlavní fáze beginning of combat step - + Začátek bojové fáze declare attackers step - + Oznámení útočníků declare blockers step - + Oznámení blokujících combat damage step - + Udělení bojového zranění end of combat step - + Konec bojové fáze second main phase - + Druhá hlavní fáze ending phase - + Konec kola It is now the %1. - + Nyní je %1. @@ -1926,22 +1930,22 @@ Local version is %1, remote version is %2. Add message - + Přidat zprávu Message: - + Zpráva: &Add - + &Přidat &Remove - + &Odstranit @@ -1949,57 +1953,57 @@ Local version is %1, remote version is %2. Untap step - + Odtapovací fáze Upkeep step - + Upkeep Draw step - + Lízací fáze First main phase - + První hlavní fáze Beginning of combat step - + Začátek bojové fáze Declare attackers step - + Oznámení útočníků Declare blockers step - + Oznámení blokujících Combat damage step - + Udělení bojového zranění End of combat step - + Konec bojové fáze Second main phase - + Druhá hlavní fáze End of turn step - + Konec kola @@ -2007,269 +2011,269 @@ Local version is %1, remote version is %2. &View graveyard - + &Zobrazit hřbitov &View exile - + &Zobrazit exilnuté karty Player "%1" - + Hráč "%1" &Graveyard - + &Hřbitov &Exile - + &Exilnuté karty Move to &top of library - + Přesunout na &vršek knihovny Move to &bottom of library - + Přesunout na &spodek knihovny Move to &graveyard - + Přesunout do &hřbitova Move to &exile - + &Exilnout Move to &hand - + Přesunout do &ruky &View library - + &Zobrazit knihovnu View &top cards of library... - + Zobrazit &vrchní karty knihovny... Reveal &library to - + Ukázat &knihovnu Reveal t&op card to - + Ukázat v&rchní kartu &View sideboard - + &Zobrazit sideboard &Draw card - + &Líznout kartu D&raw cards... - + L&íznout karty... &Undo last draw - + &Vrátit zpět poslední líznutí Take &mulligan - + &Mulliganovat &Shuffle - + &Zamíchat Move top cards to &graveyard... - + Přesunout vrchní karty do &hřbitova... Move top cards to &exile... - + &Exilnout vrchní karty... Put top card on &bottom - + Dát kartu na &spodek &Hand - + &Ruka &Reveal to - + &Ukázat Reveal r&andom card to - + Ukázat kartu n&áhodně &Sideboard - + &Sideboard &Library - + &Knihovna &Counters - + &Žetony &Untap all permanents - + &Odtapnout všechny permanenty R&oll die... - + H&odit kostkou... &Create token... - + &Vytvořit token... C&reate another token - + V&ytvořit další token S&ay - + &Chat C&ard - + K&arta &All players - + &Všem hráčům Ctrl+F3 - + Ctrl+F3 F3 - + F3 Ctrl+W - + Ctrl+W F4 - + F4 Ctrl+D - + Ctrl+D Ctrl+E - + Ctrl+E Ctrl+Shift+D - + Ctrl+Shift+D Ctrl+M - + Ctrl+M Ctrl+S - + Ctrl+S Ctrl+U - + Ctrl+U Ctrl+I - + Ctrl+I Ctrl+T - + Ctrl+T Ctrl+G - + Ctrl+G View top cards of library - + Zobrazit vrchní karty knihovny Number of cards: - + Počet karet: Draw cards - + Líznout karty @@ -2277,52 +2281,52 @@ Local version is %1, remote version is %2. Number: - + Počet: Move top cards to grave - + Přesunout vrchní karty do hřbitova Move top cards to exile - + Exilnout vrchní karty Roll die - + Hodit kostkou Number of sides: - + Počet stran: Set power/toughness - + Nastavit sílu/odolnost Please enter the new PT: - + Vložte novou odolnost/sílu: Set annotation - + Nastavit poznámku Please enter the new annotation: - + Vložte novou poznámku: Set counters - + Nastavit žetony @@ -2330,47 +2334,47 @@ Local version is %1, remote version is %2. local deck - + lokální balíček deck #%1 - + bal94ek #%1 User &details - + Detaily &uživatele Direct &chat - + &Chatovat Add to &buddy list - + Přidat mezi &přátele Remove from &buddy list - + Odstranit z &přátel Add to &ignore list - + Přidat do &ignorovaných Remove from &ignore list - + Odstranit z &ignorovaných Kick from &game - + Vyhodit ze &hry @@ -2378,27 +2382,27 @@ Local version is %1, remote version is %2. Maindeck - + Maindeck Sideboard - + Sideboard Cockatrice decks (*.cod) - + Balíčky cockatrice (*.cod) Plain text decks (*.dec *.mwDeck) - + Čistý text (*.dec*.mwDeck) All files (*.*) - + Všechny soubory (*.*) @@ -2406,17 +2410,17 @@ Local version is %1, remote version is %2. Name - + Jméno ID - + ID Upload time - + Průběh nahrávání @@ -2424,32 +2428,32 @@ Local version is %1, remote version is %2. Rooms - + Místnosti Joi&n - + &Připojit Room - + Místnost Description - + Popis Players - + Hráči Games - + Hry @@ -2457,12 +2461,12 @@ Local version is %1, remote version is %2. Short name - + Krátký název Long name - + Dlouhý název @@ -2470,37 +2474,37 @@ Local version is %1, remote version is %2. Update server &message - + Aktualizovat &zprávu serveru Server administration functions - + Administrační funkce serveru &Unlock functions - + &Odemknout funkce &Lock functions - + &Zamknout funkce Unlock administration functions - + Odemknout administrační funkce Do you really want to unlock the administration functions? - + Opravdu chcete odemknout administrační funkce? Administration - + Administrace @@ -2508,66 +2512,67 @@ Local version is %1, remote version is %2. Local file system - + Lokální systém souborů Server deck storage - + Balíčky na serveru Open in deck editor - + Otevřít v editoru balíčků Upload deck - + Nahrát balíček Download deck - + Stáhnout balíček New folder - + Nová složka Delete - + Smazat Enter deck name - + Vložit jméno balíčku This decklist does not have a name. Please enter a name: - + Tentobalíček nemá jméno. +Prosím vložte jméno: Unnamed deck - + Bezejmenný balíček Name of new folder: - + Název nové složky: Deck storage - + Uložiště balíčků @@ -2575,137 +2580,137 @@ Please enter a name: F5 - + F5 F6 - + F6 F7 - + F7 F8 - + F8 F9 - + F9 F10 - + F10 &Phases - + &Fáze &Game - + &Hra Next &phase - + Další &fáze Ctrl+Space - + Ctrl+Space Next &turn - + Další &kolo Ctrl+Return - + Ctrl+Return Ctrl+Enter - + Ctrl+Enter &Remove all local arrows - + &Odstranit všechny lokální šipky Ctrl+R - + CTRL+R &Concede - + &Ukončit hru F2 - + F2 &Leave game - + &Opustit hru Ctrl+Q - + CTRL+Q &Say: - + &Chat: Concede - + Ukončit hru Are you sure you want to concede this game? - + Opravdu chcete ukončit tuto hru? Leave game - + Opustit hru Are you sure you want to leave this game? - + Opravdu chcete opustit tuto hru? Kicked - + Vyhozen You have been kicked out of the game. - + Byli jste vyhozeni ze hry. Game %1: %2 - + Hra %1: %2 @@ -2713,32 +2718,32 @@ Please enter a name: Personal &talk - + Osobní &diskuze &Leave - + &Odejít This user is ignoring you. - + Tento uživatel vás ignoruje. %1 has left the server. - + %1 opustil server. %1 has joined the server. - + %1 se připojil k serveru. Talking to %1 - + Mlávíte k %1 @@ -2746,27 +2751,27 @@ Please enter a name: &Say: - + &Chat: Chat - + Chatovat &Room - + &Místnost &Leave room - + &Opustit místnost You are flooding the chat. Please wait a couple of seconds. - + Píšete příliš intenzivně. Počkejte pár sekund. @@ -2774,7 +2779,7 @@ Please enter a name: Server - + Server @@ -2782,7 +2787,7 @@ Please enter a name: User lists - + Seznam uživatelů @@ -2790,42 +2795,42 @@ Please enter a name: User information - + Informace o uživateli Real name: - + Pravé jméno: Location: - + Místo: User level: - + Úroveň: Administrator - + Administrátor Judge - + Judge Registered user - + Registrovaný Unregistered user - + Neregistrovaný @@ -2833,37 +2838,37 @@ Please enter a name: General interface settings - + Obecné &Double-click cards to play them (instead of single-click) - + &Pro zahraní karty je třeba dvojklik Animation settings - + Animace &Tap/untap animation - + &Animace tapnutí/odtapnutí Enable &sounds - + Povolit &zvuky Path to sounds directory: - + Adresář se zvuky: Choose path - + Vyberte cestu @@ -2871,68 +2876,69 @@ Please enter a name: Users online: %1 - + Připojených uživatelů: %1 Users in this room: %1 - + Uživatelů v této místnosti: %1 Buddies online: %1 / %2 - + Přátelé online: %1 / %2 Ignored users online: %1 / %2 - + Ignorovaných online: %1 / %2 User &details - + &Detaily uživatele Direct &chat - + &Chatovat Add to &buddy list - + Přidat mezi &přátele Remove from &buddy list - + Odstranit z &přátel Add to &ignore list - + Přidat mezi &ignorované Remove from &ignore list - + Odstranit z &ignorovaných Ban from &server - + &Zabanovat Duration - + Délka Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - + Vložte dobu trvání banu (v minutách). +Hodnota 0 je pro ban bez omezení. @@ -2940,196 +2946,198 @@ Enter 0 for an indefinite ban. &Search... - + &Hledat... &Clear search - + &Vyčistit hledání &Search for: - + &Vyhledat: Deck &name: - + &Název balíčku: &Comments: - + &Komentář: &Update prices - + Akt&ualizovat ceny Ctrl+U - + CTRL+U Deck editor [*] - + Editor balíčků [*] &New deck - + &Nový balíček &Load deck... - + &Nahrát balíček... &Save deck - + &Uložit balíček Save deck &as... - + Uložit balíček &jako... Load deck from cl&ipboard... - + Nahrát balíček ze s&chránky... Save deck to clip&board - + Vložit balíček do &schránky &Print deck... - + &Vytisknout balíček... &Close - + &Zavřít Ctrl+Q - + CTRL+Q &Edit sets... - + &Upravit sasy... &Deck - + &Balíček &Card database - + Databáze &karet Add card to &maindeck - + Přidat kartu do &balíčku Return - + Return Enter - + Enter Add card to &sideboard - + Přidat kartu do &sideboardu Ctrl+Return - + Ctrl+Return Ctrl+Enter - + Ctrl+Enter &Remove row - + &Smazat řádek Del - + Del &Increment number - + &Zvýšit počet + - + + &Decrement number - + &Snížit počet - - + - Are you sure? - + Jste si jisti? The decklist has been modified. Do you want to save the changes? - + Balíček byl upraven. +Chcete uložit změny? Load deck - + Nahrát balíček Error - + Chyba The deck could not be saved. Please check that the directory is writable and try again. - + Balíček nebylo možné uložit. +Zkontrolujte, jestli lze zapisovat do cílového adresáře a zkuste to znovu. Save deck - + Uložit balíček @@ -3137,7 +3145,7 @@ Please check that the directory is writable and try again. Edit sets - + Upravit edice @@ -3145,17 +3153,17 @@ Please check that the directory is writable and try again. sort by name - + seřadit dle jména sort by type - + seřadit dle typu shuffle when closing - + zamíchat po zavření From 8c3a3150b4d765500111b2dca67e78d906c60b51 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 10 Jul 2011 14:29:16 +0200 Subject: [PATCH 86/87] =?UTF-8?q?initial=20Czech=20translation=20by=20Ond?= =?UTF-8?q?=C5=99ej=20Trho=C5=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cockatrice/translations/cockatrice_cs.ts | 1742 +++++++++++++--------- 1 file changed, 1059 insertions(+), 683 deletions(-) diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index fd3280677..61567e4fb 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -6,32 +6,32 @@ &Set counter... - + &Nastavit žeton... Ctrl+L - + Ctrl+L F11 - + F11 F12 - + F12 Set counter - + Nastavit žeton New value for counter '%1': - + Nová hodnota pro žeton '%1': @@ -39,62 +39,62 @@ Zone background pictures - + Pozadí zón Path to hand background: - + Cesta k pozadí ruky: Path to stack background: - + Cesta k pozadí stacku: Path to table background: - + Cesta k pozadí stolu: Path to player info background: - + Cesta k pozadí informací o uživateli: Path to picture of card back: - + Cesta k rubu karet: Card rendering - + Vykreslování karet Display card names on cards having a picture - + Zobrazit jména karet na kartách s obrázky Hand layout - + Rozvržení ruky Display hand horizontally (wastes space) - + Zobrazit ruku horizontálně (zabírá více místa) Table grid layout - + Rozložení herní mřížky Invert vertical coordinate - + Převrátit vertikální souřadnice @@ -104,17 +104,17 @@ Zone view layout - + Rozvržení zón Sort by name - + Seřadit dle jména Sort by type - + Seřadit dle typu @@ -123,7 +123,7 @@ Choose path - + Vyberte cestu @@ -132,7 +132,8 @@ Please enter the duration of the ban (in minutes). Enter 0 for an indefinite ban. - + Vložte dobu trvání banu (v minutách). +Hodnota 0 je pro ban bez omezení. @@ -143,7 +144,7 @@ This is only saved for moderators and cannot be seen by the banned person. &OK - + &OK @@ -161,27 +162,27 @@ This is only saved for moderators and cannot be seen by the banned person. Name - + Jméno Sets - + Sady Mana cost - + Sesílací cena Card type - + Typ karty P/T - + S/O @@ -189,42 +190,42 @@ This is only saved for moderators and cannot be seen by the banned person. Hide card info - + Skrýt informace o kartě Show card only - + Zobrazit pouze kartu Show text only - + Zobrazit pouze text Show full info - + Zobrazit všechny informace Name: - + Jméno: Mana cost: - + Sesílací cena: Card type: - + Typ karty: P / T: - + S / O: @@ -232,57 +233,57 @@ This is only saved for moderators and cannot be seen by the banned person. &Play - + &Zahrát &Hide - + &Skrýt &Tap - + &Tapnout &Untap - + &Odtapnout Toggle &normal untapping - + Přepnout &normální odtapnutí &Flip - + &Otočit &Clone - + &Zdvojit Ctrl+H - + Ctrl+H &Attach to card... - + Připojit ke k&artě... Ctrl+A - + Ctrl+A Unattac&h - + Od&pojit @@ -292,146 +293,296 @@ This is only saved for moderators and cannot be seen by the banned person. &Power / toughness - + &Síla / odolnost &Increase power - + &Zvýšit sílu Ctrl++ - + Ctrl++ &Decrease power - + &Snížit sílu Ctrl+- - + Ctrl+- I&ncrease toughness - + &Zvýšit odolnost Alt++ - + Alt++ D&ecrease toughness - + &Snížit sílu Alt+- - + Alt+- In&crease power and toughness - + &Zvýšit sílu a odolnost Ctrl+Alt++ - + Ctrl+Alt++ Dec&rease power and toughness - + &Snížit sílu a odolnost Ctrl+Alt+- - + Ctrl+Alt+- Set &power and toughness... - + Nastavit &sílu a odolnost... Ctrl+P - + Ctrl+P &Set annotation... - + Na&stavit poznámku... red - + červená yellow - + žlutá green - + zelená &Add counter (%1) - + Přid&at žeton (%1) &Remove counter (%1) - + Odst&ranit žeton (%1) &Set counters (%1)... - + Na&stavit žetony (%1)... &top of library - + &vršek knihovny &bottom of library - + &spodek knihovny &graveyard - + &hřbitov Ctrl+Del - + Ctrl+Del &exile - + &exilnout &Move to - + &Přesunout CardZone + + his hand + nominative + jeho ruka + + + %1's hand + nominative + ruka hráče %1 + + + of his hand + genitive + jeho ruky + + + of %1's hand + genitive + ruky hráče %1 + + + his hand + accusative + jeho ruka + + + %1's hand + accusative + ruka hráče %1 + + + his library + nominative + knihovna + + + %1's library + nominative + knihovna hráče %1 + + + of his library + genitive + jeho knihovny + + + of %1's library + genitive + knihovny hráče %1 + + + his library + accusative + knihovnu + + + %1's library + accusative + knihovna hráče %1 + + + his graveyard + nominative + jeho hřbitov + + + %1's graveyard + nominative + hřbitov hráče %1 + + + of his graveyard + genitive + jeho hřbitova + + + of %1's graveyard + genitive + hřbitova hráče %1 + + + his graveyard + accusative + jeho hřbitov + + + %1's graveyard + accusative + hřbitov hráče %1 + + + his exile + nominative + jeho exilnuté karty + + + %1's exile + nominative + exilnuté karty hráče %1 + + + of his exile + genitive + exilnutých karet + + + of %1's exile + genitive + exilnutých karet hráče %1 + + + his exile + accusative + jeho exilnuté karty + + + %1's exile + accusative + exilnuté karty hráče %1 + + + his sideboard + nominative + jeho sideboard + + + %1's sideboard + nominative + sideboard hráče %1 + + + of his sideboard + genitive + sideboardu hráče + + + of %1's sideboard + genitive + sideboardu hráče %1 + + + his sideboard + accusative + jeho sideboard + + + %1's sideboard + accusative + sideboard hráče %1 + her hand @@ -442,19 +593,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's hand nominative, female owner - + ruka hráče %1 his hand nominative, male owner - + jeho ruka %1's hand nominative, male owner - + ruka hráče %1 @@ -466,19 +617,19 @@ This is only saved for moderators and cannot be seen by the banned person. of %1's hand genitive, female owner - + ruky hráče %1 of his hand genitive, male owner - + jeho ruky of %1's hand genitive, male owner - + ruky hráče %1 @@ -490,19 +641,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's hand accusative, female owner - + ruka hráče %1 his hand accusative, male owner - + jeho ruka %1's hand accusative, male owner - + ruka hráče %1 @@ -514,7 +665,7 @@ This is only saved for moderators and cannot be seen by the banned person. %1's library nominative, female owner - + knihovna hráče %1 @@ -526,7 +677,7 @@ This is only saved for moderators and cannot be seen by the banned person. %1's library nominative, male owner - + knihovna hráče %1 @@ -538,19 +689,19 @@ This is only saved for moderators and cannot be seen by the banned person. of %1's library genitive, female owner - + knihovny hráče %1 of his library genitive, male owner - + jeho knihovny of %1's library genitive, male owner - + knihovny hráče %1 @@ -562,7 +713,7 @@ This is only saved for moderators and cannot be seen by the banned person. %1's library accusative, female owner - + knihovna hráče %1 @@ -574,7 +725,7 @@ This is only saved for moderators and cannot be seen by the banned person. %1's library accusative, male owner - + knihovna hráče %1 @@ -586,19 +737,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's graveyard nominative, female owner - + hřbitov hráče %1 his graveyard nominative, male owner - + jeho hřbitov %1's graveyard nominative, male owner - + hřbitov hráče %1 @@ -610,19 +761,19 @@ This is only saved for moderators and cannot be seen by the banned person. of %1's graveyard genitive, female owner - + hřbitova hráče %1 of his graveyard genitive, male owner - + jeho hřbitova of %1's graveyard genitive, male owner - + hřbitova hráče %1 @@ -634,19 +785,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's graveyard accusative, female owner - + hřbitov hráče %1 his graveyard accusative, male owner - + jeho hřbitov %1's graveyard accusative, male owner - + hřbitov hráče %1 @@ -658,19 +809,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's exile nominative, female owner - + exilnuté karty hráče %1 his exile nominative, male owner - + jeho exilnuté karty %1's exile nominative, male owner - + exilnuté karty hráče %1 @@ -682,19 +833,19 @@ This is only saved for moderators and cannot be seen by the banned person. of %1's exile genitive, female owner - + exilnutých karet hráče %1 of his exile genitive, male owner - + exilnutých karet of %1's exile genitive, male owner - + exilnutých karet hráče %1 @@ -706,19 +857,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's exile accusative, female owner - + exilnuté karty hráče %1 his exile accusative, male owner - + jeho exilnuté karty %1's exile accusative, male owner - + exilnuté karty hráče %1 @@ -730,19 +881,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's sideboard nominative, female owner - + sideboard hráče %1 his sideboard nominative, male owner - + jeho sideboard %1's sideboard nominative, male owner - + sideboard hráče %1 @@ -754,19 +905,19 @@ This is only saved for moderators and cannot be seen by the banned person. of %1's sideboard genitive, female owner - + sideboardu hráče %1 of his sideboard genitive, male owner - + sideboardu hráče of %1's sideboard genitive, male owner - + sideboardu hráče %1 @@ -778,19 +929,19 @@ This is only saved for moderators and cannot be seen by the banned person. %1's sideboard accusative, female owner - + sideboard hráče %1 his sideboard accusative, male owner - + jeho sideboard %1's sideboard accusative, male owner - + sideboard hráče %1 @@ -798,12 +949,12 @@ This is only saved for moderators and cannot be seen by the banned person. Enable &price tag feature (using data from blacklotusproject.com) - + &Povolit zobrazovaní cen (použijí se data z blacklotusproject.com) General - + Obecné @@ -811,17 +962,17 @@ This is only saved for moderators and cannot be seen by the banned person. Number - + Počet Card - + Karta Price - + Cena @@ -829,22 +980,22 @@ This is only saved for moderators and cannot be seen by the banned person. Load &local deck - + Nahrát &lokální balíček Load d&eck from server - + Nahrát &balíček ze serveru Ready to s&tart - + Připraven ke &hře Load deck - + Nahrát balíček @@ -852,37 +1003,37 @@ This is only saved for moderators and cannot be seen by the banned person. Card name: - + Jméno karty: Card text: - + Text karty: Card type (OR): - + Typ karty (NEBO): Color (OR): - + Barva (NEBO): O&K - + O&K &Cancel - + &Cancel Card search - + Hledat kartu @@ -890,37 +1041,37 @@ This is only saved for moderators and cannot be seen by the banned person. &Host: - + &Hostitel: &Port: - + &Port: Player &name: - + Jméno &hráče: P&assword: - + H&eslo: &OK - + &OK &Cancel - + &Zrušit Connect to server - + Připojit k serveru @@ -928,87 +1079,87 @@ This is only saved for moderators and cannot be seen by the banned person. &Description: - + &Popis: P&layers: - + H&ráči: Game type - + Formát &Password: - + &Heslo: Only &buddies can join - + Jen pro &přátele Only &registered users can join - + Jen pro &registrované Joining restrictions - + Omezení připojení &Spectators allowed - + &Diváci povoleni Spectators &need a password to join - + Diváci &musí znát heslo Spectators can &chat - + Diváci mohou &chatovat Spectators see &everything - + Diváci vidí &všechno Spectators - + Diváci &OK - + &OK &Cancel - + &Zrušit Create game - + Vytvořit hru Error - + Chyba Server error. - + Chyba serveru. @@ -1016,82 +1167,82 @@ This is only saved for moderators and cannot be seen by the banned person. &Name: - + &Jméno: Token - + Token C&olor: - + B&arva: white - + bílá blue - + modrá black - + černá red - + červená green - + zelená multicolor - + multicolor colorless - + bezbarvý &P/T: - + &S/O: &Annotation: - + &Poznámka: &Destroy token when it leaves the table - + &Token se při odchodu z bojiště zničí &OK - + &OK &Cancel - + &Zrušit Create token - + Vytvořit token @@ -1099,32 +1250,32 @@ This is only saved for moderators and cannot be seen by the banned person. &Refresh - + &Obnovit &OK - + &OK &Cancel - + &Zrušit Load deck from clipboard - + Nahrát balíček ze schránky Error - + Chyba Invalid deck list. - + Neplatný formát balíčku. @@ -1132,17 +1283,17 @@ This is only saved for moderators and cannot be seen by the banned person. O&K - + O&K &Cancel - + &Zrušit Load deck - + Nahrát balíček @@ -1152,57 +1303,57 @@ This is only saved for moderators and cannot be seen by the banned person. Error - + Chyba Your card database is invalid. Would you like to go back and set the correct path? - + Cesta k databázi je neplatná. Chcete se vrátit a nastavit správnou? The path to your deck directory is invalid. Would you like to go back and set the correct path? - + Cesta k adresáři s balíčky je neplatná. Chcete se vrátit a nastavit správnou? The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - + Cesta k adresáři s obrázky je neplatná. Chcete se vrátit a nastavit správnou? Settings - + Nastavení General - + Obecné Appearance - + Vzhled User interface - + Uživatelské rozhraní Deck editor - + Editor balíčků Messages - + Zprávy &Close - + &Zavřít @@ -1217,7 +1368,7 @@ This is only saved for moderators and cannot be seen by the banned person. Error - + Chyba @@ -1227,57 +1378,57 @@ This is only saved for moderators and cannot be seen by the banned person. Wrong password. - + Špatné heslo. Spectators are not allowed in this game. - + Do této hry je divákům přístup zakázán. The game is already full. - + Hra je plná. The game does not exist any more. - + Hra již neexistuje. This game is only open to registered users. - + Hra je určena jen pro registrované. This game is only open to its creator's buddies. - + Hra je dostupná jen pro přátele zakládajícícho. You are being ignored by the creator of this game. - + Zakladatel hry vás ignoruje. Join game - + Připojit ke hře Password: - + Heslo: Games - + Hry Show &full games - + Ukázat &plné hry @@ -1287,17 +1438,17 @@ This is only saved for moderators and cannot be seen by the banned person. C&reate - + V&ytvořit &Join - + &Připojit J&oin as spectator - + P&řipojit se jako divák @@ -1305,7 +1456,7 @@ This is only saved for moderators and cannot be seen by the banned person. Esc - + Esc @@ -1313,72 +1464,72 @@ This is only saved for moderators and cannot be seen by the banned person. yes - + ano yes, free for spectators - + diváci povoleni no - + ne buddies only - + jen pro přátele reg. users only - + jen pro registrované not allowed - + nepovolené Room - + Místnost Description - + Popis Creator - + Zakladatel Game type - + Formát Password - + Heslo Restrictions - + Omezení Players - + Hráči Spectators - + Diváci @@ -1387,49 +1538,49 @@ This is only saved for moderators and cannot be seen by the banned person. English - + Česky Choose path - + Vyberte cestu Personal settings - + Osobní nastavení Language: - + Jazyk: Download card pictures on the fly - + Stahovat obrázky karet za běhu Paths - + Cesty Decks directory: - + Adresář s balíčky: Pictures directory: - + Adresář s obrázky: Path to card database: - + Karetní databáze: @@ -1437,12 +1588,12 @@ This is only saved for moderators and cannot be seen by the banned person. There are too many concurrent connections from your address. - + Z vaší adresy jde mnoho současných připojení. Banned by moderator. - + Zabanován moderátorem. @@ -1452,18 +1603,19 @@ This is only saved for moderators and cannot be seen by the banned person. Unknown reason. - + Neznámý důvod. Connection closed - + Připojení uzavřeno The server has terminated your connection. Reason: %1 - + Server přerušil spojení. +Důvod: %1 @@ -1484,78 +1636,78 @@ Reason for shutdown: %1 Number of players - + Počet hráčů Please enter the number of players. - + Vložte počet hráčů. Player %1 - + Hráč %1 About Cockatrice - + O Cockatrice Version %1 - + Verze %1 Authors: - + Autoři: Translators: - + Překlad: Spanish: - + Španělština: Portugese (Portugal): - + Portugalština (Portugalsko): Portugese (Brazil): - + Portugalština (Brazílie): French: - + Francouzština: Japanese: - + Japonština: Russian: - + Ruština: Czech: - + Čeština: Slovak: - + Slovenština: @@ -1565,239 +1717,314 @@ Reason for shutdown: %1 Error - + Chyba Server timeout - + Vypršel časový limit Invalid login data. - + Nesprávné údaje uživatele. There is already an active session using this user name. Please close that session first and re-login. - + S tímto uživatelským jménem jste již připojeni. +Přerušte spojení a znovu se přihlašte. Socket error: %1 - + Chyba socketu: %1 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. - + Snažíte se připojit na zastaralý server. Prosíme, stáhněte si nižší verzi Cockatrice, nebo se připojte k odpovídajícímu serveru. +Lokální verze je %1, verze serveru je %2. Your Cockatrice client is obsolete. Please update your Cockatrice version. Local version is %1, remote version is %2. - + Váš klient je zastaralý. Prosíme, aktualizujte Cockatrice na vyšší verzi. +Lokální verze je %1, verze serveru je %2. Connecting to %1... - + Připojování k %1... Disconnected - + Odpojeno Logged in at %1 - + Přihlášeno k %1 &Connect... - + &Připojit... &Disconnect - + &Odpojit Start &local game... - + Spustit &lokální hru... &Deck editor - + &Editor balíčků &Full screen - + &Celá obrazovka Ctrl+F - + CTRL+F &Settings... - + &Nastavení... &Exit - + &Konec &Cockatrice - + &Cockatrice &About Cockatrice - + &O Cockatrice &Help - + &Nápověda Are you sure? - + Jste si jisti? There are still open games. Are you sure you want to quit? - + Některé hry jsou stále otevřené. Opravdu chcete odejít? MessageLogWidget + + Connecting to %1... + Připojování k %1... + + + Connected. + Připojeno. + + + Disconnected from server. + Odpojeno. + + + Invalid password. + Nesprávné heslo. + + + Protocol version mismatch. Client: %1, Server: %2 + Neodpovídá verze protokolu. Klient: %1, Server: %2 + + + Protocol error. + Chyba protokolu. + + + You have joined game #%1. + Připojili jste se ke hře #%1. + + + %1 has joined the game. + %1 se připojil ke hře. + + + %1 has left the game. + %1 opustil hru. + The game has been closed. - + Hra byla ukončena. %1 is now watching the game. - + %1 nyní sleduje hru. %1 is not watching the game any more. - + %1 přestal sledovat hru. + + + %1 has loaded a local deck. + %1 nahrál lokální balíček. + + + %1 has loaded deck #%2. + %1 nahrál balíček #%2. + + + %1 is ready to start the game. + %1 je připraven ke hře. + + + %1 is not ready to start the game any more. + %1 již není připraven ke hře. + + + %1 has conceded the game. + %1 ukončil hru. The game has started. - + Hra začíná. + + + %1 shuffles his library. + %1 míchá knihovnu. + + + %1 rolls a %2 with a %3-sided die. + %1 hodil kostkou %2 (%3 stěn). + + + %1 draws %n card(s). + + %1 si lízl %n kartu. + %1 si lízl %n karty. + %1 si lízl %n karet. + You have joined game #%1. female - + Připojili jste se ke hře #%1. You have joined game #%1. male - + Připojili jste se ke hře #%1. %1 has joined the game. female - + %1 se připojil ke hře. %1 has joined the game. male - + %1 se připojil ke hře. %1 has left the game. female - + %1 opustil hru. %1 has left the game. male - + %1 opustil hru. %1 has loaded a local deck. female - + %1 nahrál lokální balíček. %1 has loaded a local deck. male - + %1 nahrál lokální balíček. %1 has loaded deck #%2. female - + %1 nahrál balíček #%2. %1 has loaded deck #%2. male - + %1 nahrál balíček #%2. %1 is ready to start the game. female - + %1 je připraven ke hře. %1 is ready to start the game. male - + %1 je připraven ke hře. %1 is not ready to start the game any more. female - + %1 již není připraven ke hře. %1 is not ready to start the game any more. male - + %1 již není připraven ke hře. %1 has conceded the game. female - + %1 ukončil hru. %1 has conceded the game. male - + %1 ukončil hru. @@ -1839,22 +2066,22 @@ Local version is %1, remote version is %2. %1 rolls a %2 with a %3-sided die. female - + %1 hodil kostkou %2 (%3 stěn). %1 rolls a %2 with a %3-sided die. male - + %1 hodil kostkou %2 (%3 stěn). %1 draws %n card(s). female - - - + %1 si lízl %n kartu. + %1 si lízl %n karty. + %1 si lízl %n karet. @@ -1862,15 +2089,15 @@ Local version is %1, remote version is %2. %1 draws %n card(s). male - - - + %1 si lízl %n kartu. + %1 si lízl %n karty. + %1 si lízl %n karet. %1 undoes his last draw. - + %1 vrátil zpět svoje poslední líznutí. @@ -1880,7 +2107,7 @@ Local version is %1, remote version is %2. %1 undoes his last draw (%2). - + %1 vrátil svoje poslední líznutí (%2). @@ -1890,27 +2117,27 @@ Local version is %1, remote version is %2. from table - + z bojiště from graveyard - + ze hřbitova from exile - + z exilnutých karet from hand - + z ruky the bottom card of his library - + spodní kartu knihovny @@ -1920,7 +2147,7 @@ Local version is %1, remote version is %2. from the bottom of his library - + ze spodku knihovny @@ -1930,7 +2157,7 @@ Local version is %1, remote version is %2. the top card of his library - + vrchní kartu knihovny @@ -1940,7 +2167,7 @@ Local version is %1, remote version is %2. from the top of his library - + z vršku knihovny @@ -1950,58 +2177,58 @@ Local version is %1, remote version is %2. from library - + z knihovny from sideboard - + ze sideboardu from the stack - + ze stacku a card - + kartu %1 gives %2 control over %3. - + %1 předává kontrolu hráči %2 karty %3. %1 puts %2 into play tapped%3. - + %1 dává kartu %2 do hry %3 tapnutou. %1 puts %2 into play%3. - + %1 dává kartu %2 %3 do hry. %1 puts %2%3 into graveyard. - + %1 dává kartu %2%3 do hřbitova. %1 exiles %2%3. - + %1 exiluje %2%3. %1 moves %2%3 to hand. - + %1 přesouvá %2%3 do ruky. %1 puts %2%3 into his library. - + %1 dává %2%3 do knihovny. @@ -2011,7 +2238,7 @@ Local version is %1, remote version is %2. %1 puts %2%3 on bottom of his library. - + %1 dává %2%3 na spodek knihovny. @@ -2021,7 +2248,7 @@ Local version is %1, remote version is %2. %1 puts %2%3 on top of his library. - + %1 dává %2%3 na vršek knihovny. @@ -2031,7 +2258,7 @@ Local version is %1, remote version is %2. %1 puts %2%3 into his library at position %4. - + %1 dává %2%3 knihovny na pozici %4. @@ -2041,21 +2268,21 @@ Local version is %1, remote version is %2. %1 moves %2%3 to sideboard. - + %1 přesouvá %2%3 do sideboardu. %1 plays %2%3. - + %1 sesílá %2%3. %1 takes a mulligan to %n. female - - - + %1 mulliganuje do %n. + %1 mulliganuje do %n. + %1 mulliganuje do %n. @@ -2063,70 +2290,99 @@ Local version is %1, remote version is %2. %1 takes a mulligan to %n. male - - - + %1 mulliganuje do %n. + %1 mulliganuje do %n. + %1 mulliganuje do %n. + + + %1 draws her initial hand. + + %1 flips %2 face-down. female - + %1 otáčí %2 lícem dolů. %1 flips %2 face-down. male - + %1 otáčí %2 lícem dolů. %1 flips %2 face-up. female - + %1 otáčí %2 lícem vzhůru. %1 flips %2 face-up. male - + %1 otáčí %2 lícem vzhůru. %1 destroys %2. female - + %1 ničí %2. %1 destroys %2. male - + %1 ničí %2. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 female + %1 připojuje %2 k %3 %4. + + + + %1 attaches %2 to %3's %4. + p1 female, p2 male + %1 připojuje %2 k %3 %4. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 female + %1 připojuje %2 k %3 %4. + + + + %1 attaches %2 to %3's %4. + p1 male, p2 male + %1 připojuje %2 k %3 %4. %1 unattaches %2. female - + %1 odpojuje %2. %1 unattaches %2. male - + %1 odpojuje %2. %1 creates token: %2%3. female - + %1 vykládá token %2%3. %1 creates token: %2%3. male - + %1 vykládá token %2%3. @@ -2192,49 +2448,49 @@ Local version is %1, remote version is %2. %1 points from %2's %3 to %4. p1 female, p2 female, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4. p1 female, p2 female, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4. p1 female, p2 male, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4. p1 female, p2 male, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4. p1 male, p2 female, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4. p1 male, p2 female, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4. p1 male, p2 male, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %4. %1 points from %2's %3 to %4. p1 male, p2 male, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %4. @@ -2300,58 +2556,58 @@ Local version is %1, remote version is %2. %1 points from %2's %3 to %4's %5. p1 female, p2 female, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 points from %2's %3 to %4's %5. p1 female, p2 female, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 points from %2's %3 to %4's %5. p1 female, p2 male, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 points from %2's %3 to %4's %5. p1 female, p2 male, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 points from %2's %3 to %4's %5. p1 male, p2 female, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 points from %2's %3 to %4's %5. p1 male, p2 female, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 points from %2's %3 to %4's %5. p1 male, p2 male, p3 female - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 points from %2's %3 to %4's %5. p1 male, p2 male, p3 male - + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). %1 places %n %2 counter(s) on %3 (now %4). female - - - + %1 pokládá %n %2 žeton na %3 (nyní %4). + %1 pokládá %n %2 žetony na %3 (nyní %4). + %1 pokládá %n %2 žetonů na %3 (nyní %4). @@ -2359,9 +2615,9 @@ Local version is %1, remote version is %2. %1 places %n %2 counter(s) on %3 (now %4). male - - - + %1 pokládá %n %2 žeton na %3 (nyní %4). + %1 pokládá %n %2 žetony na %3 (nyní %4). + %1 pokládá %n %2 žetonů na %3 (nyní %4). @@ -2369,9 +2625,9 @@ Local version is %1, remote version is %2. %1 removes %n %2 counter(s) from %3 (now %4). female - - - + %1 odebírá %n %2 žeton z %3 (nyní %4). + %1 odebírá %n %2 žetony z %3 (nyní %4). + %1 odebírá %n %2 žetonů z %3 (nyní %4). @@ -2379,9 +2635,9 @@ Local version is %1, remote version is %2. %1 removes %n %2 counter(s) from %3 (now %4). male - - - + %1 odebírá %n %2 žeton z %3 (nyní %4). + %1 odebírá %n %2 žetony z %3 (nyní %4). + %1 odebírá %n %2 žetonů z %3 (nyní %4). @@ -2436,338 +2692,441 @@ Local version is %1, remote version is %2. %1 sets counter %2 to %3 (%4%5). female - + %1 nastavuje počet %2 žetonů na %3 (%4%5). %1 sets counter %2 to %3 (%4%5). male - + %1 nastavuje počet %2 žetonů na %3 (%4%5). %1 sets %2 to not untap normally. female - + %1 nastavuje %2 na neodtapování. %1 sets %2 to not untap normally. male - + %1 nastavuje %2 na neodtapování. %1 sets %2 to untap normally. female - + %1 nastavuje %2 na standardní odtapnutí. %1 sets %2 to untap normally. male - + %1 nastavuje %2 na standardní odtapnutí. %1 sets PT of %2 to %3. female - + %1 nastavuje sílu a odolnost pro %2 na %3. %1 sets PT of %2 to %3. male - + %1 nastavuje sílu a odolnost pro %2 na %3. %1 sets annotation of %2 to %3. female - + %1 nastavuje poznámku pro %2 na %3. %1 sets annotation of %2 to %3. male - + %1 nastavuje poznámku pro %2 na %3. %1 is looking at the top %2 cards %3. female - + %1 si prohlíží %2 vrchních karet %3. %1 is looking at the top %2 cards %3. male - + %1 si prohlíží %2 vrchních karet %3. %1 is looking at %2. female - + %1 si prohlíží %2. %1 is looking at %2. male - + %1 si prohlíží %2. %1 stops looking at %2. female - + %1 si přestává prohlížet %2. %1 stops looking at %2. male - + %1 si přestává prohlížet %2. %1 reveals %2 to %3. p1 female, p2 female - + %1 ukazuje %2 hráči %3. %1 reveals %2 to %3. p1 female, p2 male - + %1 ukazuje %2 hráči %3. %1 reveals %2 to %3. p1 male, p2 female - + %1 ukazuje %2 hráči %3. %1 reveals %2 to %3. p1 male, p2 male - + %1 ukazuje %2 hráči %3. %1 reveals %2. female - + %1 ukazuje %2. %1 reveals %2. male - + %1 ukazuje %2. %1 randomly reveals %2%3 to %4. p1 female, p2 female - + %1 náhodně ukazuje %2%3 hráči %4. %1 randomly reveals %2%3 to %4. p1 female, p2 male - + %1 náhodně ukazuje %2%3 hráči %4. %1 randomly reveals %2%3 to %4. p1 male, p2 female - + %1 náhodně ukazuje %2%3 hráči %4. %1 randomly reveals %2%3 to %4. p1 male, p2 male - + %1 náhodně ukazuje %2%3 hráči %4. %1 randomly reveals %2%3. female - + %1 náhodně ukazuje %2%3. %1 randomly reveals %2%3. male - + %1 náhodně ukazuje %2%3. %1 reveals %2%3 to %4. p1 female, p2 female - + %1 ukazuje %2%3 hráči %4. %1 reveals %2%3 to %4. p1 female, p2 male - + %1 ukazuje %2%3 hráči %4. %1 reveals %2%3 to %4. p1 male, p2 female - + %1 ukazuje %2%3 hráči %4. %1 reveals %2%3 to %4. p1 male, p2 male - + %1 ukazuje %2%3 hráči %4. %1 reveals %2%3. female - + %1 ukazuje %2%3. %1 reveals %2%3. male - + %1 ukazuje %2%3. It is now %1's turn. female - + Nyní je kolo hráče %1. It is now %1's turn. male - + Nyní je kolo hráče %1. + + + %1 takes a mulligan to %n. + + %1 mulliganuje do %n. + %1 mulliganuje do %n. + %1 mulliganuje do %n. + %1 draws his initial hand. - + %1 líže startovní ruku. - - %1 draws her initial hand. - + %1 flips %2 face-down. + %1 otáčí %2 lícem dolů. + + + %1 flips %2 face-up. + %1 otáčí %2 lícem vzhůru. + + + %1 destroys %2. + %1 ničí %2. - %1 attaches %2 to %3's %4. - p1 female, p2 female - + %1 připojuje %2 k %3 %4. - - %1 attaches %2 to %3's %4. - p1 female, p2 male - + %1 unattaches %2. + %1 odpojuje %2. - - %1 attaches %2 to %3's %4. - p1 male, p2 female - + %1 creates token: %2%3. + %1 vykládá token %2%3. - - %1 attaches %2 to %3's %4. - p1 male, p2 male - + %1 points from %2's %3 to %4. + %1 ukazuje kartou %3 (hráče %2) na %4. + + + %1 points from %2's %3 to %4's %5. + %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). + + + %1 places %n %2 counter(s) on %3 (now %4). + + %1 pokládá %n %2 žeton na %3 (nyní %4). + %1 pokládá %n %2 žetony na %3 (nyní %4). + %1 pokládá %n %2 žetonů na %3 (nyní %4). + + + + %1 removes %n %2 counter(s) from %3 (now %4). + + %1 odebírá %n %2 žeton z %3 (nyní %4). + %1 odebírá %n %2 žetony z %3 (nyní %4). + %1 odebírá %n %2 žetonů z %3 (nyní %4). + red - - - - + + červený + červené + červených yellow - - - - + + žlutý + žluté + žlutých green - - - - + + zelený + zelené + zelených + + his permanents + permanenty + + + %1 %2 %3. + %1 %2 %3. + + + taps + tapuje + + + untaps + odtapuje + + + %1 sets counter %2 to %3 (%4%5). + %1 nastavuje počet %2 žetonů na %3 (%4%5). + + + %1 sets %2 to not untap normally. + %1 nastavuje %2 na neodtapování. + + + %1 sets %2 to untap normally. + %1 nastavuje %2 na standardní odtapnutí. + + + %1 sets PT of %2 to %3. + %1 nastavuje sílu a odolnost pro %2 na %3. + + + %1 sets annotation of %2 to %3. + %1 nastavuje poznámku pro %2 na %3. + + + %1 is looking at the top %2 cards %3. + %1 si prohlíží %2 vrchních karet %3. + + + %1 is looking at %2. + %1 si prohlíží %2. + + + %1 stops looking at %2. + %1 si přestává prohlížet %2. + + + %1 reveals %2 to %3. + %1 ukazuje %2 hráči %3. + + + %1 reveals %2. + %1 ukazuje %2. + + + %1 randomly reveals %2%3 to %4. + %1 náhodně ukazuje %2%3 hráči %4. + + + %1 randomly reveals %2%3. + %1 náhodně ukazuje %2%3. + + + %1 reveals %2%3 to %4. + %1 ukazuje %2%3 hráči %4. + + + %1 reveals %2%3. + %1 ukazuje %2%3. + + + It is now %1's turn. + Nyní je kolo hráče %1. + untap step - + Odtapovací fáze upkeep step - + Upkeep draw step - + Lízací fáze first main phase - + První hlavní fáze beginning of combat step - + Začátek bojové fáze declare attackers step - + Oznámení útočníků declare blockers step - + Oznámení blokujících combat damage step - + Udělení bojového zranění end of combat step - + Konec bojové fáze second main phase - + Druhá hlavní fáze ending phase - + Konec kola It is now the %1. - + Nyní je %1. @@ -2775,22 +3134,22 @@ Local version is %1, remote version is %2. Add message - + Přidat zprávu Message: - + Zpráva: &Add - + &Přidat &Remove - + &Odstranit @@ -2798,57 +3157,57 @@ Local version is %1, remote version is %2. Untap step - + Odtapovací fáze Upkeep step - + Upkeep Draw step - + Lízací fáze First main phase - + První hlavní fáze Beginning of combat step - + Začátek bojové fáze Declare attackers step - + Oznámení útočníků Declare blockers step - + Oznámení blokujících Combat damage step - + Udělení bojového zranění End of combat step - + Konec bojové fáze Second main phase - + Druhá hlavní fáze End of turn step - + Konec kola @@ -2856,269 +3215,269 @@ Local version is %1, remote version is %2. &View graveyard - + &Zobrazit hřbitov &View exile - + &Zobrazit exilnuté karty Player "%1" - + Hráč "%1" &Graveyard - + &Hřbitov &Exile - + &Exilnuté karty Move to &top of library - + Přesunout na &vršek knihovny Move to &bottom of library - + Přesunout na &spodek knihovny Move to &graveyard - + Přesunout do &hřbitova Move to &exile - + &Exilnout Move to &hand - + Přesunout do &ruky &View library - + &Zobrazit knihovnu View &top cards of library... - + Zobrazit &vrchní karty knihovny... Reveal &library to - + Ukázat &knihovnu Reveal t&op card to - + Ukázat v&rchní kartu &View sideboard - + &Zobrazit sideboard &Draw card - + &Líznout kartu D&raw cards... - + L&íznout karty... &Undo last draw - + &Vrátit zpět poslední líznutí Take &mulligan - + &Mulliganovat &Shuffle - + &Zamíchat Move top cards to &graveyard... - + Přesunout vrchní karty do &hřbitova... Move top cards to &exile... - + &Exilnout vrchní karty... Put top card on &bottom - + Dát kartu na &spodek &Hand - + &Ruka &Reveal to - + &Ukázat Reveal r&andom card to - + Ukázat kartu n&áhodně &Sideboard - + &Sideboard &Library - + &Knihovna &Counters - + &Žetony &Untap all permanents - + &Odtapnout všechny permanenty R&oll die... - + H&odit kostkou... &Create token... - + &Vytvořit token... C&reate another token - + V&ytvořit další token S&ay - + &Chat C&ard - + K&arta &All players - + &Všem hráčům Ctrl+F3 - + Ctrl+F3 F3 - + F3 Ctrl+W - + Ctrl+W F4 - + F4 Ctrl+D - + Ctrl+D Ctrl+E - + Ctrl+E Ctrl+Shift+D - + Ctrl+Shift+D Ctrl+M - + Ctrl+M Ctrl+S - + Ctrl+S Ctrl+U - + Ctrl+U Ctrl+I - + Ctrl+I Ctrl+T - + Ctrl+T Ctrl+G - + Ctrl+G View top cards of library - + Zobrazit vrchní karty knihovny Number of cards: - + Počet karet: Draw cards - + Líznout karty @@ -3126,52 +3485,52 @@ Local version is %1, remote version is %2. Number: - + Počet: Move top cards to grave - + Přesunout vrchní karty do hřbitova Move top cards to exile - + Exilnout vrchní karty Roll die - + Hodit kostkou Number of sides: - + Počet stran: Set power/toughness - + Nastavit sílu/odolnost Please enter the new PT: - + Vložte novou odolnost/sílu: Set annotation - + Nastavit poznámku Please enter the new annotation: - + Vložte novou poznámku: Set counters - + Nastavit žetony @@ -3179,47 +3538,47 @@ Local version is %1, remote version is %2. local deck - + lokální balíček deck #%1 - + bal94ek #%1 User &details - + Detaily &uživatele Direct &chat - + &Chatovat Add to &buddy list - + Přidat mezi &přátele Remove from &buddy list - + Odstranit z &přátel Add to &ignore list - + Přidat do &ignorovaných Remove from &ignore list - + Odstranit z &ignorovaných Kick from &game - + Vyhodit ze &hry @@ -3227,27 +3586,27 @@ Local version is %1, remote version is %2. Maindeck - + Maindeck Sideboard - + Sideboard Cockatrice decks (*.cod) - + Balíčky cockatrice (*.cod) Plain text decks (*.dec *.mwDeck) - + Čistý text (*.dec*.mwDeck) All files (*.*) - + Všechny soubory (*.*) @@ -3255,17 +3614,17 @@ Local version is %1, remote version is %2. Name - + Jméno ID - + ID Upload time - + Průběh nahrávání @@ -3273,32 +3632,32 @@ Local version is %1, remote version is %2. Rooms - + Místnosti Joi&n - + &Připojit Room - + Místnost Description - + Popis Players - + Hráči Games - + Hry @@ -3306,12 +3665,12 @@ Local version is %1, remote version is %2. Short name - + Krátký název Long name - + Dlouhý název @@ -3329,7 +3688,7 @@ Local version is %1, remote version is %2. &OK - + &OK @@ -3347,7 +3706,7 @@ Local version is %1, remote version is %2. Update server &message - + Aktualizovat &zprávu serveru @@ -3357,32 +3716,32 @@ Local version is %1, remote version is %2. Server administration functions - + Administrační funkce serveru &Unlock functions - + &Odemknout funkce &Lock functions - + &Zamknout funkce Unlock administration functions - + Odemknout administrační funkce Do you really want to unlock the administration functions? - + Opravdu chcete odemknout administrační funkce? Administration - + Administrace @@ -3390,66 +3749,67 @@ Local version is %1, remote version is %2. Local file system - + Lokální systém souborů Server deck storage - + Balíčky na serveru Open in deck editor - + Otevřít v editoru balíčků Upload deck - + Nahrát balíček Download deck - + Stáhnout balíček New folder - + Nová složka Delete - + Smazat Enter deck name - + Vložit jméno balíčku This decklist does not have a name. Please enter a name: - + Tentobalíček nemá jméno. +Prosím vložte jméno: Unnamed deck - + Bezejmenný balíček Name of new folder: - + Název nové složky: Deck storage - + Uložiště balíčků @@ -3457,137 +3817,137 @@ Please enter a name: F5 - + F5 F6 - + F6 F7 - + F7 F8 - + F8 F9 - + F9 F10 - + F10 &Phases - + &Fáze &Game - + &Hra Next &phase - + Další &fáze Ctrl+Space - + Ctrl+Space Next &turn - + Další &kolo Ctrl+Return - + Ctrl+Return Ctrl+Enter - + Ctrl+Enter &Remove all local arrows - + &Odstranit všechny lokální šipky Ctrl+R - + CTRL+R &Concede - + &Ukončit hru F2 - + F2 &Leave game - + &Opustit hru Ctrl+Q - + CTRL+Q &Say: - + &Chat: Concede - + Ukončit hru Are you sure you want to concede this game? - + Opravdu chcete ukončit tuto hru? Leave game - + Opustit hru Are you sure you want to leave this game? - + Opravdu chcete opustit tuto hru? Kicked - + Vyhozen You have been kicked out of the game. - + Byli jste vyhozeni ze hry. Game %1: %2 - + Hra %1: %2 @@ -3595,32 +3955,32 @@ Please enter a name: Personal &talk - + Osobní &diskuze &Leave - + &Odejít This user is ignoring you. - + Tento uživatel vás ignoruje. %1 has left the server. - + %1 opustil server. %1 has joined the server. - + %1 se připojil k serveru. Talking to %1 - + Mlávíte k %1 @@ -3628,27 +3988,27 @@ Please enter a name: &Say: - + &Chat: Chat - + Chatovat &Room - + &Místnost &Leave room - + &Opustit místnost You are flooding the chat. Please wait a couple of seconds. - + Píšete příliš intenzivně. Počkejte pár sekund. @@ -3656,7 +4016,7 @@ Please enter a name: Server - + Server @@ -3664,7 +4024,7 @@ Please enter a name: User lists - + Seznam uživatelů @@ -3672,12 +4032,12 @@ Please enter a name: User information - + Informace o uživateli Real name: - + Pravé jméno: @@ -3687,32 +4047,36 @@ Please enter a name: Location: - + Místo: User level: - + Úroveň: Administrator - + Administrátor Moderator + + Judge + Judge + Registered user - + Registrovaný Unregistered user - + Neregistrovaný @@ -3720,37 +4084,37 @@ Please enter a name: General interface settings - + Obecné &Double-click cards to play them (instead of single-click) - + &Pro zahraní karty je třeba dvojklik Animation settings - + Animace &Tap/untap animation - + &Animace tapnutí/odtapnutí Enable &sounds - + Povolit &zvuky Path to sounds directory: - + Adresář se zvuky: Choose path - + Vyberte cestu @@ -3758,22 +4122,22 @@ Please enter a name: Users online: %1 - + Připojených uživatelů: %1 Users in this room: %1 - + Uživatelů v této místnosti: %1 Buddies online: %1 / %2 - + Přátelé online: %1 / %2 Ignored users online: %1 / %2 - + Ignorovaných online: %1 / %2 @@ -3783,12 +4147,12 @@ Please enter a name: User &details - + &Detaily uživatele Direct &chat - + &Chatovat @@ -3798,27 +4162,37 @@ Please enter a name: Add to &buddy list - + Přidat mezi &přátele Remove from &buddy list - + Odstranit z &přátel Add to &ignore list - + Přidat mezi &ignorované Remove from &ignore list - + Odstranit z &ignorovaných Ban from &server - + &Zabanovat + + + Duration + Délka + + + Please enter the duration of the ban (in minutes). +Enter 0 for an indefinite ban. + Vložte dobu trvání banu (v minutách). +Hodnota 0 je pro ban bez omezení. @@ -3826,196 +4200,198 @@ Please enter a name: &Search... - + &Hledat... &Clear search - + &Vyčistit hledání &Search for: - + &Vyhledat: Deck &name: - + &Název balíčku: &Comments: - + &Komentář: &Update prices - + Akt&ualizovat ceny Ctrl+U - + CTRL+U Deck editor [*] - + Editor balíčků [*] &New deck - + &Nový balíček &Load deck... - + &Nahrát balíček... &Save deck - + &Uložit balíček Save deck &as... - + Uložit balíček &jako... Load deck from cl&ipboard... - + Nahrát balíček ze s&chránky... Save deck to clip&board - + Vložit balíček do &schránky &Print deck... - + &Vytisknout balíček... &Close - + &Zavřít Ctrl+Q - + CTRL+Q &Edit sets... - + &Upravit sasy... &Deck - + &Balíček &Card database - + Databáze &karet Add card to &maindeck - + Přidat kartu do &balíčku Return - + Return Enter - + Enter Add card to &sideboard - + Přidat kartu do &sideboardu Ctrl+Return - + Ctrl+Return Ctrl+Enter - + Ctrl+Enter &Remove row - + &Smazat řádek Del - + Del &Increment number - + &Zvýšit počet + - + + &Decrement number - + &Snížit počet - - + - Are you sure? - + Jste si jisti? The decklist has been modified. Do you want to save the changes? - + Balíček byl upraven. +Chcete uložit změny? Load deck - + Nahrát balíček Error - + Chyba The deck could not be saved. Please check that the directory is writable and try again. - + Balíček nebylo možné uložit. +Zkontrolujte, jestli lze zapisovat do cílového adresáře a zkuste to znovu. Save deck - + Uložit balíček @@ -4023,7 +4399,7 @@ Please check that the directory is writable and try again. Edit sets - + Upravit edice @@ -4031,17 +4407,17 @@ Please check that the directory is writable and try again. sort by name - + seřadit dle jména sort by type - + seřadit dle typu shuffle when closing - + zamíchat po zavření From dd4948576c9f9cd11635f0c904f2e0e19cfeaec1 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sun, 10 Jul 2011 14:40:48 +0200 Subject: [PATCH 87/87] temp: removed cockatrice_cs.ts --- cockatrice/translations/cockatrice_cs.ts | 3169 ---------------------- 1 file changed, 3169 deletions(-) delete mode 100644 cockatrice/translations/cockatrice_cs.ts diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts deleted file mode 100644 index b43c9b208..000000000 --- a/cockatrice/translations/cockatrice_cs.ts +++ /dev/null @@ -1,3169 +0,0 @@ - - - - - AbstractCounter - - - &Set counter... - &Nastavit žeton... - - - - Ctrl+L - Ctrl+L - - - - F11 - F11 - - - - F12 - F12 - - - - Set counter - Nastavit žeton - - - - New value for counter '%1': - Nová hodnota pro žeton '%1': - - - - AppearanceSettingsPage - - - Zone background pictures - Pozadí zón - - - - Path to hand background: - Cesta k pozadí ruky: - - - - Path to stack background: - Cesta k pozadí stacku: - - - - Path to table background: - Cesta k pozadí stolu: - - - - Path to player info background: - Cesta k pozadí informací o uživateli: - - - - Path to picture of card back: - Cesta k rubu karet: - - - - Card rendering - Vykreslování karet - - - - Display card names on cards having a picture - Zobrazit jména karet na kartách s obrázky - - - - Hand layout - Rozvržení ruky - - - - Display hand horizontally (wastes space) - Zobrazit ruku horizontálně (zabírá více místa) - - - - Table grid layout - Rozložení herní mřížky - - - - Invert vertical coordinate - Převrátit vertikální souřadnice - - - - Zone view layout - Rozvržení zón - - - - Sort by name - Seřadit dle jména - - - - Sort by type - Seřadit dle typu - - - - - - - - Choose path - Vyberte cestu - - - - CardDatabaseModel - - - Name - Jméno - - - - Sets - Sady - - - - Mana cost - Sesílací cena - - - - Card type - Typ karty - - - - P/T - S/O - - - - CardInfoWidget - - - Hide card info - Skrýt informace o kartě - - - - Show card only - Zobrazit pouze kartu - - - - Show text only - Zobrazit pouze text - - - - Show full info - Zobrazit všechny informace - - - - Name: - Jméno: - - - - Mana cost: - Sesílací cena: - - - - Card type: - Typ karty: - - - - P / T: - S / O: - - - - CardItem - - - &Play - &Zahrát - - - - &Hide - &Skrýt - - - - &Tap - &Tapnout - - - - &Untap - &Odtapnout - - - - Toggle &normal untapping - Přepnout &normální odtapnutí - - - - &Flip - &Otočit - - - - &Clone - &Zdvojit - - - - Ctrl+H - Ctrl+H - - - - &Attach to card... - Připojit ke k&artě... - - - - Ctrl+A - Ctrl+A - - - - Unattac&h - Od&pojit - - - - &Power / toughness - &Síla / odolnost - - - - &Increase power - &Zvýšit sílu - - - - Ctrl++ - Ctrl++ - - - - &Decrease power - &Snížit sílu - - - - Ctrl+- - Ctrl+- - - - - I&ncrease toughness - &Zvýšit odolnost - - - - Alt++ - Alt++ - - - - D&ecrease toughness - &Snížit sílu - - - - Alt+- - Alt+- - - - - In&crease power and toughness - &Zvýšit sílu a odolnost - - - - Ctrl+Alt++ - Ctrl+Alt++ - - - - Dec&rease power and toughness - &Snížit sílu a odolnost - - - - Ctrl+Alt+- - Ctrl+Alt+- - - - - Set &power and toughness... - Nastavit &sílu a odolnost... - - - - Ctrl+P - Ctrl+P - - - - &Set annotation... - Na&stavit poznámku... - - - - red - červená - - - - yellow - žlutá - - - - green - zelená - - - - &Add counter (%1) - Přid&at žeton (%1) - - - - &Remove counter (%1) - Odst&ranit žeton (%1) - - - - &Set counters (%1)... - Na&stavit žetony (%1)... - - - - &top of library - &vršek knihovny - - - - &bottom of library - &spodek knihovny - - - - &graveyard - &hřbitov - - - - Ctrl+Del - Ctrl+Del - - - - &exile - &exilnout - - - - &Move to - &Přesunout - - - - CardZone - - - his hand - nominative - jeho ruka - - - - %1's hand - nominative - ruka hráče %1 - - - - of his hand - genitive - jeho ruky - - - - of %1's hand - genitive - ruky hráče %1 - - - - his hand - accusative - jeho ruka - - - - %1's hand - accusative - ruka hráče %1 - - - - his library - nominative - knihovna - - - - %1's library - nominative - knihovna hráče %1 - - - - of his library - genitive - jeho knihovny - - - - of %1's library - genitive - knihovny hráče %1 - - - - his library - accusative - knihovnu - - - - %1's library - accusative - knihovna hráče %1 - - - - his graveyard - nominative - jeho hřbitov - - - - %1's graveyard - nominative - hřbitov hráče %1 - - - - of his graveyard - genitive - jeho hřbitova - - - - of %1's graveyard - genitive - hřbitova hráče %1 - - - - his graveyard - accusative - jeho hřbitov - - - - %1's graveyard - accusative - hřbitov hráče %1 - - - - his exile - nominative - jeho exilnuté karty - - - - %1's exile - nominative - exilnuté karty hráče %1 - - - - of his exile - genitive - exilnutých karet - - - - of %1's exile - genitive - exilnutých karet hráče %1 - - - - his exile - accusative - jeho exilnuté karty - - - - %1's exile - accusative - exilnuté karty hráče %1 - - - - his sideboard - nominative - jeho sideboard - - - - %1's sideboard - nominative - sideboard hráče %1 - - - - of his sideboard - genitive - sideboardu hráče - - - - of %1's sideboard - genitive - sideboardu hráče %1 - - - - his sideboard - accusative - jeho sideboard - - - - %1's sideboard - accusative - sideboard hráče %1 - - - - DeckEditorSettingsPage - - - Enable &price tag feature (using data from blacklotusproject.com) - &Povolit zobrazovaní cen (použijí se data z blacklotusproject.com) - - - - General - Obecné - - - - DeckListModel - - - Number - Počet - - - - Card - Karta - - - - Price - Cena - - - - DeckViewContainer - - - Load &local deck - Nahrát &lokální balíček - - - - Load d&eck from server - Nahrát &balíček ze serveru - - - - Ready to s&tart - Připraven ke &hře - - - - Load deck - Nahrát balíček - - - - DlgCardSearch - - - Card name: - Jméno karty: - - - - Card text: - Text karty: - - - - Card type (OR): - Typ karty (NEBO): - - - - Color (OR): - Barva (NEBO): - - - - O&K - O&K - - - - &Cancel - &Cancel - - - - Card search - Hledat kartu - - - - DlgConnect - - - &Host: - &Hostitel: - - - - &Port: - &Port: - - - - Player &name: - Jméno &hráče: - - - - P&assword: - H&eslo: - - - - &OK - &OK - - - - &Cancel - &Zrušit - - - - Connect to server - Připojit k serveru - - - - DlgCreateGame - - - &Description: - &Popis: - - - - P&layers: - H&ráči: - - - - Game type - Formát - - - - &Password: - &Heslo: - - - - Only &buddies can join - Jen pro &přátele - - - - Only &registered users can join - Jen pro &registrované - - - - Joining restrictions - Omezení připojení - - - - &Spectators allowed - &Diváci povoleni - - - - Spectators &need a password to join - Diváci &musí znát heslo - - - - Spectators can &chat - Diváci mohou &chatovat - - - - Spectators see &everything - Diváci vidí &všechno - - - - Spectators - Diváci - - - - &OK - &OK - - - - &Cancel - &Zrušit - - - - Create game - Vytvořit hru - - - - Error - Chyba - - - - Server error. - Chyba serveru. - - - - DlgCreateToken - - - &Name: - &Jméno: - - - - Token - Token - - - - C&olor: - B&arva: - - - - white - bílá - - - - blue - modrá - - - - black - černá - - - - red - červená - - - - green - zelená - - - - multicolor - multicolor - - - - colorless - bezbarvý - - - - &P/T: - &S/O: - - - - &Annotation: - &Poznámka: - - - - &Destroy token when it leaves the table - &Token se při odchodu z bojiště zničí - - - - &OK - &OK - - - - &Cancel - &Zrušit - - - - Create token - Vytvořit token - - - - DlgLoadDeckFromClipboard - - - &Refresh - &Obnovit - - - - &OK - &OK - - - - &Cancel - &Zrušit - - - - Load deck from clipboard - Nahrát balíček ze schránky - - - - Error - Chyba - - - - Invalid deck list. - Neplatný formát balíčku. - - - - DlgLoadRemoteDeck - - - O&K - O&K - - - - &Cancel - &Zrušit - - - - Load deck - Nahrát balíček - - - - DlgSettings - - - - - Error - Chyba - - - - Your card database is invalid. Would you like to go back and set the correct path? - Cesta k databázi je neplatná. Chcete se vrátit a nastavit správnou? - - - - The path to your deck directory is invalid. Would you like to go back and set the correct path? - Cesta k adresáři s balíčky je neplatná. Chcete se vrátit a nastavit správnou? - - - - The path to your card pictures directory is invalid. Would you like to go back and set the correct path? - Cesta k adresáři s obrázky je neplatná. Chcete se vrátit a nastavit správnou? - - - - Settings - Nastavení - - - - General - Obecné - - - - Appearance - Vzhled - - - - User interface - Uživatelské rozhraní - - - - Deck editor - Editor balíčků - - - - Messages - Zprávy - - - - &Close - &Zavřít - - - - GameSelector - - - - - - - - - Error - Chyba - - - - Wrong password. - Špatné heslo. - - - - Spectators are not allowed in this game. - Do této hry je divákům přístup zakázán. - - - - The game is already full. - Hra je plná. - - - - The game does not exist any more. - Hra již neexistuje. - - - - This game is only open to registered users. - Hra je určena jen pro registrované. - - - - This game is only open to its creator's buddies. - Hra je dostupná jen pro přátele zakládajícícho. - - - - You are being ignored by the creator of this game. - Zakladatel hry vás ignoruje. - - - - Join game - Připojit ke hře - - - - Password: - Heslo: - - - - Games - Hry - - - - Show &full games - Ukázat &plné hry - - - - C&reate - V&ytvořit - - - - &Join - &Připojit - - - - J&oin as spectator - P&řipojit se jako divák - - - - GameView - - - Esc - Esc - - - - GamesModel - - - yes - ano - - - - yes, free for spectators - diváci povoleni - - - - no - ne - - - - buddies only - jen pro přátele - - - - reg. users only - jen pro registrované - - - - not allowed - nepovolené - - - - Description - Popis - - - - Creator - Zakladatel - - - - Game type - Formát - - - - Password - Heslo - - - - Restrictions - Omezení - - - - Players - Hráči - - - - Spectators - Diváci - - - - GeneralSettingsPage - - - - English - Česky - - - - - - Choose path - Vyberte cestu - - - - Personal settings - Osobní nastavení - - - - Language: - Jazyk: - - - - Download card pictures on the fly - Stahovat obrázky karet za běhu - - - - Paths - Cesty - - - - Decks directory: - Adresář s balíčky: - - - - Pictures directory: - Adresář s obrázky: - - - - Path to card database: - Karetní databáze: - - - - MainWindow - - - There are too many concurrent connections from your address. - Z vaší adresy jde mnoho současných připojení. - - - - Banned by moderator. - Zabanován moderátorem. - - - - Unknown reason. - Neznámý důvod. - - - - Connection closed - Připojení uzavřeno - - - - The server has terminated your connection. -Reason: %1 - Server přerušil spojení. -Důvod: %1 - - - - Number of players - Počet hráčů - - - - Please enter the number of players. - Vložte počet hráčů. - - - - - Player %1 - Hráč %1 - - - - About Cockatrice - O Cockatrice - - - - Version %1 - Verze %1 - - - - Authors: - Autoři: - - - - Translators: - Překlad: - - - - Spanish: - Španělština: - - - - Portugese (Portugal): - Portugalština (Portugalsko): - - - - Portugese (Brazil): - Portugalština (Brazílie): - - - - French: - Francouzština: - - - - Japanese: - Japonština: - - - - Russian: - Ruština: - - - - Czech: - Čeština: - - - - Slovak: - Slovenština: - - - - - - - - - Error - Chyba - - - - Server timeout - Vypršel časový limit - - - - Invalid login data. - Nesprávné údaje uživatele. - - - - There is already an active session using this user name. -Please close that session first and re-login. - S tímto uživatelským jménem jste již připojeni. -Přerušte spojení a znovu se přihlašte. - - - - Socket error: %1 - Chyba socketu: %1 - - - - 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. - Snažíte se připojit na zastaralý server. Prosíme, stáhněte si nižší verzi Cockatrice, nebo se připojte k odpovídajícímu serveru. -Lokální verze je %1, verze serveru je %2. - - - - Your Cockatrice client is obsolete. Please update your Cockatrice version. -Local version is %1, remote version is %2. - Váš klient je zastaralý. Prosíme, aktualizujte Cockatrice na vyšší verzi. -Lokální verze je %1, verze serveru je %2. - - - - Connecting to %1... - Připojování k %1... - - - - Disconnected - Odpojeno - - - - Logged in at %1 - Přihlášeno k %1 - - - - &Connect... - &Připojit... - - - - &Disconnect - &Odpojit - - - - Start &local game... - Spustit &lokální hru... - - - - &Deck editor - &Editor balíčků - - - - &Full screen - &Celá obrazovka - - - - Ctrl+F - CTRL+F - - - - &Settings... - &Nastavení... - - - - &Exit - &Konec - - - - &Cockatrice - &Cockatrice - - - - &About Cockatrice - &O Cockatrice - - - - &Help - &Nápověda - - - - Are you sure? - Jste si jisti? - - - - There are still open games. Are you sure you want to quit? - Některé hry jsou stále otevřené. Opravdu chcete odejít? - - - - MessageLogWidget - - - Connecting to %1... - Připojování k %1... - - - - Connected. - Připojeno. - - - - Disconnected from server. - Odpojeno. - - - - Invalid password. - Nesprávné heslo. - - - - Protocol version mismatch. Client: %1, Server: %2 - Neodpovídá verze protokolu. Klient: %1, Server: %2 - - - - Protocol error. - Chyba protokolu. - - - - You have joined game #%1. - Připojili jste se ke hře #%1. - - - - %1 has joined the game. - %1 se připojil ke hře. - - - - %1 has left the game. - %1 opustil hru. - - - - The game has been closed. - Hra byla ukončena. - - - - %1 is now watching the game. - %1 nyní sleduje hru. - - - - %1 is not watching the game any more. - %1 přestal sledovat hru. - - - - %1 has loaded a local deck. - %1 nahrál lokální balíček. - - - - %1 has loaded deck #%2. - %1 nahrál balíček #%2. - - - - %1 is ready to start the game. - %1 je připraven ke hře. - - - - %1 is not ready to start the game any more. - %1 již není připraven ke hře. - - - - %1 has conceded the game. - %1 ukončil hru. - - - - The game has started. - Hra začíná. - - - - %1 shuffles his library. - %1 míchá knihovnu. - - - - %1 rolls a %2 with a %3-sided die. - %1 hodil kostkou %2 (%3 stěn). - - - - %1 draws %n card(s). - - %1 si lízl %n kartu. - %1 si lízl %n karty. - %1 si lízl %n karet. - - - - - %1 undoes his last draw. - %1 vrátil zpět svoje poslední líznutí. - - - - %1 undoes his last draw (%2). - %1 vrátil svoje poslední líznutí (%2). - - - - from table - z bojiště - - - - from graveyard - ze hřbitova - - - - from exile - z exilnutých karet - - - - from hand - z ruky - - - - the bottom card of his library - spodní kartu knihovny - - - - from the bottom of his library - ze spodku knihovny - - - - the top card of his library - vrchní kartu knihovny - - - - from the top of his library - z vršku knihovny - - - - from library - z knihovny - - - - from sideboard - ze sideboardu - - - - from the stack - ze stacku - - - - - a card - kartu - - - - %1 gives %2 control over %3. - %1 předává kontrolu hráči %2 karty %3. - - - - %1 puts %2 into play tapped%3. - %1 dává kartu %2 do hry %3 tapnutou. - - - - %1 puts %2 into play%3. - %1 dává kartu %2 %3 do hry. - - - - %1 puts %2%3 into graveyard. - %1 dává kartu %2%3 do hřbitova. - - - - %1 exiles %2%3. - %1 exiluje %2%3. - - - - %1 moves %2%3 to hand. - %1 přesouvá %2%3 do ruky. - - - - %1 puts %2%3 into his library. - %1 dává %2%3 do knihovny. - - - - %1 puts %2%3 on bottom of his library. - %1 dává %2%3 na spodek knihovny. - - - - %1 puts %2%3 on top of his library. - %1 dává %2%3 na vršek knihovny. - - - - %1 puts %2%3 into his library at position %4. - %1 dává %2%3 knihovny na pozici %4. - - - - %1 moves %2%3 to sideboard. - %1 přesouvá %2%3 do sideboardu. - - - - %1 plays %2%3. - %1 sesílá %2%3. - - - - %1 takes a mulligan to %n. - - %1 mulliganuje do %n. - %1 mulliganuje do %n. - %1 mulliganuje do %n. - - - - - %1 draws his initial hand. - %1 líže startovní ruku. - - - - %1 flips %2 face-down. - %1 otáčí %2 lícem dolů. - - - - %1 flips %2 face-up. - %1 otáčí %2 lícem vzhůru. - - - - %1 destroys %2. - %1 ničí %2. - - - - %1 attaches %2 to %3's %4. - %1 připojuje %2 k %3 %4. - - - - %1 unattaches %2. - %1 odpojuje %2. - - - - %1 creates token: %2%3. - %1 vykládá token %2%3. - - - - %1 points from %2's %3 to %4. - %1 ukazuje kartou %3 (hráče %2) na %4. - - - - %1 points from %2's %3 to %4's %5. - %1 ukazuje kartou %3 (hráče %2) na %5 (hráče %4). - - - - %1 places %n %2 counter(s) on %3 (now %4). - - %1 pokládá %n %2 žeton na %3 (nyní %4). - %1 pokládá %n %2 žetony na %3 (nyní %4). - %1 pokládá %n %2 žetonů na %3 (nyní %4). - - - - - %1 removes %n %2 counter(s) from %3 (now %4). - - %1 odebírá %n %2 žeton z %3 (nyní %4). - %1 odebírá %n %2 žetony z %3 (nyní %4). - %1 odebírá %n %2 žetonů z %3 (nyní %4). - - - - - red - - červený - červené - červených - - - - - yellow - - žlutý - žluté - žlutých - - - - - green - - zelený - zelené - zelených - - - - - his permanents - permanenty - - - - %1 %2 %3. - %1 %2 %3. - - - - taps - tapuje - - - - untaps - odtapuje - - - - %1 sets counter %2 to %3 (%4%5). - %1 nastavuje počet %2 žetonů na %3 (%4%5). - - - - %1 sets %2 to not untap normally. - %1 nastavuje %2 na neodtapování. - - - - %1 sets %2 to untap normally. - %1 nastavuje %2 na standardní odtapnutí. - - - - %1 sets PT of %2 to %3. - %1 nastavuje sílu a odolnost pro %2 na %3. - - - - %1 sets annotation of %2 to %3. - %1 nastavuje poznámku pro %2 na %3. - - - - %1 is looking at the top %2 cards %3. - %1 si prohlíží %2 vrchních karet %3. - - - - %1 is looking at %2. - %1 si prohlíží %2. - - - - %1 stops looking at %2. - %1 si přestává prohlížet %2. - - - - %1 reveals %2 to %3. - %1 ukazuje %2 hráči %3. - - - - %1 reveals %2. - %1 ukazuje %2. - - - - %1 randomly reveals %2%3 to %4. - %1 náhodně ukazuje %2%3 hráči %4. - - - - %1 randomly reveals %2%3. - %1 náhodně ukazuje %2%3. - - - - %1 reveals %2%3 to %4. - %1 ukazuje %2%3 hráči %4. - - - - %1 reveals %2%3. - %1 ukazuje %2%3. - - - - It is now %1's turn. - Nyní je kolo hráče %1. - - - - untap step - Odtapovací fáze - - - - upkeep step - Upkeep - - - - draw step - Lízací fáze - - - - first main phase - První hlavní fáze - - - - beginning of combat step - Začátek bojové fáze - - - - declare attackers step - Oznámení útočníků - - - - declare blockers step - Oznámení blokujících - - - - combat damage step - Udělení bojového zranění - - - - end of combat step - Konec bojové fáze - - - - second main phase - Druhá hlavní fáze - - - - ending phase - Konec kola - - - - It is now the %1. - Nyní je %1. - - - - MessagesSettingsPage - - - Add message - Přidat zprávu - - - - Message: - Zpráva: - - - - &Add - &Přidat - - - - &Remove - &Odstranit - - - - PhasesToolbar - - - Untap step - Odtapovací fáze - - - - Upkeep step - Upkeep - - - - Draw step - Lízací fáze - - - - First main phase - První hlavní fáze - - - - Beginning of combat step - Začátek bojové fáze - - - - Declare attackers step - Oznámení útočníků - - - - Declare blockers step - Oznámení blokujících - - - - Combat damage step - Udělení bojového zranění - - - - End of combat step - Konec bojové fáze - - - - Second main phase - Druhá hlavní fáze - - - - End of turn step - Konec kola - - - - Player - - - &View graveyard - &Zobrazit hřbitov - - - - &View exile - &Zobrazit exilnuté karty - - - - Player "%1" - Hráč "%1" - - - - &Graveyard - &Hřbitov - - - - &Exile - &Exilnuté karty - - - - - - Move to &top of library - Přesunout na &vršek knihovny - - - - - - Move to &bottom of library - Přesunout na &spodek knihovny - - - - - Move to &graveyard - Přesunout do &hřbitova - - - - - Move to &exile - &Exilnout - - - - - Move to &hand - Přesunout do &ruky - - - - &View library - &Zobrazit knihovnu - - - - View &top cards of library... - Zobrazit &vrchní karty knihovny... - - - - Reveal &library to - Ukázat &knihovnu - - - - Reveal t&op card to - Ukázat v&rchní kartu - - - - &View sideboard - &Zobrazit sideboard - - - - &Draw card - &Líznout kartu - - - - D&raw cards... - L&íznout karty... - - - - &Undo last draw - &Vrátit zpět poslední líznutí - - - - Take &mulligan - &Mulliganovat - - - - &Shuffle - &Zamíchat - - - - Move top cards to &graveyard... - Přesunout vrchní karty do &hřbitova... - - - - Move top cards to &exile... - &Exilnout vrchní karty... - - - - Put top card on &bottom - Dát kartu na &spodek - - - - &Hand - &Ruka - - - - &Reveal to - &Ukázat - - - - Reveal r&andom card to - Ukázat kartu n&áhodně - - - - &Sideboard - &Sideboard - - - - &Library - &Knihovna - - - - &Counters - &Žetony - - - - &Untap all permanents - &Odtapnout všechny permanenty - - - - R&oll die... - H&odit kostkou... - - - - &Create token... - &Vytvořit token... - - - - C&reate another token - V&ytvořit další token - - - - S&ay - &Chat - - - - C&ard - K&arta - - - - &All players - &Všem hráčům - - - - Ctrl+F3 - Ctrl+F3 - - - - F3 - F3 - - - - Ctrl+W - Ctrl+W - - - - F4 - F4 - - - - Ctrl+D - Ctrl+D - - - - Ctrl+E - Ctrl+E - - - - Ctrl+Shift+D - Ctrl+Shift+D - - - - Ctrl+M - Ctrl+M - - - - Ctrl+S - Ctrl+S - - - - Ctrl+U - Ctrl+U - - - - Ctrl+I - Ctrl+I - - - - Ctrl+T - Ctrl+T - - - - Ctrl+G - Ctrl+G - - - - View top cards of library - Zobrazit vrchní karty knihovny - - - - Number of cards: - Počet karet: - - - - Draw cards - Líznout karty - - - - - - - Number: - Počet: - - - - Move top cards to grave - Přesunout vrchní karty do hřbitova - - - - Move top cards to exile - Exilnout vrchní karty - - - - Roll die - Hodit kostkou - - - - Number of sides: - Počet stran: - - - - Set power/toughness - Nastavit sílu/odolnost - - - - Please enter the new PT: - Vložte novou odolnost/sílu: - - - - Set annotation - Nastavit poznámku - - - - Please enter the new annotation: - Vložte novou poznámku: - - - - Set counters - Nastavit žetony - - - - PlayerListWidget - - - local deck - lokální balíček - - - - deck #%1 - bal94ek #%1 - - - - User &details - Detaily &uživatele - - - - Direct &chat - &Chatovat - - - - Add to &buddy list - Přidat mezi &přátele - - - - Remove from &buddy list - Odstranit z &přátel - - - - Add to &ignore list - Přidat do &ignorovaných - - - - Remove from &ignore list - Odstranit z &ignorovaných - - - - Kick from &game - Vyhodit ze &hry - - - - QObject - - - Maindeck - Maindeck - - - - Sideboard - Sideboard - - - - Cockatrice decks (*.cod) - Balíčky cockatrice (*.cod) - - - - Plain text decks (*.dec *.mwDeck) - Čistý text (*.dec*.mwDeck) - - - - All files (*.*) - Všechny soubory (*.*) - - - - RemoteDeckList_TreeModel - - - Name - Jméno - - - - ID - ID - - - - Upload time - Průběh nahrávání - - - - RoomSelector - - - Rooms - Místnosti - - - - Joi&n - &Připojit - - - - Room - Místnost - - - - Description - Popis - - - - Players - Hráči - - - - Games - Hry - - - - SetsModel - - - Short name - Krátký název - - - - Long name - Dlouhý název - - - - TabAdmin - - - Update server &message - Aktualizovat &zprávu serveru - - - - Server administration functions - Administrační funkce serveru - - - - &Unlock functions - &Odemknout funkce - - - - &Lock functions - &Zamknout funkce - - - - Unlock administration functions - Odemknout administrační funkce - - - - Do you really want to unlock the administration functions? - Opravdu chcete odemknout administrační funkce? - - - - Administration - Administrace - - - - TabDeckStorage - - - Local file system - Lokální systém souborů - - - - Server deck storage - Balíčky na serveru - - - - - Open in deck editor - Otevřít v editoru balíčků - - - - Upload deck - Nahrát balíček - - - - Download deck - Stáhnout balíček - - - - - New folder - Nová složka - - - - Delete - Smazat - - - - Enter deck name - Vložit jméno balíčku - - - - This decklist does not have a name. -Please enter a name: - Tentobalíček nemá jméno. -Prosím vložte jméno: - - - - - Unnamed deck - Bezejmenný balíček - - - - Name of new folder: - Název nové složky: - - - - Deck storage - Uložiště balíčků - - - - TabGame - - - F5 - F5 - - - - F6 - F6 - - - - F7 - F7 - - - - F8 - F8 - - - - F9 - F9 - - - - F10 - F10 - - - - &Phases - &Fáze - - - - &Game - &Hra - - - - Next &phase - Další &fáze - - - - Ctrl+Space - Ctrl+Space - - - - Next &turn - Další &kolo - - - - Ctrl+Return - Ctrl+Return - - - - Ctrl+Enter - Ctrl+Enter - - - - &Remove all local arrows - &Odstranit všechny lokální šipky - - - - Ctrl+R - CTRL+R - - - - &Concede - &Ukončit hru - - - - F2 - F2 - - - - &Leave game - &Opustit hru - - - - Ctrl+Q - CTRL+Q - - - - &Say: - &Chat: - - - - Concede - Ukončit hru - - - - Are you sure you want to concede this game? - Opravdu chcete ukončit tuto hru? - - - - Leave game - Opustit hru - - - - Are you sure you want to leave this game? - Opravdu chcete opustit tuto hru? - - - - Kicked - Vyhozen - - - - You have been kicked out of the game. - Byli jste vyhozeni ze hry. - - - - Game %1: %2 - Hra %1: %2 - - - - TabMessage - - - Personal &talk - Osobní &diskuze - - - - &Leave - &Odejít - - - - This user is ignoring you. - Tento uživatel vás ignoruje. - - - - %1 has left the server. - %1 opustil server. - - - - %1 has joined the server. - %1 se připojil k serveru. - - - - Talking to %1 - Mlávíte k %1 - - - - TabRoom - - - &Say: - &Chat: - - - - Chat - Chatovat - - - - &Room - &Místnost - - - - &Leave room - &Opustit místnost - - - - You are flooding the chat. Please wait a couple of seconds. - Píšete příliš intenzivně. Počkejte pár sekund. - - - - TabServer - - - Server - Server - - - - TabUserLists - - - User lists - Seznam uživatelů - - - - UserInfoBox - - - User information - Informace o uživateli - - - - Real name: - Pravé jméno: - - - - Location: - Místo: - - - - User level: - Úroveň: - - - - Administrator - Administrátor - - - - Judge - Judge - - - - Registered user - Registrovaný - - - - Unregistered user - Neregistrovaný - - - - UserInterfaceSettingsPage - - - General interface settings - Obecné - - - - &Double-click cards to play them (instead of single-click) - &Pro zahraní karty je třeba dvojklik - - - - Animation settings - Animace - - - - &Tap/untap animation - &Animace tapnutí/odtapnutí - - - - Enable &sounds - Povolit &zvuky - - - - Path to sounds directory: - Adresář se zvuky: - - - - Choose path - Vyberte cestu - - - - UserList - - - Users online: %1 - Připojených uživatelů: %1 - - - - Users in this room: %1 - Uživatelů v této místnosti: %1 - - - - Buddies online: %1 / %2 - Přátelé online: %1 / %2 - - - - Ignored users online: %1 / %2 - Ignorovaných online: %1 / %2 - - - - User &details - &Detaily uživatele - - - - Direct &chat - &Chatovat - - - - Add to &buddy list - Přidat mezi &přátele - - - - Remove from &buddy list - Odstranit z &přátel - - - - Add to &ignore list - Přidat mezi &ignorované - - - - Remove from &ignore list - Odstranit z &ignorovaných - - - - Ban from &server - &Zabanovat - - - - Duration - Délka - - - - Please enter the duration of the ban (in minutes). -Enter 0 for an indefinite ban. - Vložte dobu trvání banu (v minutách). -Hodnota 0 je pro ban bez omezení. - - - - WndDeckEditor - - - &Search... - &Hledat... - - - - &Clear search - &Vyčistit hledání - - - - &Search for: - &Vyhledat: - - - - Deck &name: - &Název balíčku: - - - - &Comments: - &Komentář: - - - - &Update prices - Akt&ualizovat ceny - - - - Ctrl+U - CTRL+U - - - - Deck editor [*] - Editor balíčků [*] - - - - &New deck - &Nový balíček - - - - &Load deck... - &Nahrát balíček... - - - - &Save deck - &Uložit balíček - - - - Save deck &as... - Uložit balíček &jako... - - - - Load deck from cl&ipboard... - Nahrát balíček ze s&chránky... - - - - Save deck to clip&board - Vložit balíček do &schránky - - - - &Print deck... - &Vytisknout balíček... - - - - &Close - &Zavřít - - - - Ctrl+Q - CTRL+Q - - - - &Edit sets... - &Upravit sasy... - - - - &Deck - &Balíček - - - - &Card database - Databáze &karet - - - - Add card to &maindeck - Přidat kartu do &balíčku - - - - Return - Return - - - - Enter - Enter - - - - Add card to &sideboard - Přidat kartu do &sideboardu - - - - Ctrl+Return - Ctrl+Return - - - - Ctrl+Enter - Ctrl+Enter - - - - &Remove row - &Smazat řádek - - - - Del - Del - - - - &Increment number - &Zvýšit počet - - - - + - + - - - - &Decrement number - &Snížit počet - - - - - - - - - - - Are you sure? - Jste si jisti? - - - - The decklist has been modified. -Do you want to save the changes? - Balíček byl upraven. -Chcete uložit změny? - - - - Load deck - Nahrát balíček - - - - - Error - Chyba - - - - - The deck could not be saved. -Please check that the directory is writable and try again. - Balíček nebylo možné uložit. -Zkontrolujte, jestli lze zapisovat do cílového adresáře a zkuste to znovu. - - - - Save deck - Uložit balíček - - - - WndSets - - - Edit sets - Upravit edice - - - - ZoneViewWidget - - - sort by name - seřadit dle jména - - - - sort by type - seřadit dle typu - - - - shuffle when closing - zamíchat po zavření - - -