Merge branch 'master' into set_extinfo
This commit is contained in:
commit
2704523c73
20 changed files with 440 additions and 54 deletions
18
.travis.yml
18
.travis.yml
|
@ -1,10 +1,26 @@
|
|||
language: cpp
|
||||
env:
|
||||
- QT4=1
|
||||
- QT4=0
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
script: mkdir build && cd build && cmake .. -DWITH_SERVER=1 && make
|
||||
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
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- compiler: clang
|
||||
os: linux
|
||||
env: QT4=0
|
||||
|
|
|
@ -9,11 +9,11 @@ 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.
|
||||
|
||||
[](https://gitter.im/Daenyth/Cockatrice)
|
||||
[](https://gitter.im/Cockatrice/Cockatrice)
|
||||
|
||||
# Building
|
||||
|
||||
[](https://travis-ci.org/Daenyth/Cockatrice)
|
||||
[](https://travis-ci.org/Cockatrice/Cockatrice)
|
||||
|
||||
Dependencies:
|
||||
|
||||
|
@ -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.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<file>resources/hand.svg</file>
|
||||
<file>resources/pencil.svg</file>
|
||||
<file>resources/icon_search.svg</file>
|
||||
<file>resources/icon_search_black.svg</file>
|
||||
<file>resources/icon_clearsearch.svg</file>
|
||||
<file>resources/icon_update.png</file>
|
||||
<file>resources/icon_view.svg</file>
|
||||
|
|
198
cockatrice/resources/icon_search_black.svg
Normal file
198
cockatrice/resources/icon_search_black.svg
Normal file
|
@ -0,0 +1,198 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64"
|
||||
height="64"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="icon_search_black.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3709">
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3711" />
|
||||
<stop
|
||||
style="stop-color:#4d4d4d;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3713" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3699">
|
||||
<stop
|
||||
style="stop-color:#ececec;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3701" />
|
||||
<stop
|
||||
style="stop-color:#ececec;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3703" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3632">
|
||||
<stop
|
||||
style="stop-color:#c87137;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3634" />
|
||||
<stop
|
||||
style="stop-color:#c87137;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3636" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3622">
|
||||
<stop
|
||||
style="stop-color:#f9f9f9;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3624" />
|
||||
<stop
|
||||
style="stop-color:#f9f9f9;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3626" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3622"
|
||||
id="linearGradient3628"
|
||||
x1="30.59761"
|
||||
y1="8.9243031"
|
||||
x2="30.59761"
|
||||
y2="21.545816"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3632"
|
||||
id="linearGradient3638"
|
||||
x1="28.430279"
|
||||
y1="47.808765"
|
||||
x2="29.960159"
|
||||
y2="47.808765"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<inkscape:perspective
|
||||
id="perspective3685"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3699"
|
||||
id="linearGradient3705"
|
||||
x1="29.215645"
|
||||
y1="1021.9559"
|
||||
x2="31.852083"
|
||||
y2="1021.9559"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3709"
|
||||
id="linearGradient3715"
|
||||
x1="22.288248"
|
||||
y1="35.505978"
|
||||
x2="49.488647"
|
||||
y2="49.106178"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3632"
|
||||
id="linearGradient3730"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="28.430279"
|
||||
y1="47.808765"
|
||||
x2="29.960159"
|
||||
y2="47.808765" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3699"
|
||||
id="linearGradient3732"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="29.215645"
|
||||
y1="1021.9559"
|
||||
x2="31.852083"
|
||||
y2="1021.9559" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.84375"
|
||||
inkscape:cx="6.0725518"
|
||||
inkscape:cy="32"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g3717"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-988.36218)">
|
||||
<g
|
||||
id="g3717"
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,729.31175,279.31708)">
|
||||
<path
|
||||
transform="matrix(1.7216859,0,0,1.7216859,-37.751505,955.72849)"
|
||||
d="m 49.338646,35.505978 a 13.450199,13.450199 0 1 1 -26.900398,0 13.450199,13.450199 0 1 1 26.900398,0 z"
|
||||
sodipodi:ry="13.450199"
|
||||
sodipodi:rx="13.450199"
|
||||
sodipodi:cy="35.505978"
|
||||
sodipodi:cx="35.888447"
|
||||
id="path2816"
|
||||
style="fill:#222326;fill-opacity:0;stroke:#222326;stroke-width:1.90745997;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(-0.08671958,-1.1164509,1.1164509,-0.08671958,2.9138372,1039.7631)"
|
||||
d="m 18.613546,52.207172 a 2.5498009,12.302789 0 1 1 -5.099601,0 2.5498009,12.302789 0 1 1 5.099601,0 z"
|
||||
sodipodi:ry="12.302789"
|
||||
sodipodi:rx="2.5498009"
|
||||
sodipodi:cy="52.207172"
|
||||
sodipodi:cx="16.063745"
|
||||
id="path2826"
|
||||
style="fill:#222326;fill-opacity:1;stroke:#222326;stroke-width:0.30000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
|
@ -3,9 +3,11 @@
|
|||
#include <QCursor>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
|
||||
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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -227,16 +227,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 ? 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!") ||
|
||||
|
|
|
@ -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);
|
||||
|
@ -76,6 +77,8 @@ 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()
|
||||
|
|
|
@ -1,6 +1,67 @@
|
|||
#include "gamesmodel.h"
|
||||
#include "pb/serverinfo_game.pb.h"
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <sstream>
|
||||
#include <time.h>
|
||||
|
||||
namespace {
|
||||
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; <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-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"
|
||||
* 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");
|
||||
}
|
||||
if (secs < SECS_PER_HOUR) {
|
||||
uint32_t mins = secs / SECS_PER_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_MIN * 90) {
|
||||
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_MIN * 30)
|
||||
hours++;
|
||||
//: This will have a number prepended, like "2h ago"
|
||||
return QString::number(hours).append(QObject::tr("hr ago"));
|
||||
}
|
||||
return QObject::tr("5+ hrs ago");
|
||||
}
|
||||
}
|
||||
|
||||
GamesModel::GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_gameTypes, QObject *parent)
|
||||
: QAbstractTableModel(parent), rooms(_rooms), gameTypes(_gameTypes)
|
||||
|
@ -13,25 +74,39 @@ 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 prettyPrintSecsAgo(secs);
|
||||
case SORT_ROLE: return QVariant(secs);
|
||||
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());
|
||||
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 +114,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 +125,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("Game Created");
|
||||
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 +146,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 +154,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 +174,7 @@ GamesProxyModel::GamesProxyModel(QObject *parent, ServerInfo_User *_ownUser)
|
|||
maxPlayersFilterMin(-1),
|
||||
maxPlayersFilterMax(-1)
|
||||
{
|
||||
setSortRole(GamesModel::SORT_ROLE);
|
||||
setDynamicSortFilter(true);
|
||||
}
|
||||
|
||||
|
@ -146,7 +224,7 @@ void GamesProxyModel::resetFilterParameters()
|
|||
gameTypeFilter.clear();
|
||||
maxPlayersFilterMin = -1;
|
||||
maxPlayersFilterMax = -1;
|
||||
|
||||
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
@ -155,7 +233,7 @@ bool GamesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &/*sourc
|
|||
GamesModel *model = qobject_cast<GamesModel *>(sourceModel());
|
||||
if (!model)
|
||||
return false;
|
||||
|
||||
|
||||
const ServerInfo_Game &game = model->getGame(sourceRow);
|
||||
if (!unavailableGamesVisible) {
|
||||
if (game.player_count() == game.max_players())
|
||||
|
@ -174,17 +252,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<int> 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;
|
||||
}
|
||||
|
|
|
@ -16,15 +16,27 @@ private:
|
|||
QList<ServerInfo_Game> gameList;
|
||||
QMap<int, QString> rooms;
|
||||
QMap<int, GameTypeMap> gameTypes;
|
||||
|
||||
static const int NUM_COLS = 9;
|
||||
public:
|
||||
static const int SORT_ROLE = Qt::UserRole+1;
|
||||
|
||||
GamesModel(const QMap<int, QString> &_rooms, const QMap<int, GameTypeMap> &_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<int, GameTypeMap> &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; }
|
||||
|
|
|
@ -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;
|
||||
|
@ -493,7 +496,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);
|
||||
|
@ -610,6 +612,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 +928,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;
|
||||
|
|
|
@ -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<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
|
||||
QAction *aPlay,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#include <QObject>
|
||||
|
||||
#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);
|
||||
};
|
||||
|
||||
|
|
|
@ -50,10 +50,12 @@ 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()));
|
||||
|
||||
searchLabel = new QLabel();
|
||||
searchEdit = new SearchLineEdit;
|
||||
searchLabel->setBuddy(searchEdit);
|
||||
#if QT_VERSION >= 0x050300
|
||||
searchEdit->addAction(QIcon(":/resources/icon_search_black.svg"), QLineEdit::LeadingPosition);
|
||||
#endif
|
||||
searchEdit->setObjectName("searchEdit");
|
||||
|
||||
setFocusProxy(searchEdit);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
||||
|
@ -73,7 +75,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 +294,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:"));
|
||||
|
|
|
@ -85,7 +85,6 @@ private:
|
|||
QTreeView *deckView;
|
||||
KeySignals deckViewKeySignals;
|
||||
CardFrame *cardInfo;
|
||||
QLabel *searchLabel;
|
||||
SearchLineEdit *searchEdit;
|
||||
KeySignals searchKeySignals;
|
||||
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
12
travis-compile.sh
Executable file
12
travis-compile.sh
Executable file
|
@ -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.2/"
|
||||
fi
|
||||
cmake .. -DWITH_SERVER=1 -DWITH_QT4=$QT4 $prefix
|
||||
make
|
|
@ -2,8 +2,20 @@
|
|||
|
||||
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
|
||||
brew update
|
||||
brew install qt protobuf libgcrypt
|
||||
if (( QT4 )); then
|
||||
brew install qt protobuf libgcrypt
|
||||
else
|
||||
brew install qt5 protobuf libgcrypt
|
||||
fi
|
||||
else
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev
|
||||
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 cmake\
|
||||
qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev qt5-default qttools5-dev-tools\
|
||||
qttools5-dev qtmultimedia5-dev libqt5svg5-dev
|
||||
fi
|
||||
fi
|
||||
|
|
Loading…
Reference in a new issue