From eef4a621b330e4c331649b103f0a38d680857301 Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Sun, 9 Nov 2014 12:04:09 +0100 Subject: [PATCH 01/36] Updated Search Bar Style Please note that I don't feel that the search bar needs to be skinned by users, hence why it is not part of the large css-skinning project. I also feel that given the PR #416 a new search bar with highlight the new search functionality. Updated the look of the search bar: + larger, curved edges + changes color when has focus + search icon built into search - removed "Search For" text in lieu of search icon --- cockatrice/cockatrice.qrc | 1 + cockatrice/resources/icon_search_black.svg | 198 +++++++++++++++++++++ cockatrice/src/tab_deck_editor.cpp | 7 +- cockatrice/src/tab_deck_editor.h | 1 - 4 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 cockatrice/resources/icon_search_black.svg diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index b4d2f05e..34aacb68 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -25,6 +25,7 @@ resources/hand.svg resources/pencil.svg resources/icon_search.svg + resources/icon_search_black.svg resources/icon_clearsearch.svg resources/icon_update.png resources/icon_view.svg diff --git a/cockatrice/resources/icon_search_black.svg b/cockatrice/resources/icon_search_black.svg new file mode 100644 index 00000000..05439a12 --- /dev/null +++ b/cockatrice/resources/icon_search_black.svg @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + \ No newline at end of file diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index 82a356d1..8c4e9e8e 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -51,9 +51,10 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) aClearSearch->setIcon(QIcon(":/resources/icon_clearsearch.svg")); connect(aClearSearch, SIGNAL(triggered()), this, SLOT(actClearSearch())); - searchLabel = new QLabel(); searchEdit = new SearchLineEdit; - searchLabel->setBuddy(searchEdit); + searchEdit->addAction(QIcon(":/resources/icon_search_black.svg"), QLineEdit::LeadingPosition); + searchEdit->setObjectName("searchEdit"); + searchEdit->setStyleSheet("#searchEdit{background:#DFE0E5;border-radius:13px;padding:5px 0px;}#searchEdit:focus{background:#EBEBEB;}"); setFocusProxy(searchEdit); setFocusPolicy(Qt::ClickFocus); @@ -73,7 +74,6 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) QHBoxLayout *searchLayout = new QHBoxLayout; searchLayout->addWidget(deckEditToolBar); - searchLayout->addWidget(searchLabel); searchLayout->addWidget(searchEdit); databaseModel = new CardDatabaseModel(db, this); @@ -293,7 +293,6 @@ void TabDeckEditor::retranslateUi() { aCardTextOnly->setText(tr("Show card text only")); aClearSearch->setText(tr("&Clear search")); - searchLabel->setText(tr("&Search for:")); nameLabel->setText(tr("Deck &name:")); commentsLabel->setText(tr("&Comments:")); diff --git a/cockatrice/src/tab_deck_editor.h b/cockatrice/src/tab_deck_editor.h index dd3b56ac..8db00e73 100644 --- a/cockatrice/src/tab_deck_editor.h +++ b/cockatrice/src/tab_deck_editor.h @@ -85,7 +85,6 @@ private: QTreeView *deckView; KeySignals deckViewKeySignals; CardFrame *cardInfo; - QLabel *searchLabel; SearchLineEdit *searchEdit; KeySignals searchKeySignals; From fc1d06e13b0b51b58129795c67aa18b80cc62f51 Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Mon, 10 Nov 2014 00:23:41 +0100 Subject: [PATCH 02/36] Add fallback urls for cards without a muId set We only have a good HQ source for them; any idea on a low-quality source? --- cockatrice/src/carddatabase.cpp | 14 ++++++++------ cockatrice/src/settingscache.cpp | 14 ++++++++++++++ cockatrice/src/settingscache.h | 8 ++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 25886d18..f34a0725 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -224,16 +224,18 @@ QString PictureLoader::getPicUrl() return picUrl; } - // otherwise, fallback to the default url - picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl(); - picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName())); + // if a card has a muid, use the default url; if not, use the fallback + int muid = set ? muid = card->getMuId(set->getShortName()) : 0; + if(muid) + picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl(); + else + picUrl = picDownloadHq ? settingsCache->getPicUrlHqFallback() : settingsCache->getPicUrlFallback(); + picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName())); + picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(muid))); if (set) { picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName())); picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName())); - int muid = card->getMuId(set->getShortName()); - if (muid) - picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(muid))); } if (picUrl.contains("!name!") || diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 5821d352..8374bdb5 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -25,6 +25,8 @@ SettingsCache::SettingsCache() picDownloadHq = settings->value("personal/picturedownloadhq", false).toBool(); picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString(); picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString(); + picUrlFallback = settings->value("personal/picUrlFallback", PIC_URL_FALLBACK).toString(); + picUrlHqFallback = settings->value("personal/picUrlHqFallback", PIC_URL_HQ_FALLBACK).toString(); mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray(); notificationsEnabled = settings->value("interface/notificationsenabled", true).toBool(); @@ -153,6 +155,18 @@ void SettingsCache::setPicUrlHq(const QString &_picUrlHq) settings->setValue("personal/picUrlHq", picUrlHq); } +void SettingsCache::setPicUrlFallback(const QString &_picUrlFallback) +{ + picUrlFallback = _picUrlFallback; + settings->setValue("personal/picUrlFallback", picUrlFallback); +} + +void SettingsCache::setPicUrlHqFallback(const QString &_picUrlHqFallback) +{ + picUrlHqFallback = _picUrlHqFallback; + settings->setValue("personal/picUrlHqFallback", picUrlHqFallback); +} + void SettingsCache::setNotificationsEnabled(int _notificationsEnabled) { notificationsEnabled = _notificationsEnabled; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index b222a58b..3b1908a9 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -4,7 +4,9 @@ #include #define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card" +#define PIC_URL_FALLBACK "http://mtgimage.com/set/!setcode!/!name!.jpg" #define PIC_URL_HQ_DEFAULT "http://mtgimage.com/multiverseid/!cardid!.jpg" +#define PIC_URL_HQ_FALLBACK "http://mtgimage.com/set/!setcode!/!name!.jpg" class QSettings; @@ -57,6 +59,8 @@ private: bool ignoreUnregisteredUsers; QString picUrl; QString picUrlHq; + QString picUrlFallback; + QString picUrlHqFallback; bool attemptAutoConnect; public: SettingsCache(); @@ -93,6 +97,8 @@ public: bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; } QString getPicUrl() const { return picUrl; } QString getPicUrlHq() const { return picUrlHq; } + QString getPicUrlFallback() const { return picUrlFallback; } + QString getPicUrlHqFallback() const { return picUrlHqFallback; } void copyPath(const QString &src, const QString &dst); bool getAutoConnect() const { return attemptAutoConnect; } public slots: @@ -129,6 +135,8 @@ public slots: void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers); void setPicUrl(const QString &_picUrl); void setPicUrlHq(const QString &_picUrlHq); + void setPicUrlFallback(const QString &_picUrlFallback); + void setPicUrlHqFallback(const QString &_picUrlHqFallback); void setAutoConnect(const bool &_autoConnect); }; From 33a6e3c5c0233f6d8b1ad60d287f10c5c78d5308 Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Mon, 10 Nov 2014 08:49:24 +0100 Subject: [PATCH 03/36] Removed hard coded CSS Hard coded CSS might have a slight chance of not rendering the same across all platforms. More research needs to be performed. Until then I have removed the hard coded search bar customization. --- cockatrice/src/tab_deck_editor.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index 8c4e9e8e..c413d134 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -50,11 +50,10 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) aClearSearch = new QAction(QString(), this); aClearSearch->setIcon(QIcon(":/resources/icon_clearsearch.svg")); connect(aClearSearch, SIGNAL(triggered()), this, SLOT(actClearSearch())); - searchEdit = new SearchLineEdit; searchEdit->addAction(QIcon(":/resources/icon_search_black.svg"), QLineEdit::LeadingPosition); searchEdit->setObjectName("searchEdit"); - searchEdit->setStyleSheet("#searchEdit{background:#DFE0E5;border-radius:13px;padding:5px 0px;}#searchEdit:focus{background:#EBEBEB;}"); + setFocusProxy(searchEdit); setFocusPolicy(Qt::ClickFocus); From 4b478efa61251d350ded6458d4eb5f0fbedd19b9 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Mon, 10 Nov 2014 15:12:45 -0500 Subject: [PATCH 04/36] Build both Qt4 and Qt5 --- .travis.yml | 5 ++++- travis-dependencies.sh | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 74f6feff..7e2bd5fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,13 @@ language: cpp +env: + - QT="-DWITH_QT4=0" + - QT="-DWITH_QT4=1" os: - linux - osx compiler: - gcc - clang -script: mkdir build && cd build && cmake .. -DWITH_SERVER=1 && make +script: mkdir build && cd build && cmake .. $QT -DWITH_SERVER=1 && make install: ./travis-dependencies.sh cache: apt diff --git a/travis-dependencies.sh b/travis-dependencies.sh index 10af11cd..2bfabf6b 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -2,8 +2,8 @@ if [[ $TRAVIS_OS_NAME == "osx" ]] ; then brew update - brew install qt protobuf libgcrypt + brew install qt qt5 protobuf libgcrypt else sudo apt-get update -qq - sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev + sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev qt5-default qttools5-dev-tools fi From a91106f90ec36deb3bd1e27cf833849a5024fa91 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Mon, 10 Nov 2014 15:36:31 -0500 Subject: [PATCH 05/36] Add ppa for qt5 on travis ubuntu --- travis-dependencies.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/travis-dependencies.sh b/travis-dependencies.sh index 2bfabf6b..e4280fd5 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -4,6 +4,8 @@ if [[ $TRAVIS_OS_NAME == "osx" ]] ; then brew update brew install qt qt5 protobuf libgcrypt else + sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa sudo apt-get update -qq - sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev qt5-default qttools5-dev-tools + sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev\ + qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools fi From f58cc32ef45a7cdfcd5a653cb67a08321a58d6f0 Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Mon, 10 Nov 2014 22:14:27 +0100 Subject: [PATCH 06/36] Added version check Added version check, to only include the new Searchbar icon for Users running Qt 5+ --- cockatrice/src/tab_deck_editor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index c413d134..c717d8f3 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -51,7 +51,9 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) aClearSearch->setIcon(QIcon(":/resources/icon_clearsearch.svg")); connect(aClearSearch, SIGNAL(triggered()), this, SLOT(actClearSearch())); searchEdit = new SearchLineEdit; +#if QT_VERSION >= 0x050000 searchEdit->addAction(QIcon(":/resources/icon_search_black.svg"), QLineEdit::LeadingPosition); +#endif searchEdit->setObjectName("searchEdit"); setFocusProxy(searchEdit); From 84a5117b4c7bed6731303578423fbe64817c7546 Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Tue, 11 Nov 2014 14:15:02 -0500 Subject: [PATCH 07/36] Default logging to enable with no config file If no configuration file is found, default the logger to logging enabled. --- servatrice/src/server_logger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index 1a1e4bed..4896852a 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -50,7 +50,7 @@ void ServerLogger::logMessage(QString message, void *caller) callerString = QString::number((qulonglong) caller, 16) + " "; //filter out all log entries based on values in configuration file - bool shouldWeWriteLog = settingsCache->value("server/writelog").toBool(); + bool shouldWeWriteLog = settingsCache->value("server/writelog",1).toBool(); QString logFilters = settingsCache->value("server/logfilters").toString(); QStringList listlogFilters = logFilters.split(",", QString::SkipEmptyParts); bool shouldWeSkipLine = false; From 62b7890e591af60a1ad2e63e828d8bc7066dd219 Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Wed, 12 Nov 2014 23:26:24 +0100 Subject: [PATCH 08/36] Cards Scale with mouse over action Cards now scale up by 10% when mouse over. --- cockatrice/src/abstractcarditem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index 018cc5e0..26359929 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -190,6 +190,8 @@ void AbstractCardItem::setHovered(bool _hovered) processHoverEvent(); isHovered = _hovered; setZValue(_hovered ? 2000000004 : realZValue); + setScale(_hovered ? 1.1 : 1); + setTransformOriginPoint(_hovered ? CARD_WIDTH / 2 : 0, _hovered ? CARD_HEIGHT / 2 : 0); update(); } From 68118191619b26ffa908c86679c51c4db0d61125 Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Thu, 13 Nov 2014 20:31:55 -0500 Subject: [PATCH 09/36] Don't remove card images from revealed decks Revealed library had write access, which meant that the user would see cards being removed from the zone as the other player drew cards. The cards were not the actual ones drawn, just the ones at the same index, so no information was leaked. Fix #297 --- cockatrice/src/player.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 16b77eae..6667d040 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -493,7 +493,6 @@ void Player::playerListActionTriggered() if (menu == mRevealLibrary) { cmd.set_zone_name("deck"); - cmd.set_grant_write_access(true); } else if (menu == mRevealTopCard) { cmd.set_zone_name("deck"); cmd.set_card_id(0); From e918900d4e66020dd9e5fe87b53c5b3755dc73e2 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 14 Nov 2014 10:38:54 -0500 Subject: [PATCH 10/36] Refine travis config to only install qt4 or qt5 per build instead of both --- .travis.yml | 6 +++--- travis-dependencies.sh | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7e2bd5fc..89b71d6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,13 @@ language: cpp env: - - QT="-DWITH_QT4=0" - - QT="-DWITH_QT4=1" + - QT4=1 + - QT4=0 os: - linux - osx compiler: - gcc - clang -script: mkdir build && cd build && cmake .. $QT -DWITH_SERVER=1 && make +script: mkdir build && cd build && cmake .. -DWITH_QT4=$QT4 -DWITH_SERVER=1 && make install: ./travis-dependencies.sh cache: apt diff --git a/travis-dependencies.sh b/travis-dependencies.sh index e4280fd5..39c0e4e4 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -2,10 +2,19 @@ if [[ $TRAVIS_OS_NAME == "osx" ]] ; then brew update - brew install qt qt5 protobuf libgcrypt + if (( QT4 )); then + brew install qt protobuf libgcrypt + else + brew install qt qt5 protobuf libgcrypt + fi else - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - sudo apt-get update -qq - sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev\ - qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools + if (( QT4 )); then + sudo apt-get update -qq + sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev + else + sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa + sudo apt-get update -qq + sudo apt-get install -y libprotobuf-dev protobuf-compiler qtbase5-dev\ + qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools + fi fi From c93fdbefe2e3fbc499fd1a90a05ba7aeccd024fe Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 14 Nov 2014 10:52:39 -0500 Subject: [PATCH 11/36] Update travis build badge link for org change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f67c6fcc..7ce4292e 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Chat with the Cockatrice developers on Gitter. Come here to talk about the appli # Building -[![Build Status](https://travis-ci.org/Daenyth/Cockatrice.svg?branch=master)](https://travis-ci.org/Daenyth/Cockatrice) +[![Build Status](https://travis-ci.org/Cockatrice/Cockatrice.svg?branch=master)](https://travis-ci.org/Cockatrice/Cockatrice) Dependencies: From b351abcce43969aebbd1b025d1c44a7964e6ce28 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 14 Nov 2014 10:54:02 -0500 Subject: [PATCH 12/36] Update gitter chat room for org change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ce4292e..9b88f18d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ a network interface as well. Both client and server are written in Qt, supportin Chat with the Cockatrice developers on Gitter. Come here to talk about the application, features, or just to hang out. For support regarding specific servers, please contact that server's admin or forum for support rather than asking here. -[![Gitter chat](https://badges.gitter.im/Daenyth/Cockatrice.png)](https://gitter.im/Daenyth/Cockatrice) +[![Gitter chat](https://badges.gitter.im/Cockatrice/Cockatrice.png)](https://gitter.im/Cockatrice/Cockatrice) # Building From 5f944f1d6ea57a324fd67a9e554d4e0dd8c6b340 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 14 Nov 2014 16:32:56 -0500 Subject: [PATCH 13/36] Actually use Qt5 for qt5-osx build --- .travis.yml | 2 +- travis-compile.sh | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100755 travis-compile.sh diff --git a/.travis.yml b/.travis.yml index 89b71d6a..28eee8f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,6 @@ os: compiler: - gcc - clang -script: mkdir build && cd build && cmake .. -DWITH_QT4=$QT4 -DWITH_SERVER=1 && make +script: ./travis-compile.sh install: ./travis-dependencies.sh cache: apt diff --git a/travis-compile.sh b/travis-compile.sh new file mode 100755 index 00000000..8da51620 --- /dev/null +++ b/travis-compile.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +mkdir build +cd build +prefix="" +if [[ $TRAVIS_OS_NAME == "osx" && $QT4 == 0 ]]; then + prefix="-DCMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.3.0/" +fi +cmake .. -DWITH_SERVER=1 -DWITH_QT4=$QT4 $prefix +make From fbbe40fbf3d2754dd3e6133d06784fb4002399cb Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 14 Nov 2014 17:11:50 -0500 Subject: [PATCH 14/36] Use correct qt version path for cmake on osx --- travis-compile.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis-compile.sh b/travis-compile.sh index 8da51620..e5058543 100755 --- a/travis-compile.sh +++ b/travis-compile.sh @@ -6,7 +6,7 @@ mkdir build cd build prefix="" if [[ $TRAVIS_OS_NAME == "osx" && $QT4 == 0 ]]; then - prefix="-DCMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.3.0/" + prefix="-DCMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.3.2/" fi cmake .. -DWITH_SERVER=1 -DWITH_QT4=$QT4 $prefix make From a2c4a1e5374e6e8ad87bdf457bbc7aac81d99bca Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Sat, 15 Nov 2014 16:35:30 +0100 Subject: [PATCH 15/36] Action: Move Bottom Card to Graveyard Created menu action to move card from the bottom of the library to the graveyard. Qt accelerator key is "i". #125 --- cockatrice/src/player.cpp | 17 +++++++++++++++++ cockatrice/src/player.h | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index 16b77eae..2aeb6b0e 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -236,6 +236,8 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare connect(aMoveTopCardsToExile, SIGNAL(triggered()), this, SLOT(actMoveTopCardsToExile())); aMoveTopCardToBottom = new QAction(this); connect(aMoveTopCardToBottom, SIGNAL(triggered()), this, SLOT(actMoveTopCardToBottom())); + aMoveBottomCardToGrave = new QAction(this); + connect(aMoveBottomCardToGrave, SIGNAL(triggered()), this, SLOT(actMoveBottomCardToGrave())); } playerMenu = new QMenu(QString()); @@ -271,6 +273,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare libraryMenu->addAction(aMoveTopCardsToGrave); libraryMenu->addAction(aMoveTopCardsToExile); libraryMenu->addAction(aMoveTopCardToBottom); + libraryMenu->addAction(aMoveBottomCardToGrave); deck->setMenu(libraryMenu, aDrawCard); } else { handMenu = 0; @@ -610,6 +613,7 @@ void Player::retranslateUi() aMoveTopCardsToGrave->setText(tr("Move top cards to &graveyard...")); aMoveTopCardsToExile->setText(tr("Move top cards to &exile...")); aMoveTopCardToBottom->setText(tr("Put top card on &bottom")); + aMoveBottomCardToGrave->setText(tr("Put bottom card &in graveyard")); handMenu->setTitle(tr("&Hand")); mRevealHand->setTitle(tr("&Reveal to")); @@ -925,6 +929,19 @@ void Player::actMoveTopCardToBottom() sendGameCommand(cmd); } +void Player::actMoveBottomCardToGrave() { + CardZone *zone = zones.value("deck"); + Command_MoveCard cmd; + cmd.set_start_zone("deck"); + cmd.mutable_cards_to_move()->add_card()->set_card_id(zone->getCards().size() - 1); + cmd.set_target_player_id(getId()); + cmd.set_target_zone("grave"); + cmd.set_x(0); + cmd.set_y(0); + + sendGameCommand(cmd); +} + void Player::actUntapAll() { Command_SetCardAttr cmd; diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index d8396e4d..f0227620 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -120,6 +120,7 @@ public slots: void actMoveTopCardsToGrave(); void actMoveTopCardsToExile(); void actMoveTopCardToBottom(); + void actMoveBottomCardToGrave(); void actViewLibrary(); void actViewTopCards(); @@ -169,7 +170,7 @@ private: *aViewGraveyard, *aViewRfg, *aViewSideboard, *aDrawCard, *aDrawCards, *aUndoDraw, *aMulligan, *aShuffle, *aUntapAll, *aRollDie, *aCreateToken, *aCreateAnotherToken, - *aCardMenu; + *aCardMenu, *aMoveBottomCardToGrave; QList aAddCounter, aSetCounter, aRemoveCounter; QAction *aPlay, From 1640e778483d9ab09127b8e542b4e67a2d8dbda9 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Mon, 17 Nov 2014 11:29:20 -0500 Subject: [PATCH 16/36] Notify gitter about build changes --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 28eee8f1..dfceb213 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,3 +11,10 @@ compiler: script: ./travis-compile.sh install: ./travis-dependencies.sh cache: apt +notifications: + webhooks: + urls: + - https://webhooks.gitter.im/e/d94969c3b01b22cbdcb7 + on_success: change + on_failure: change + on_start: false From d2e706164d03706b2f1f69510bc7c3841b4e1cd5 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Tue, 18 Nov 2014 06:08:56 -0500 Subject: [PATCH 17/36] Install qt5tools-dev for ubuntu build --- travis-dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis-dependencies.sh b/travis-dependencies.sh index 39c0e4e4..fc5b15ff 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -15,6 +15,6 @@ else sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa sudo apt-get update -qq sudo apt-get install -y libprotobuf-dev protobuf-compiler qtbase5-dev\ - qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools + qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools qttools5-dev fi fi From 1ba6b468de7ae274fda421eb9e9321624d7f4504 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Tue, 18 Nov 2014 07:48:55 -0500 Subject: [PATCH 18/36] Install updated cmake from ubuntu sdk ppa --- travis-dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis-dependencies.sh b/travis-dependencies.sh index fc5b15ff..4acb972d 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -14,7 +14,7 @@ else else sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa sudo apt-get update -qq - sudo apt-get install -y libprotobuf-dev protobuf-compiler qtbase5-dev\ + sudo apt-get install -y libprotobuf-dev protobuf-compiler qtbase5-dev cmake\ qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools qttools5-dev fi fi From d467cc8b01055125b84cf273bd620345e679f213 Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Tue, 18 Nov 2014 18:14:47 +0100 Subject: [PATCH 19/36] QT_VERSION check now checks for correct version Feature is only included in Qt 5.3+ --- cockatrice/src/tab_deck_editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index c717d8f3..01520acf 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -51,7 +51,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) aClearSearch->setIcon(QIcon(":/resources/icon_clearsearch.svg")); connect(aClearSearch, SIGNAL(triggered()), this, SLOT(actClearSearch())); searchEdit = new SearchLineEdit; -#if QT_VERSION >= 0x050000 +#if QT_VERSION >= 0x050300 searchEdit->addAction(QIcon(":/resources/icon_search_black.svg"), QLineEdit::LeadingPosition); #endif searchEdit->setObjectName("searchEdit"); From ee2ba4abd3d5f8ea0a07b0a46a5b2086ef51fa64 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Tue, 18 Nov 2014 12:18:30 -0500 Subject: [PATCH 20/36] Include qtmultimedia and qtsvg for travis qt5 build --- travis-dependencies.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/travis-dependencies.sh b/travis-dependencies.sh index 4acb972d..6d9c9afc 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -15,6 +15,7 @@ else sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa sudo apt-get update -qq sudo apt-get install -y libprotobuf-dev protobuf-compiler qtbase5-dev cmake\ - qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools qttools5-dev + qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools\ + qttools5-dev qtmultimedia5-dev libqt5svg5-dev fi fi From b4dc9b79d4398e9f3b520a171bc02945c01f69de Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Tue, 18 Nov 2014 12:41:08 -0500 Subject: [PATCH 21/36] Don't install qt4 when building qt5 on osx --- travis-dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis-dependencies.sh b/travis-dependencies.sh index 6d9c9afc..5878b513 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -5,7 +5,7 @@ if [[ $TRAVIS_OS_NAME == "osx" ]] ; then if (( QT4 )); then brew install qt protobuf libgcrypt else - brew install qt qt5 protobuf libgcrypt + brew install qt5 protobuf libgcrypt fi else if (( QT4 )); then From 141d0c7618b36a2bbd85b3a449985875ae3753a5 Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Fri, 21 Nov 2014 00:09:38 +0100 Subject: [PATCH 22/36] Added fade to card drag items [REVIEW] Added a white mask to cards that are being dragged. Preview: http://webmup.com/1we4W/ --- cockatrice/src/abstractcarddragitem.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cockatrice/src/abstractcarddragitem.cpp b/cockatrice/src/abstractcarddragitem.cpp index acc73532..35476941 100644 --- a/cockatrice/src/abstractcarddragitem.cpp +++ b/cockatrice/src/abstractcarddragitem.cpp @@ -3,9 +3,11 @@ #include #include #include +#include static const float CARD_WIDTH_HALF = CARD_WIDTH / 2; static const float CARD_HEIGHT_HALF = CARD_HEIGHT / 2; +const QColor GHOST_MASK = QColor(255, 255, 255, 50); AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag) : QGraphicsItem(), item(_item), hotSpot(_hotSpot) @@ -40,6 +42,9 @@ AbstractCardDragItem::~AbstractCardDragItem() void AbstractCardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { item->paint(painter, option, widget); + + // adds a mask to the card so it looks like the card hasnt been placed yet + painter->fillRect(boundingRect(), GHOST_MASK); } void AbstractCardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) From 7e92b4e7df027164b8c4f5521a0978d59e770fa3 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 21 Nov 2014 11:19:58 -0500 Subject: [PATCH 23/36] Add community resource links to README ref #452 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 9b88f18d..f66459cd 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,11 @@ The following flags can be passed to `cmake`: `cockatrice` is the game client `servatrice` is the server +# Community Resources +- [reddit r/Cockatrice](http://reddit.com/r/cockatrice) +- [Woogerworks Server & Forums](http://woogerworks.com) +- [Cockatrice Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki) + # License Cockatrice is free software, licensed under the GPLv2; see COPYING for details. From 8c7aa41721b41618861b19943b224e577c01a721 Mon Sep 17 00:00:00 2001 From: Gavin Bisesi Date: Fri, 21 Nov 2014 12:15:12 -0500 Subject: [PATCH 24/36] Permit linux/clang/qt5 build to fail --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index dfceb213..a1c468ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,3 +18,9 @@ notifications: on_success: change on_failure: change on_start: false +matrix: + fast_finish: true + allow_failures: + - compiler: clang + os: linux + env: QT4=0 From 93ab9f969183e2642708a395f68d5373343811bd Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Sun, 16 Nov 2014 21:12:14 -0800 Subject: [PATCH 25/36] Add 'Start time' column to game list --- CMakeLists.txt | 4 +- cockatrice/src/carddatabase.cpp | 2 +- cockatrice/src/gameselector.cpp | 11 ++-- cockatrice/src/gamesmodel.cpp | 110 ++++++++++++++++++++++++-------- cockatrice/src/gamesmodel.h | 18 +++++- 5 files changed, 109 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cf8857a..350fb149 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,9 +79,9 @@ ELSEIF (CMAKE_COMPILER_IS_GNUCXX) include(CheckCXXCompilerFlag) set(CMAKE_CXX_FLAGS_RELEASE "-s -O2") - set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror") + set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic") - set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations) + set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-inline) FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS}) CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG}) diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index f34a0725..5336b5b3 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -225,7 +225,7 @@ QString PictureLoader::getPicUrl() } // if a card has a muid, use the default url; if not, use the fallback - int muid = set ? muid = card->getMuId(set->getShortName()) : 0; + int muid = set ? card->getMuId(set->getShortName()) : 0; if(muid) picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl(); else diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 25bf2ebd..f858a129 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -27,16 +27,17 @@ GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSup gameListProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); gameListView->setModel(gameListProxyModel); gameListView->setSortingEnabled(true); + gameListView->sortByColumn(gameListModel->startTimeColIndex(), Qt::AscendingOrder); gameListView->setAlternatingRowColors(true); gameListView->setRootIsDecorated(true); if (_room) - gameListView->header()->hideSection(1); + gameListView->header()->hideSection(gameListModel->roomColIndex()); else gameListProxyModel->setUnavailableGamesVisible(true); #if QT_VERSION < 0x050000 - gameListView->header()->setResizeMode(1, QHeaderView::ResizeToContents); + gameListView->header()->setResizeMode(0, QHeaderView::ResizeToContents); #else - gameListView->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + gameListView->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); #endif filterButton = new QPushButton; filterButton->setIcon(QIcon(":/resources/icon_search.svg")); @@ -53,7 +54,7 @@ GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSup createButton = 0; joinButton = new QPushButton; spectateButton = new QPushButton; - + QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addWidget(filterButton); buttonLayout->addWidget(clearFilterButton); @@ -63,7 +64,7 @@ GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSup buttonLayout->addWidget(joinButton); buttonLayout->addWidget(spectateButton); buttonLayout->setAlignment(Qt::AlignTop); - + QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(gameListView); mainLayout->addLayout(buttonLayout); diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index df0ec880..17900834 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -1,6 +1,52 @@ #include "gamesmodel.h" #include "pb/serverinfo_game.pb.h" #include +#include +#include + +namespace { + const unsigned SECS_PER_HALF_MIN = 30; + const unsigned SECS_PER_MIN = 60; + const unsigned SECS_PER_HALF_HOUR = 1600; // 60 * 30 + const unsigned SECS_PER_HOUR = 3600; // 60 * 60 + const unsigned SECS_PER_DAY = 86400; // 60 * 60 * 24 + + /** + * Pretty print an integer number of seconds ago. Accurate to only one unit, + * rounded. + * + * For example... + * 0-59 seconds will return "X seconds ago" + * 1-59 minutes will return "X minutes ago"; 90 seconds will return "2 minutes ago" + * 1-23 hours will return "X hours ago"; 90 minutes will return "2 hours ago" + * 24+ hours will return "1+ days ago", because it seems unlikely that we care about + * an accurate timestamp of day old games. + */ + std::string prettyPrintSecsAgo(uint32_t secs) { + std::ostringstream str_stream; + + if (secs < SECS_PER_MIN) { + str_stream << secs; + str_stream << "s ago"; + } else if (secs < SECS_PER_HOUR) { + uint32_t mins = secs / SECS_PER_MIN; + if (secs % SECS_PER_MIN >= SECS_PER_HALF_MIN) + mins++; + str_stream << mins; + str_stream << "m ago"; + } else if (secs < SECS_PER_DAY) { + uint32_t hours = secs / SECS_PER_HOUR; + if (secs % SECS_PER_HOUR >= SECS_PER_HALF_HOUR) + hours++; + str_stream << hours; + str_stream << "h ago"; + } else { + str_stream << "a long time ago"; + } + + return str_stream.str(); + } +} GamesModel::GamesModel(const QMap &_rooms, const QMap &_gameTypes, QObject *parent) : QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes) @@ -13,25 +59,36 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const return QVariant(); if (role == Qt::UserRole) return index.row(); - if (role != Qt::DisplayRole) + if (role != Qt::DisplayRole && role != SORT_ROLE) return QVariant(); if ((index.row() >= gameList.size()) || (index.column() >= columnCount())) return QVariant(); - + const ServerInfo_Game &g = gameList[index.row()]; switch (index.column()) { - case 0: return QString::fromStdString(g.description()); - case 1: return rooms.value(g.room_id()); - case 2: return QString::fromStdString(g.creator_info().name()); - case 3: { + case 0: return rooms.value(g.room_id()); + case 1: { + uint32_t now = time(NULL); + uint32_t then = g.start_time(); + int secs = now - then; + + switch (role) { + case Qt::DisplayRole: return QString::fromStdString(prettyPrintSecsAgo(secs)); + case SORT_ROLE: return QVariant(secs); + default: return QVariant(); // Shouldn't ever be reached. + } + } + case 2: return QString::fromStdString(g.description()); + case 3: return QString::fromStdString(g.creator_info().name()); + case 4: { QStringList result; GameTypeMap gameTypeMap = gameTypes.value(g.room_id()); for (int i = g.game_types_size() - 1; i >= 0; --i) result.append(gameTypeMap.value(g.game_types(i))); return result.join(", "); } - case 4: return g.with_password() ? ((g.spectators_need_password() || !g.spectators_allowed()) ? tr("yes") : tr("yes, free for spectators")) : tr("no"); - case 5: { + case 5: return g.with_password() ? ((g.spectators_need_password() || !g.spectators_allowed()) ? tr("yes") : tr("yes, free for spectators")) : tr("no"); + case 6: { QStringList result; if (g.only_buddies()) result.append(tr("buddies only")); @@ -39,8 +96,8 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const result.append(tr("reg. users only")); return result.join(", "); } - case 6: return QString("%1/%2").arg(g.player_count()).arg(g.max_players()); - case 7: return g.spectators_allowed() ? QVariant(g.spectators_count()) : QVariant(tr("not allowed")); + case 7: return QString("%1/%2").arg(g.player_count()).arg(g.max_players()); + case 8: return g.spectators_allowed() ? QVariant(g.spectators_count()) : QVariant(tr("not allowed")); default: return QVariant(); } } @@ -50,14 +107,15 @@ 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("Room"); - 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"); + case 0: return tr("Room"); + case 1: return tr("Start time"); + case 2: return tr("Description"); + case 3: return tr("Creator"); + case 4: return tr("Game type"); + case 5: return tr("Password"); + case 6: return tr("Restrictions"); + case 7: return tr("Players"); + case 8: return tr("Spectators"); default: return QVariant(); } } @@ -70,7 +128,7 @@ const ServerInfo_Game &GamesModel::getGame(int row) void GamesModel::updateGameList(const ServerInfo_Game &game) { - for (int i = 0; i < gameList.size(); i++) + for (int i = 0; i < gameList.size(); i++) { if (gameList[i].game_id() == game.game_id()) { if (game.closed()) { beginRemoveRows(QModelIndex(), i, i); @@ -78,10 +136,11 @@ void GamesModel::updateGameList(const ServerInfo_Game &game) endRemoveRows(); } else { gameList[i].MergeFrom(game); - emit dataChanged(index(i, 0), index(i, 7)); + emit dataChanged(index(i, 0), index(i, NUM_COLS-1)); } return; } + } if (game.player_count() <= 0) return; beginInsertRows(QModelIndex(), gameList.size(), gameList.size()); @@ -97,6 +156,7 @@ GamesProxyModel::GamesProxyModel(QObject *parent, ServerInfo_User *_ownUser) maxPlayersFilterMin(-1), maxPlayersFilterMax(-1) { + setSortRole(GamesModel::SORT_ROLE); setDynamicSortFilter(true); } @@ -146,7 +206,7 @@ void GamesProxyModel::resetFilterParameters() gameTypeFilter.clear(); maxPlayersFilterMin = -1; maxPlayersFilterMax = -1; - + invalidateFilter(); } @@ -155,7 +215,7 @@ bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &/*sourc GamesModel *model = qobject_cast(sourceModel()); if (!model) return false; - + const ServerInfo_Game &game = model->getGame(sourceRow); if (!unavailableGamesVisible) { if (game.player_count() == game.max_players()) @@ -174,17 +234,17 @@ bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &/*sourc if (!creatorNameFilter.isEmpty()) if (!QString::fromStdString(game.creator_info().name()).contains(creatorNameFilter, Qt::CaseInsensitive)) return false; - + QSet gameTypes; for (int i = 0; i < game.game_types_size(); ++i) gameTypes.insert(game.game_types(i)); if (!gameTypeFilter.isEmpty() && gameTypes.intersect(gameTypeFilter).isEmpty()) return false; - + if ((maxPlayersFilterMin != -1) && ((int)game.max_players() < maxPlayersFilterMin)) return false; if ((maxPlayersFilterMax != -1) && ((int)game.max_players() > maxPlayersFilterMax)) return false; - + return true; } diff --git a/cockatrice/src/gamesmodel.h b/cockatrice/src/gamesmodel.h index aeb37e95..85432cf1 100644 --- a/cockatrice/src/gamesmodel.h +++ b/cockatrice/src/gamesmodel.h @@ -16,15 +16,27 @@ private: QList gameList; QMap rooms; QMap gameTypes; + + static const int NUM_COLS = 9; public: + static const int SORT_ROLE = Qt::UserRole+1; + GamesModel(const QMap &_rooms, const QMap &_gameTypes, QObject *parent = 0); int rowCount(const QModelIndex &parent = QModelIndex()) const { return parent.isValid() ? 0 : gameList.size(); } - int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return 8; } + int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const { return NUM_COLS; } QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - + const ServerInfo_Game &getGame(int row); + + /** + * Update game list with a (possibly new) game. + */ void updateGameList(const ServerInfo_Game &game); + + int roomColIndex() { return 0; } + int startTimeColIndex() { return 1; } + const QMap &getGameTypes() { return gameTypes; } }; @@ -39,7 +51,7 @@ private: int maxPlayersFilterMin, maxPlayersFilterMax; public: GamesProxyModel(QObject *parent = 0, ServerInfo_User *_ownUser = 0); - + bool getUnavailableGamesVisible() const { return unavailableGamesVisible; } void setUnavailableGamesVisible(bool _unavailableGamesVisible); bool getPasswordProtectedGamesVisible() const { return passwordProtectedGamesVisible; } From 4972d227d9c16e97c22310294faed17e747f09c6 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Mon, 17 Nov 2014 10:19:34 -0800 Subject: [PATCH 26/36] Add back -Werror, etc. on debug build --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 350fb149..4cf8857a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,9 +79,9 @@ ELSEIF (CMAKE_COMPILER_IS_GNUCXX) include(CheckCXXCompilerFlag) set(CMAKE_CXX_FLAGS_RELEASE "-s -O2") - set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic") + set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror") - set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-inline) + set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations) FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS}) CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG}) From a3dc403f75e0007c456c45d9eb7fe9bea226e326 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Mon, 17 Nov 2014 10:28:15 -0800 Subject: [PATCH 27/36] Translate, change 'Start time' to 'Game created', add debug log --- cockatrice/src/gamesmodel.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 17900834..da177fbe 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -1,5 +1,6 @@ #include "gamesmodel.h" #include "pb/serverinfo_game.pb.h" +#include #include #include #include @@ -12,7 +13,7 @@ namespace { const unsigned SECS_PER_DAY = 86400; // 60 * 60 * 24 /** - * Pretty print an integer number of seconds ago. Accurate to only one unit, + * Pretty print an integer number of seconds ago. Accurate to only one unit, * rounded. * * For example... @@ -34,17 +35,17 @@ namespace { mins++; str_stream << mins; str_stream << "m ago"; - } else if (secs < SECS_PER_DAY) { + } else if (secs < SECS_PER_HOUR * 5) { uint32_t hours = secs / SECS_PER_HOUR; if (secs % SECS_PER_HOUR >= SECS_PER_HALF_HOUR) hours++; str_stream << hours; - str_stream << "h ago"; + str_stream << "hr ago"; } else { - str_stream << "a long time ago"; + str_stream << "5+ hours ago"; } - return str_stream.str(); + return tr(str_stream.str()); } } @@ -75,7 +76,10 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const switch (role) { case Qt::DisplayRole: return QString::fromStdString(prettyPrintSecsAgo(secs)); case SORT_ROLE: return QVariant(secs); - default: return QVariant(); // Shouldn't ever be reached. + default: { + qDebug() << "Returning data for col 1 of games model when role != display, role != sort"; + return QVariant(); // Shouldn't ever be reached. + } } } case 2: return QString::fromStdString(g.description()); @@ -108,7 +112,7 @@ QVariant GamesModel::headerData(int section, Qt::Orientation orientation, int ro return QVariant(); switch (section) { case 0: return tr("Room"); - case 1: return tr("Start time"); + case 1: return tr("Game created"); case 2: return tr("Description"); case 3: return tr("Creator"); case 4: return tr("Game type"); From 7aff20b4ee849281b71ea63c85440a6cb8c2825a Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Mon, 17 Nov 2014 10:35:54 -0800 Subject: [PATCH 28/36] Fix the build --- cockatrice/src/gamesmodel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index da177fbe..95d02c06 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -23,7 +23,7 @@ namespace { * 24+ hours will return "1+ days ago", because it seems unlikely that we care about * an accurate timestamp of day old games. */ - std::string prettyPrintSecsAgo(uint32_t secs) { + QString prettyPrintSecsAgo(uint32_t secs) { std::ostringstream str_stream; if (secs < SECS_PER_MIN) { @@ -45,7 +45,7 @@ namespace { str_stream << "5+ hours ago"; } - return tr(str_stream.str()); + return QObject::tr(str_stream.str().c_str()); } } @@ -74,7 +74,7 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const int secs = now - then; switch (role) { - case Qt::DisplayRole: return QString::fromStdString(prettyPrintSecsAgo(secs)); + case Qt::DisplayRole: return prettyPrintSecsAgo(secs); case SORT_ROLE: return QVariant(secs); default: { qDebug() << "Returning data for col 1 of games model when role != display, role != sort"; From da145bdd7b5d53f2f69aa5959af8654f54f3cd00 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Mon, 17 Nov 2014 10:45:37 -0800 Subject: [PATCH 29/36] fix localization in time strings --- cockatrice/src/gamesmodel.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 95d02c06..3c84ad3b 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -10,7 +10,6 @@ namespace { const unsigned SECS_PER_MIN = 60; const unsigned SECS_PER_HALF_HOUR = 1600; // 60 * 30 const unsigned SECS_PER_HOUR = 3600; // 60 * 60 - const unsigned SECS_PER_DAY = 86400; // 60 * 60 * 24 /** * Pretty print an integer number of seconds ago. Accurate to only one unit, @@ -24,28 +23,22 @@ namespace { * an accurate timestamp of day old games. */ QString prettyPrintSecsAgo(uint32_t secs) { - std::ostringstream str_stream; - if (secs < SECS_PER_MIN) { - str_stream << secs; - str_stream << "s ago"; - } else if (secs < SECS_PER_HOUR) { + return QString::number(secs).append(QObject::tr("s ago")); + } + if (secs < SECS_PER_HOUR) { uint32_t mins = secs / SECS_PER_MIN; if (secs % SECS_PER_MIN >= SECS_PER_HALF_MIN) mins++; - str_stream << mins; - str_stream << "m ago"; - } else if (secs < SECS_PER_HOUR * 5) { + return QString::number(mins).append(QObject::tr("m ago")); + } + if (secs < SECS_PER_HOUR * 5) { uint32_t hours = secs / SECS_PER_HOUR; if (secs % SECS_PER_HOUR >= SECS_PER_HALF_HOUR) hours++; - str_stream << hours; - str_stream << "hr ago"; - } else { - str_stream << "5+ hours ago"; + return QString::number(hours).append(QObject::tr("hr ago")); } - - return QObject::tr(str_stream.str().c_str()); + return QObject::tr("5+ hours ago"); } } From d0969c10c63815eab4c03ab47c5a559ce5ec1025 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Mon, 17 Nov 2014 20:38:52 -0800 Subject: [PATCH 30/36] Show hours and minutes between 60 and 90 minutes --- cockatrice/src/gamesmodel.cpp | 46 ++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 3c84ad3b..af09ea73 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -6,39 +6,61 @@ #include namespace { - const unsigned SECS_PER_HALF_MIN = 30; const unsigned SECS_PER_MIN = 60; - const unsigned SECS_PER_HALF_HOUR = 1600; // 60 * 30 - const unsigned SECS_PER_HOUR = 3600; // 60 * 60 + const unsigned SECS_PER_HALF_HOUR = 60 * 30; + const unsigned SECS_PER_HOUR = 60 * 60; + const unsigned SECS_PER_90_MINS = 60 * 90; /** * Pretty print an integer number of seconds ago. Accurate to only one unit, - * rounded. + * rounded. As a special case, time between 60 and 90 minutes will display + * both the hours and minutes. * * For example... - * 0-59 seconds will return "X seconds ago" - * 1-59 minutes will return "X minutes ago"; 90 seconds will return "2 minutes ago" - * 1-23 hours will return "X hours ago"; 90 minutes will return "2 hours ago" - * 24+ hours will return "1+ days ago", because it seems unlikely that we care about - * an accurate timestamp of day old games. + * 0-59 seconds will return "Xs ago" + * 1-59 minutes will return "Xm ago"; 90 seconds will return "2m ago" + * 60-90 minutes will return "Xhr Ym ago" + * 91-300 minutes will return "Xhr ago"; 91 minutes will return "2hr ago" + * 300+ minutes will return "5+ hr ago", because it seems unlikely that we + * care about an accurate timestamp of old games. */ QString prettyPrintSecsAgo(uint32_t secs) { if (secs < SECS_PER_MIN) { + //: This will have a number prepended, like "10s ago" return QString::number(secs).append(QObject::tr("s ago")); } if (secs < SECS_PER_HOUR) { uint32_t mins = secs / SECS_PER_MIN; - if (secs % SECS_PER_MIN >= SECS_PER_HALF_MIN) + if (secs % SECS_PER_MIN >= 30) mins++; + //: This will have a number prepended, like "10m ago" return QString::number(mins).append(QObject::tr("m ago")); - } + } + // Here, we want to display both the hours and minutes. + // + // There are two small "corner" cases which could be rectified with + // some more knotty iffy-elsey code: + // Between 1:00:00 and 1:00:29 will display "1hr 0m ago" + // Between 1:29:30 and 1:29:59 will display "1hr 31m ago" + // + // Personally, I prefer to keep the code cleaner, and allow these. + if (secs < SECS_PER_90_MINS) { + uint32_t mins = secs / SECS_PER_MIN - 60; + if (secs % SECS_PER_MIN >= 30) + mins++; + return QObject::tr("1hr ") + .append(QString::number(mins)) + //: This will have a number prepended, like "5m ago" + .append(QObject::tr("m ago")); + } if (secs < SECS_PER_HOUR * 5) { uint32_t hours = secs / SECS_PER_HOUR; if (secs % SECS_PER_HOUR >= SECS_PER_HALF_HOUR) hours++; + //: This will have a number prepended, like "2h ago" return QString::number(hours).append(QObject::tr("hr ago")); } - return QObject::tr("5+ hours ago"); + return QObject::tr("5+ hrs ago"); } } From 0af70883a8bd96deca5f5681d89b14728901fdec Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Mon, 17 Nov 2014 20:57:28 -0800 Subject: [PATCH 31/36] 0s-5m displayed as '<5m ago' --- cockatrice/src/gamesmodel.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index af09ea73..6bf32d35 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -6,28 +6,24 @@ #include namespace { - const unsigned SECS_PER_MIN = 60; - const unsigned SECS_PER_HALF_HOUR = 60 * 30; - const unsigned SECS_PER_HOUR = 60 * 60; - const unsigned SECS_PER_90_MINS = 60 * 90; + const unsigned SECS_PER_MIN = 60; + const unsigned SECS_PER_HOUR = 60 * 60; /** * Pretty print an integer number of seconds ago. Accurate to only one unit, - * rounded. As a special case, time between 60 and 90 minutes will display - * both the hours and minutes. + * rounded; <5 minutes and >5 hours are displayed as such. As a special case, + * time between 60 and 90 minutes will display both the hours and minutes. * * For example... - * 0-59 seconds will return "Xs ago" - * 1-59 minutes will return "Xm ago"; 90 seconds will return "2m ago" + * 0-300 seconds will return "<5m ago" + * 5-59 minutes will return "Xm ago" * 60-90 minutes will return "Xhr Ym ago" - * 91-300 minutes will return "Xhr ago"; 91 minutes will return "2hr ago" - * 300+ minutes will return "5+ hr ago", because it seems unlikely that we - * care about an accurate timestamp of old games. + * 91-300 minutes will return "Xhr ago" + * 300+ minutes will return "5+ hr ago" */ QString prettyPrintSecsAgo(uint32_t secs) { - if (secs < SECS_PER_MIN) { - //: This will have a number prepended, like "10s ago" - return QString::number(secs).append(QObject::tr("s ago")); + if (secs < SECS_PER_MIN * 5) { + return QObject::tr("<5m ago"); } if (secs < SECS_PER_HOUR) { uint32_t mins = secs / SECS_PER_MIN; @@ -44,7 +40,7 @@ namespace { // Between 1:29:30 and 1:29:59 will display "1hr 31m ago" // // Personally, I prefer to keep the code cleaner, and allow these. - if (secs < SECS_PER_90_MINS) { + if (secs < SECS_PER_MIN * 90) { uint32_t mins = secs / SECS_PER_MIN - 60; if (secs % SECS_PER_MIN >= 30) mins++; @@ -55,7 +51,7 @@ namespace { } if (secs < SECS_PER_HOUR * 5) { uint32_t hours = secs / SECS_PER_HOUR; - if (secs % SECS_PER_HOUR >= SECS_PER_HALF_HOUR) + if (secs % SECS_PER_HOUR >= SECS_PER_MIN * 30) hours++; //: This will have a number prepended, like "2h ago" return QString::number(hours).append(QObject::tr("hr ago")); From 03bdbe2c7a58f92c42f6f17aa73623ed28eaea19 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Sat, 22 Nov 2014 00:08:00 -0800 Subject: [PATCH 32/36] Added '<1m ago' --- cockatrice/src/gamesmodel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 6bf32d35..57c2988f 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -22,6 +22,9 @@ namespace { * 300+ minutes will return "5+ hr ago" */ QString prettyPrintSecsAgo(uint32_t secs) { + if (secs < SECS_PER_MIN) { + return QObject::tr("<1m ago"); + } if (secs < SECS_PER_MIN * 5) { return QObject::tr("<5m ago"); } From cab37b39452eb14cbed3e64a07fc01429d8f4d70 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Sat, 22 Nov 2014 00:08:47 -0800 Subject: [PATCH 33/36] Capitalize game columns --- cockatrice/src/gamesmodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index 57c2988f..77e2f7f5 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -126,10 +126,10 @@ QVariant GamesModel::headerData(int section, Qt::Orientation orientation, int ro return QVariant(); switch (section) { case 0: return tr("Room"); - case 1: return tr("Game created"); + case 1: return tr("Game Created"); case 2: return tr("Description"); case 3: return tr("Creator"); - case 4: return tr("Game type"); + case 4: return tr("Game Type"); case 5: return tr("Password"); case 6: return tr("Restrictions"); case 7: return tr("Players"); From 6a44855a5cdc819ca9046fb81b61a7209792df1e Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Sun, 23 Nov 2014 00:36:50 +0100 Subject: [PATCH 34/36] Added double click to join a room Can now double click on a room in the lobby to join --- cockatrice/src/gameselector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 25bf2ebd..475768da 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -76,6 +76,7 @@ GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSup connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); + connect(gameListView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actJoin())); } void GameSelector::actSetFilter() From 9e349d8b886cc94de1cdf0a37b8827e162088c7b Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Sun, 23 Nov 2014 00:46:54 +0100 Subject: [PATCH 35/36] Added "ENTER" to join a room Can now join a room by highlighting a room and pressing ENTER. Works nice with arrow navigation. --- cockatrice/src/gameselector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 475768da..eef42706 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -77,6 +77,7 @@ GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSup connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); connect(spectateButton, SIGNAL(clicked()), this, SLOT(actJoin())); connect(gameListView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actJoin())); + connect(gameListView, SIGNAL(activated(const QModelIndex &)), this, SLOT(actJoin())); } void GameSelector::actSetFilter() From bbcfe84d088775897544d9db019cb81853b936c5 Mon Sep 17 00:00:00 2001 From: Matt Lowe Date: Sun, 23 Nov 2014 20:01:09 +0100 Subject: [PATCH 36/36] Added double click/Enter for Server tab Added the same functionality to the server tab --- cockatrice/src/tab_server.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cockatrice/src/tab_server.cpp b/cockatrice/src/tab_server.cpp index b82248a3..4fba193b 100644 --- a/cockatrice/src/tab_server.cpp +++ b/cockatrice/src/tab_server.cpp @@ -52,6 +52,8 @@ RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent) setLayout(vbox); connect(client, SIGNAL(listRoomsEventReceived(const Event_ListRooms &)), this, SLOT(processListRoomsEvent(const Event_ListRooms &))); + connect(roomList, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(joinClicked())); + connect(roomList, SIGNAL(activated(const QModelIndex &)), this, SLOT(joinClicked())); client->sendCommand(client->prepareSessionCommand(Command_ListRooms())); }